]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Mar 2011 14:50:45 +0000 (07:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Mar 2011 14:50:45 +0000 (07:50 -0700)
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (65 commits)
  ARM: 6826/1: Merge v6 and v7 DEBUG_LL DCC support
  ARM: 6838/1: etm: fix section mismatch warning
  ARM: 6837/1: remove unused pci_fixup_prpmc1100
  ARM: 6836/1: kprobes/fix emulation of LDR/STR instruction when Rn == PC
  Fix the broken build for Marvell Dove platform.
  ARM: 6835/1: perf: ensure overflows aren't missed due to IRQ latency
  ARM: 6834/1: perf: reset counters on all CPUs during initialisation
  ARM: 6833/1: perf: add required isbs() to ARMv7 backend
  ARM: 6825/1: kernel/sleep.S: fix Thumb2 compilation issues
  ARM: 6807/1: realview: Fix secondary GIC initialisation for EB with MPCore tile
  arm: mach-mx3: pcm043: add write-protect and card-detect for SD1
  eukrea_mbimxsd51: add SD Card detect
  eukrea_mbimxsd25-baseboard: add SD card detect
  mx3/eukrea_mbimxsd-baseboard: add SD card detect support
  mx3/eukrea_mbimxsd-baseboard: fix gpio request
  ARM: mxs/mx28evk: add mmc device
  ARM: mxs/mx23evk: add mmc device
  ARM: mxs: dynamically allocate mmc device
  ARM: mx51_efika: update platform data for new mfd changes
  mx2/iomux: Set direction for CSPI2 pins
  ...

826 files changed:
Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
Documentation/ABI/testing/sysfs-driver-samsung-laptop [new file with mode: 0644]
Documentation/ABI/testing/sysfs-platform-asus-wmi [new file with mode: 0644]
Documentation/ABI/testing/sysfs-platform-eeepc-wmi [deleted file]
Documentation/DocBook/Makefile
Documentation/DocBook/rapidio.tmpl
Documentation/development-process/1.Intro
Documentation/development-process/2.Process
Documentation/development-process/3.Early-stage
Documentation/development-process/4.Coding
Documentation/development-process/5.Posting
Documentation/development-process/6.Followthrough
Documentation/development-process/7.AdvancedTopics
Documentation/dynamic-debug-howto.txt
Documentation/hwmon/f71882fg
Documentation/laptops/sony-laptop.txt
MAINTAINERS
Makefile
arch/alpha/Kconfig
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/irq_i8259.c
arch/alpha/kernel/irq_pyxis.c
arch/alpha/kernel/irq_srm.c
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_jensen.c
arch/alpha/kernel/sys_marvel.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_titan.c
arch/alpha/kernel/sys_wildfire.c
arch/arm/Kconfig
arch/arm/common/gic.c
arch/arm/common/it8152.c
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/common/vic.c
arch/arm/include/asm/hw_irq.h
arch/arm/kernel/ecard.c
arch/arm/kernel/irq.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/at572d940hf.h
arch/arm/mach-at91/irq.c
arch/arm/mach-bcmring/irq.c
arch/arm/mach-clps711x/irq.c
arch/arm/mach-davinci/cp_intc.c
arch/arm/mach-davinci/gpio.c
arch/arm/mach-davinci/irq.c
arch/arm/mach-dove/irq.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ep93xx/gpio.c
arch/arm/mach-exynos4/Kconfig
arch/arm/mach-exynos4/Makefile
arch/arm/mach-exynos4/include/mach/debug-macro.S
arch/arm/mach-exynos4/irq-combiner.c
arch/arm/mach-exynos4/irq-eint.c
arch/arm/mach-exynos4/mach-smdkc210.c
arch/arm/mach-exynos4/mach-smdkv310.c
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/isa-irq.c
arch/arm/mach-gemini/gpio.c
arch/arm/mach-gemini/irq.c
arch/arm/mach-h720x/common.c
arch/arm/mach-h720x/cpu-h7202.c
arch/arm/mach-iop13xx/irq.c
arch/arm/mach-iop13xx/msi.c
arch/arm/mach-iop32x/irq.c
arch/arm/mach-iop33x/irq.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/ixdp2x00.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/coyote-pci.c
arch/arm/mach-ixp4xx/dsmg600-pci.c
arch/arm/mach-ixp4xx/fsg-pci.c
arch/arm/mach-ixp4xx/gateway7001-pci.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdpg425-pci.c
arch/arm/mach-ixp4xx/nas100d-pci.c
arch/arm/mach-ixp4xx/nslu2-pci.c
arch/arm/mach-ixp4xx/vulcan-pci.c
arch/arm/mach-ixp4xx/wg302v2-pci.c
arch/arm/mach-kirkwood/irq.c
arch/arm/mach-ks8695/gpio.c
arch/arm/mach-ks8695/irq.c
arch/arm/mach-lpc32xx/irq.c
arch/arm/mach-mmp/irq-mmp2.c
arch/arm/mach-mmp/irq-pxa168.c
arch/arm/mach-msm/board-msm8960.c
arch/arm/mach-msm/board-msm8x60.c
arch/arm/mach-msm/board-trout-gpio.c
arch/arm/mach-msm/board-trout-mmc.c
arch/arm/mach-msm/gpio-v2.c
arch/arm/mach-msm/gpio.c
arch/arm/mach-msm/irq-vic.c
arch/arm/mach-msm/irq.c
arch/arm/mach-msm/sirc.c
arch/arm/mach-mv78xx0/irq.c
arch/arm/mach-mx3/mach-mx31ads.c
arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
arch/arm/mach-mxs/gpio.c
arch/arm/mach-mxs/icoll.c
arch/arm/mach-netx/generic.c
arch/arm/mach-ns9xxx/board-a9m9750dev.c
arch/arm/mach-ns9xxx/include/mach/board.h
arch/arm/mach-ns9xxx/include/mach/module.h
arch/arm/mach-ns9xxx/irq.c
arch/arm/mach-nuc93x/irq.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/fpga.c
arch/arm/mach-omap1/irq.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/omap_l3_smx.c
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/irq.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/terastation_pro2-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-pnx4008/irq.c
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/cm-x2xx-pci.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-rpc/irq.c
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2412/irq.c
arch/arm/mach-s3c2416/irq.c
arch/arm/mach-s3c2440/irq.c
arch/arm/mach-s3c2440/s3c244x-irq.c
arch/arm/mach-s3c2443/irq.c
arch/arm/mach-s3c64xx/irq-eint.c
arch/arm/mach-s5p64x0/cpu.c
arch/arm/mach-s5pv210/include/mach/irqs.h
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/irq.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-shark/irq.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-g4evm.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/intc-sh7367.c
arch/arm/mach-shmobile/intc-sh7372.c
arch/arm/mach-shmobile/intc-sh7377.c
arch/arm/mach-tcc8k/irq.c
arch/arm/mach-tegra/gpio.c
arch/arm/mach-tegra/irq.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-regulators.c
arch/arm/mach-ux500/board-mop500-regulators.h
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
arch/arm/mach-ux500/modem-irq-db5500.c
arch/arm/mach-versatile/core.c
arch/arm/mach-vt8500/irq.c
arch/arm/mach-w90x900/irq.c
arch/arm/plat-mxc/3ds_debugboard.c
arch/arm/plat-mxc/avic.c
arch/arm/plat-mxc/gpio.c
arch/arm/plat-mxc/irq-common.c
arch/arm/plat-mxc/tzic.c
arch/arm/plat-nomadik/gpio.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/onenand.h
arch/arm/plat-orion/gpio.c
arch/arm/plat-orion/irq.c
arch/arm/plat-pxa/gpio.c
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
arch/arm/plat-s3c24xx/irq.c
arch/arm/plat-s5p/cpu.c
arch/arm/plat-s5p/irq-eint.c
arch/arm/plat-s5p/irq-gpioint.c
arch/arm/plat-samsung/init.c
arch/arm/plat-samsung/irq-uart.c
arch/arm/plat-samsung/irq-vic-timer.c
arch/arm/plat-samsung/wakeup-mask.c
arch/arm/plat-spear/shirq.c
arch/arm/plat-stmp3xxx/irq.c
arch/arm/plat-stmp3xxx/pinmux.c
arch/arm/plat-versatile/fpga-irq.c
arch/blackfin/kernel/irqchip.c
arch/blackfin/kernel/trace.c
arch/blackfin/mach-bf561/smp.c
arch/blackfin/mach-common/ints-priority.c
arch/cris/Kconfig
arch/cris/arch-v10/drivers/axisflashmap.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/Makefile
arch/cris/arch-v32/drivers/axisflashmap.c
arch/cris/arch-v32/drivers/pcf8563.c [deleted file]
arch/frv/Kconfig
arch/frv/include/asm/system.h
arch/frv/include/asm/thread_info.h
arch/frv/kernel/irq-mb93091.c
arch/frv/kernel/irq-mb93093.c
arch/frv/kernel/irq-mb93493.c
arch/frv/kernel/irq.c
arch/ia64/Kconfig
arch/ia64/hp/sim/hpsim_irq.c
arch/ia64/include/asm/hw_irq.h
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/irq_lsapic.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/msi_ia64.c
arch/ia64/kernel/smpboot.c
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/xen/irq_xen.c
arch/m68k/kernel/irq.c
arch/m68k/platform/5249/intc2.c
arch/m68k/platform/5272/intc.c
arch/m68k/platform/68328/ints.c
arch/m68k/platform/68360/ints.c
arch/m68k/platform/coldfire/intc-2.c
arch/m68k/platform/coldfire/intc-simr.c
arch/m68k/platform/coldfire/intc.c
arch/microblaze/Kconfig
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/irq.c
arch/microblaze/pci/pci-common.c
arch/mips/alchemy/devboards/bcsr.c
arch/mips/alchemy/devboards/db1200/setup.c
arch/mips/alchemy/devboards/db1x00/board_setup.c
arch/mips/alchemy/devboards/pb1000/board_setup.c
arch/mips/alchemy/devboards/pb1100/board_setup.c
arch/mips/alchemy/devboards/pb1200/board_setup.c
arch/mips/alchemy/devboards/pb1500/board_setup.c
arch/mips/alchemy/devboards/pb1550/board_setup.c
arch/mips/alchemy/mtx-1/board_setup.c
arch/mips/alchemy/xxs1500/board_setup.c
arch/mips/ar7/irq.c
arch/mips/ath79/irq.c
arch/mips/bcm63xx/irq.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/dec/ioasic-irq.c
arch/mips/dec/kn02-irq.c
arch/mips/emma/markeins/irq.c
arch/mips/include/asm/mach-cavium-octeon/irq.h
arch/mips/include/asm/octeon/octeon.h
arch/mips/include/asm/unistd.h
arch/mips/jazz/irq.c
arch/mips/jz4740/gpio.c
arch/mips/jz4740/irq.c
arch/mips/kernel/i8259.c
arch/mips/kernel/irq-gic.c
arch/mips/kernel/irq-gt641xx.c
arch/mips/kernel/irq-msc01.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/irq_txx9.c
arch/mips/kernel/smtc.c
arch/mips/lasat/interrupt.c
arch/mips/loongson/common/bonito-irq.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-time.c
arch/mips/pci/msi-octeon.c
arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
arch/mips/pmc-sierra/msp71xx/msp_smp.c
arch/mips/pnx833x/common/interrupts.c
arch/mips/pnx8550/common/int.c
arch/mips/powertv/asic/irq_asic.c
arch/mips/rb532/irq.c
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/sb1250/irq.c
arch/mips/sni/a20r.c
arch/mips/sni/pcimt.c
arch/mips/sni/pcit.c
arch/mips/sni/rm200.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/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/icu.c
arch/mips/vr41xx/common/irq.c
arch/mn10300/Kconfig
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/smp.c
arch/mn10300/unit-asb2364/irq-fpga.c
arch/parisc/kernel/irq.c
arch/powerpc/Kconfig
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
arch/powerpc/platforms/52xx/media5200.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
arch/powerpc/platforms/85xx/ksi8560.c
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
arch/powerpc/platforms/85xx/stx_gp3.c
arch/powerpc/platforms/85xx/tqm85xx.c
arch/powerpc/platforms/86xx/gef_pic.c
arch/powerpc/platforms/86xx/pic.c
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/cell/Kconfig
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/beat_interrupt.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/embedded6xx/flipper-pic.c
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/iseries/irq.c
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/cpm1.c
arch/powerpc/sysdev/cpm2_pic.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/i8259.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/mpc8xx_pic.c
arch/powerpc/sysdev/mpc8xxx_gpio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_pasemi_msi.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/mv64x60_pic.c
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/tsi108_pci.c
arch/powerpc/sysdev/uic.c
arch/powerpc/sysdev/xilinx_intc.c
arch/score/Kconfig
arch/score/include/asm/irqflags.h
arch/score/kernel/irq.c
arch/sh/boards/board-magicpanelr2.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-cayman/irq.c
arch/sh/boards/mach-dreamcast/irq.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-kfr2r09/setup.c
arch/sh/boards/mach-microdev/irq.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7206/irq.c
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7724/irq.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/boards/mach-x3proto/gpio.c
arch/sh/cchips/hd6446x/hd64461.c
arch/sh/kernel/cpu/irq/imask.c
arch/sh/kernel/cpu/irq/intc-sh5.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sparc/Kconfig
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/pci_msi.c
arch/tile/Kconfig
arch/tile/kernel/irq.c
arch/unicore32/Kconfig
arch/unicore32/kernel/irq.c
arch/x86/crypto/aesni-intel_asm.S
arch/x86/crypto/aesni-intel_glue.c
arch/x86/include/asm/percpu.h
arch/x86/lib/cmpxchg16b_emu.S
arch/x86/platform/olpc/olpc-xo1.c
arch/x86/xen/p2m.c
drivers/acpi/video.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_rb532_cf.c
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/block/cciss_scsi.c
drivers/block/drbd/drbd_actlog.c
drivers/block/drbd/drbd_bitmap.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_proc.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_strings.c
drivers/block/drbd/drbd_worker.c
drivers/block/drbd/drbd_wrappers.h
drivers/char/tpm/tpm.c
drivers/dma/ipu/ipu_irq.c
drivers/edac/amd64_edac.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/ab8500-gpio.c [new file with mode: 0644]
drivers/hwmon/Kconfig
drivers/hwmon/f71882fg.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/pmbus_core.c
drivers/hwspinlock/Kconfig
drivers/ide/ide-io.c
drivers/input/keyboard/lm8323.c
drivers/input/serio/ams_delta_serio.c
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/input/touchscreen/zylonite-wm97xx.c
drivers/md/md.c
drivers/memstick/host/r592.c
drivers/mfd/88pm860x-core.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab3550-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-i2c.c
drivers/mfd/asic3.c
drivers/mfd/cs5535-mfd.c
drivers/mfd/ezx-pcap.c
drivers/mfd/htc-egpio.c
drivers/mfd/htc-i2cpld.c
drivers/mfd/jz4740-adc.c
drivers/mfd/max8925-core.c
drivers/mfd/max8997-irq.c [new file with mode: 0644]
drivers/mfd/max8998-irq.c
drivers/mfd/max8998.c
drivers/mfd/mfd-core.c
drivers/mfd/pcf50633-core.c
drivers/mfd/rdc321x-southbridge.c
drivers/mfd/sh_mobile_sdhi.c [deleted file]
drivers/mfd/stmpe.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc3589x.c
drivers/mfd/tc6393xb.c
drivers/mfd/tps6586x.c
drivers/mfd/twl4030-irq.c
drivers/mfd/twl6030-irq.c
drivers/mfd/wl1273-core.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm8350-irq.c
drivers/mfd/wm8994-irq.c
drivers/misc/sgi-gru/grufile.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/sd_ops.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmci.c
drivers/mmc/host/of_mmc_spi.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.h
drivers/mmc/host/sdhci-spear.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mobile_sdhi.c [new file with mode: 0644]
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/tmio_mmc.h [new file with mode: 0644]
drivers/mmc/host/tmio_mmc_dma.c [new file with mode: 0644]
drivers/mmc/host/tmio_mmc_pio.c [new file with mode: 0644]
drivers/mmc/host/via-sdmmc.c
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/ceiva.c
drivers/mtd/maps/integrator-flash.c
drivers/mtd/maps/latch-addr-flash.c [new file with mode: 0644]
drivers/mtd/maps/physmap.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/maps/ts5500_flash.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdswap.c [new file with mode: 0644]
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_bch.c [new file with mode: 0644]
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/onenand/omap2.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/sm_ftl.c
drivers/mtd/tests/mtd_speedtest.c
drivers/mtd/tests/mtd_subpagetest.c
drivers/net/bfin_mac.c
drivers/net/bnx2.c
drivers/net/can/c_can/c_can.c
drivers/net/can/c_can/c_can_platform.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/dm9000.c
drivers/net/jme.c
drivers/net/ksz884x.c
drivers/net/mlx4/en_netdev.c
drivers/net/myri10ge/myri10ge.c
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/qlcnic/qlcnic_ethtool.c
drivers/net/s2io.c
drivers/net/tg3.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vxge/vxge-ethtool.c
drivers/net/wireless/p54/p54spi.c
drivers/net/wireless/wl1251/sdio.c
drivers/net/wireless/wl1251/spi.c
drivers/parisc/eisa.c
drivers/parisc/gsc.c
drivers/parisc/superio.c
drivers/pci/dmar.c
drivers/pci/htirq.c
drivers/pci/intel-iommu.c
drivers/pci/intr_remapping.c
drivers/pci/msi.c
drivers/pcmcia/bfin_cf_pcmcia.c
drivers/pcmcia/db1xxx_ss.c
drivers/pcmcia/sa1100_nanoengine.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/xxs1500_ss.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-nb-wmi.c [new file with mode: 0644]
drivers/platform/x86/asus-wmi.c [new file with mode: 0644]
drivers/platform/x86/asus-wmi.h [new file with mode: 0644]
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-wmi-aio.c [new file with mode: 0644]
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_mid_powerbtn.c [new file with mode: 0644]
drivers/platform/x86/intel_mid_thermal.c [new file with mode: 0644]
drivers/platform/x86/intel_pmic_gpio.c
drivers/platform/x86/intel_rar_register.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/samsung-laptop.c [new file with mode: 0644]
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/xo15-ebook.c [new file with mode: 0644]
drivers/power/z2_battery.c
drivers/regulator/Kconfig
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/core.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/rtc/rtc-sh.c
drivers/sh/intc/core.c
drivers/sh/intc/virq.c
drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/serial/msm_serial_hs.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/musb/tusb6010.c
drivers/vlynq/vlynq.c
drivers/w1/masters/ds1wm.c
drivers/watchdog/davinci_wdt.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/nv_tco.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/softdog.c
drivers/watchdog/sp5100_tco.c
drivers/xen/events.c
drivers/xen/gntdev.c
fs/btrfs/btrfs_inode.h
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-ref.c
fs/btrfs/dir-item.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-cache.h
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/relocation.c
fs/btrfs/root-tree.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/btrfs/xattr.c
fs/ceph/addr.c
fs/ceph/snap.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/ecryptfs/read_write.c
fs/ecryptfs/super.c
fs/inode.c
fs/jffs2/xattr.c
fs/nfs/namespace.c
fs/nfs/nfs4state.c
fs/nfs/pagelist.c
fs/nfs/write.c
fs/ocfs2/acl.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/buffer_head_io.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/cluster/tcp.c
fs/ocfs2/dcache.c
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmconvert.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmlock.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmunlock.c
fs/ocfs2/dlmglue.c
fs/ocfs2/export.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/ocfs2/heartbeat.c
fs/ocfs2/inode.c
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/localalloc.c
fs/ocfs2/locks.c
fs/ocfs2/mmap.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_trace.h [new file with mode: 0644]
fs/ocfs2/quota_global.c
fs/ocfs2/quota_local.c
fs/ocfs2/refcounttree.c
fs/ocfs2/reservations.c
fs/ocfs2/resize.c
fs/ocfs2/slot_map.c
fs/ocfs2/suballoc.c
fs/ocfs2/super.c
fs/ocfs2/symlink.c
fs/ocfs2/sysfile.c
fs/ocfs2/uptodate.c
fs/ocfs2/xattr.c
fs/proc/task_mmu.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.h
include/linux/bch.h [new file with mode: 0644]
include/linux/can/core.h
include/linux/drbd.h
include/linux/drbd_limits.h
include/linux/drbd_nl.h
include/linux/drbd_tag_magic.h
include/linux/ethtool.h
include/linux/fs.h
include/linux/input.h
include/linux/irq.h
include/linux/irqdesc.h
include/linux/mfd/ab8500.h
include/linux/mfd/ab8500/gpio.h [new file with mode: 0644]
include/linux/mfd/core.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8997.h
include/linux/mfd/sh_mobile_sdhi.h [deleted file]
include/linux/mmc/sh_mobile_sdhi.h [new file with mode: 0644]
include/linux/mmc/tmio.h [new file with mode: 0644]
include/linux/mtd/blktrans.h
include/linux/mtd/cfi.h
include/linux/mtd/latch-addr-flash.h [new file with mode: 0644]
include/linux/mtd/nand.h
include/linux/mtd/nand_bch.h [new file with mode: 0644]
include/linux/mtd/onenand.h
include/linux/nfs_page.h
include/linux/regulator/ab8500.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h
include/linux/skbuff.h
include/linux/sonypi.h
include/linux/vmalloc.h
include/net/dst.h
include/net/rose.h
include/net/xfrm.h
include/sound/pcm.h
include/trace/events/btrfs.h [new file with mode: 0644]
ipc/util.c
kernel/irq/Kconfig
kernel/irq/autoprobe.c
kernel/irq/chip.c
kernel/irq/compat.h [deleted file]
kernel/irq/debug.h
kernel/irq/dummychip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/irq/migration.c
kernel/irq/proc.c
kernel/irq/resend.c
kernel/irq/settings.h
kernel/irq/spurious.c
kernel/signal.c
lib/Kconfig
lib/Makefile
lib/bch.c [new file with mode: 0644]
mm/memory.c
mm/nommu.c
mm/percpu.c
net/bridge/br_if.c
net/bridge/br_private.h
net/bridge/br_stp_if.c
net/can/af_can.c
net/can/bcm.c
net/can/raw.c
net/core/dev.c
net/core/ethtool.c
net/ipv4/fib_trie.c
net/ipv4/ip_options.c
net/ipv4/raw.c
net/ipv6/ip6mr.c
net/irda/iriap.c
net/irda/irnet/irnet_ppp.c
net/rose/af_rose.c
net/rose/rose_loopback.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/sunrpc/sched.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
security/selinux/ss/services.c
sound/core/init.c
sound/core/pcm_native.c
sound/oss/dev_table.h
sound/oss/midi_synth.c
sound/oss/midi_synth.h
sound/oss/opl3.c
sound/oss/sequencer.c
sound/pci/asihpi/asihpi.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_realtek.c
sound/usb/quirks-table.h

index 4f29e5f1ebfa5b19cd7851e6148b80219911e9c2..f5bb0a3bb8c0d5d18bdcfdd2bf8ce70765ed4dc5 100644 (file)
@@ -59,3 +59,15 @@ Kernel Version: 2.6.31
 Contact:       iss_storagedev@hp.com
 Description:   Displays the usage count (number of opens) of logical drive Y
                of controller X.
+
+Where:         /sys/bus/pci/devices/<dev>/ccissX/resettable
+Date:          February 2011
+Kernel Version:        2.6.38
+Contact:       iss_storagedev@hp.com
+Description:   Value of 1 indicates the controller can honor the reset_devices
+               kernel parameter.  Value of 0 indicates reset_devices cannot be
+               honored.  This is to allow, for example, kexec tools to be able
+               to warn the user if they designate an unresettable device as
+               a dump device, as kdump requires resetting the device in order
+               to work reliably.
+
diff --git a/Documentation/ABI/testing/sysfs-driver-samsung-laptop b/Documentation/ABI/testing/sysfs-driver-samsung-laptop
new file mode 100644 (file)
index 0000000..0a81023
--- /dev/null
@@ -0,0 +1,19 @@
+What:          /sys/devices/platform/samsung/performance_level
+Date:          January 1, 2010
+KernelVersion: 2.6.33
+Contact:       Greg Kroah-Hartman <gregkh@suse.de>
+Description:   Some Samsung laptops have different "performance levels"
+               that are can be modified by a function key, and by this
+               sysfs file.  These values don't always make a whole lot
+               of sense, but some users like to modify them to keep
+               their fans quiet at all costs.  Reading from this file
+               will show the current performance level.  Writing to the
+               file can change this value.
+                       Valid options:
+                               "silent"
+                               "normal"
+                               "overclock"
+               Note that not all laptops support all of these options.
+               Specifically, not all support the "overclock" option,
+               and it's still unknown if this value even changes
+               anything, other than making the user feel a bit better.
diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi
new file mode 100644 (file)
index 0000000..2e7df91
--- /dev/null
@@ -0,0 +1,31 @@
+What:          /sys/devices/platform/<platform>/cpufv
+Date:          Oct 2010
+KernelVersion: 2.6.37
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Change CPU clock configuration (write-only).
+               There are three available clock configuration:
+                   * 0 -> Super Performance Mode
+                   * 1 -> High Performance Mode
+                   * 2 -> Power Saving Mode
+
+What:          /sys/devices/platform/<platform>/camera
+Date:          Jan 2010
+KernelVersion: 2.6.39
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Control the camera. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/<platform>/cardr
+Date:          Jan 2010
+KernelVersion: 2.6.39
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Control the card reader. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/<platform>/touchpad
+Date:          Jan 2010
+KernelVersion: 2.6.39
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Control the card touchpad. 1 means on, 0 means off.
diff --git a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
deleted file mode 100644 (file)
index e4b5fef..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-What:          /sys/devices/platform/eeepc-wmi/cpufv
-Date:          Oct 2010
-KernelVersion: 2.6.37
-Contact:       "Corentin Chary" <corentincj@iksaif.net>
-Description:
-               Change CPU clock configuration (write-only).
-               There are three available clock configuration:
-                   * 0 -> Super Performance Mode
-                   * 1 -> High Performance Mode
-                   * 2 -> Power Saving Mode
index 2deb069aedf1e9a99e8264f545a56f9f3b9b112f..8436b018c289cbc1c858dc8722d92a5f48389b5b 100644 (file)
@@ -55,7 +55,6 @@ mandocs: $(MAN)
 build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
               cp $(srctree)/Documentation/DocBook/dvb/*.png \
                  $(srctree)/Documentation/DocBook/v4l/*.gif \
-                 $(srctree)/Documentation/DocBook/v4l/*.png \
                  $(objtree)/Documentation/DocBook/media/
 
 xmldoclinks:
index 54eb26b573720e21a85a4181000b603de4678fcb..50479360d84590640c0dd6deba02935a295239fb 100644 (file)
 !Idrivers/rapidio/rio-sysfs.c
      </sect1>
      <sect1 id="PPC32_support"><title>PPC32 support</title>
-!Earch/powerpc/sysdev/fsl_rio.c
 !Iarch/powerpc/sysdev/fsl_rio.c
      </sect1>
   </chapter>
index 8cc2cba2b10d39b5a090fbdd468f3e3c3f3f01b4..9b614480aa84a3a8dba599b61ab39ea03bf2f374 100644 (file)
@@ -56,13 +56,13 @@ information on kernel development.
 
 1.2: WHAT THIS DOCUMENT IS ABOUT
 
-The Linux kernel, at over 6 million lines of code and well over 1000 active
-contributors, is one of the largest and most active free software projects
-in existence.  Since its humble beginning in 1991, this kernel has evolved
-into a best-of-breed operating system component which runs on pocket-sized
-digital music players, desktop PCs, the largest supercomputers in
-existence, and all types of systems in between.  It is a robust, efficient,
-and scalable solution for almost any situation.
+The Linux kernel, at over 8 million lines of code and well over 1000
+contributors to each release, is one of the largest and most active free
+software projects in existence.  Since its humble beginning in 1991, this
+kernel has evolved into a best-of-breed operating system component which
+runs on pocket-sized digital music players, desktop PCs, the largest
+supercomputers in existence, and all types of systems in between.  It is a
+robust, efficient, and scalable solution for almost any situation.
 
 With the growth of Linux has come an increase in the number of developers
 (and companies) wishing to participate in its development.  Hardware
@@ -115,7 +115,7 @@ This document was written by Jonathan Corbet, corbet@lwn.net.  It has been
 improved by comments from Johannes Berg, James Berry, Alex Chiang, Roland
 Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
 Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and
-Jochen Voß. 
+Jochen Voß.
 
 This work was supported by the Linux Foundation; thanks especially to
 Amanda McPherson, who saw the value of this effort and made it all happen.
@@ -221,7 +221,7 @@ include:
 - Everything that was said above about code review applies doubly to
   closed-source code.  Since this code is not available at all, it cannot
   have been reviewed by the community and will, beyond doubt, have serious
-  problems. 
+  problems.
 
 Makers of embedded systems, in particular, may be tempted to disregard much
 of what has been said in this section in the belief that they are shipping
index 911a4518634048d9098a02865d328c18824c8248..4823577c65092f967ef3d46eb024fa8a1366ab7e 100644 (file)
@@ -14,16 +14,15 @@ The kernel developers use a loosely time-based release process, with a new
 major kernel release happening every two or three months.  The recent
 release history looks like this:
 
-       2.6.26  July 13, 2008
-       2.6.25  April 16, 2008
-       2.6.24  January 24, 2008
-       2.6.23  October 9, 2007
-       2.6.22  July 8, 2007
-       2.6.21  April 25, 2007
-       2.6.20  February 4, 2007
+       2.6.38  March 14, 2011
+       2.6.37  January 4, 2011
+       2.6.36  October 20, 2010
+       2.6.35  August 1, 2010
+       2.6.34  May 15, 2010
+       2.6.33  February 24, 2010
 
 Every 2.6.x release is a major kernel release with new features, internal
-API changes, and more.  A typical 2.6 release can contain over 10,000
+API changes, and more.  A typical 2.6 release can contain nearly 10,000
 changesets with changes to several hundred thousand lines of code.  2.6 is
 thus the leading edge of Linux kernel development; the kernel uses a
 rolling development model which is continually integrating major changes.
@@ -42,13 +41,13 @@ merge window do not come out of thin air; they have been collected, tested,
 and staged ahead of time.  How that process works will be described in
 detail later on).
 
-The merge window lasts for two weeks.  At the end of this time, Linus
-Torvalds will declare that the window is closed and release the first of
-the "rc" kernels.  For the kernel which is destined to be 2.6.26, for
-example, the release which happens at the end of the merge window will be
-called 2.6.26-rc1.  The -rc1 release is the signal that the time to merge
-new features has passed, and that the time to stabilize the next kernel has
-begun.
+The merge window lasts for approximately two weeks.  At the end of this
+time, Linus Torvalds will declare that the window is closed and release the
+first of the "rc" kernels.  For the kernel which is destined to be 2.6.40,
+for example, the release which happens at the end of the merge window will
+be called 2.6.40-rc1.  The -rc1 release is the signal that the time to
+merge new features has passed, and that the time to stabilize the next
+kernel has begun.
 
 Over the next six to ten weeks, only patches which fix problems should be
 submitted to the mainline.  On occasion a more significant change will be
@@ -66,20 +65,19 @@ will get up to somewhere between -rc6 and -rc9 before the kernel is
 considered to be sufficiently stable and the final 2.6.x release is made.
 At that point the whole process starts over again.
 
-As an example, here is how the 2.6.25 development cycle went (all dates in
-2008): 
-
-       January 24      2.6.24 stable release
-       February 10     2.6.25-rc1, merge window closes
-       February 15     2.6.25-rc2
-       February 24     2.6.25-rc3
-       March 4         2.6.25-rc4
-       March 9         2.6.25-rc5
-       March 16        2.6.25-rc6
-       March 25        2.6.25-rc7
-       April 1         2.6.25-rc8
-       April 11        2.6.25-rc9
-       April 16        2.6.25 stable release
+As an example, here is how the 2.6.38 development cycle went (all dates in
+2011):
+
+       January 4       2.6.37 stable release
+       January 18      2.6.38-rc1, merge window closes
+       January 21      2.6.38-rc2
+       February 1      2.6.38-rc3
+       February 7      2.6.38-rc4
+       February 15     2.6.38-rc5
+       February 21     2.6.38-rc6
+       March 1         2.6.38-rc7
+       March 7         2.6.38-rc8
+       March 14        2.6.38 stable release
 
 How do the developers decide when to close the development cycle and create
 the stable release?  The most significant metric used is the list of
@@ -87,7 +85,7 @@ regressions from previous releases.  No bugs are welcome, but those which
 break systems which worked in the past are considered to be especially
 serious.  For this reason, patches which cause regressions are looked upon
 unfavorably and are quite likely to be reverted during the stabilization
-period. 
+period.
 
 The developers' goal is to fix all known regressions before the stable
 release is made.  In the real world, this kind of perfection is hard to
@@ -99,26 +97,34 @@ kernels go out with a handful of known regressions though, hopefully, none
 of them are serious.
 
 Once a stable release is made, its ongoing maintenance is passed off to the
-"stable team," currently comprised of Greg Kroah-Hartman and Chris Wright.
-The stable team will release occasional updates to the stable release using
-the 2.6.x.y numbering scheme.  To be considered for an update release, a
-patch must (1) fix a significant bug, and (2) already be merged into the
-mainline for the next development kernel.  Continuing our 2.6.25 example,
-the history (as of this writing) is:
-
-       May 1           2.6.25.1
-       May 6           2.6.25.2 
-       May 9           2.6.25.3 
-       May 15          2.6.25.4
-       June 7          2.6.25.5
-       June 9          2.6.25.6
-       June 16         2.6.25.7
-       June 21         2.6.25.8
-       June 24         2.6.25.9
-
-Stable updates for a given kernel are made for approximately six months;
-after that, the maintenance of stable releases is solely the responsibility
-of the distributors which have shipped that particular kernel.
+"stable team," currently consisting of Greg Kroah-Hartman.  The stable team
+will release occasional updates to the stable release using the 2.6.x.y
+numbering scheme.  To be considered for an update release, a patch must (1)
+fix a significant bug, and (2) already be merged into the mainline for the
+next development kernel.  Kernels will typically receive stable updates for
+a little more than one development cycle past their initial release.  So,
+for example, the 2.6.36 kernel's history looked like:
+
+       October 10      2.6.36 stable release
+       November 22     2.6.36.1
+       December 9      2.6.36.2
+       January 7       2.6.36.3
+       February 17     2.6.36.4
+
+2.6.36.4 was the final stable update for the 2.6.36 release.
+
+Some kernels are designated "long term" kernels; they will receive support
+for a longer period.  As of this writing, the current long term kernels
+and their maintainers are:
+
+       2.6.27  Willy Tarreau           (Deep-frozen stable kernel)
+       2.6.32  Greg Kroah-Hartman
+       2.6.35  Andi Kleen              (Embedded flag kernel)
+
+The selection of a kernel for long-term support is purely a matter of a
+maintainer having the need and the time to maintain that release.  There
+are no known plans for long-term support for any specific upcoming
+release.
 
 
 2.2: THE LIFECYCLE OF A PATCH
@@ -130,7 +136,7 @@ each patch implements a change which is desirable to have in the mainline.
 This process can happen quickly for minor fixes, or, in the case of large
 and controversial changes, go on for years.  Much developer frustration
 comes from a lack of understanding of this process or from attempts to
-circumvent it.  
+circumvent it.
 
 In the hopes of reducing that frustration, this document will describe how
 a patch gets into the kernel.  What follows below is an introduction which
@@ -193,8 +199,8 @@ involved.
 2.3: HOW PATCHES GET INTO THE KERNEL
 
 There is exactly one person who can merge patches into the mainline kernel
-repository: Linus Torvalds.  But, of the over 12,000 patches which went
-into the 2.6.25 kernel, only 250 (around 2%) were directly chosen by Linus
+repository: Linus Torvalds.  But, of the over 9,500 patches which went
+into the 2.6.38 kernel, only 112 (around 1.3%) were directly chosen by Linus
 himself.  The kernel project has long since grown to a size where no single
 developer could possibly inspect and select every patch unassisted.  The
 way the kernel developers have addressed this growth is through the use of
@@ -229,7 +235,7 @@ first in trees dedicated to network device drivers, wireless networking,
 etc.  This chain of repositories can be arbitrarily long, though it rarely
 exceeds two or three links.  Since each maintainer in the chain trusts
 those managing lower-level trees, this process is known as the "chain of
-trust." 
+trust."
 
 Clearly, in a system like this, getting patches into the kernel depends on
 finding the right maintainer.  Sending patches directly to Linus is not
@@ -254,7 +260,7 @@ The answer comes in the form of -next trees, where subsystem trees are
 collected for testing and review.  The older of these trees, maintained by
 Andrew Morton, is called "-mm" (for memory management, which is how it got
 started).  The -mm tree integrates patches from a long list of subsystem
-trees; it also has some patches aimed at helping with debugging.  
+trees; it also has some patches aimed at helping with debugging.
 
 Beyond that, -mm contains a significant collection of patches which have
 been selected by Andrew directly.  These patches may have been posted on a
@@ -264,8 +270,8 @@ subsystem tree of last resort; if there is no other obvious path for a
 patch into the mainline, it is likely to end up in -mm.  Miscellaneous
 patches which accumulate in -mm will eventually either be forwarded on to
 an appropriate subsystem tree or be sent directly to Linus.  In a typical
-development cycle, approximately 10% of the patches going into the mainline
-get there via -mm.
+development cycle, approximately 5-10% of the patches going into the
+mainline get there via -mm.
 
 The current -mm patch is available in the "mmotm" (-mm of the moment)
 directory at:
@@ -275,7 +281,7 @@ directory at:
 Use of the MMOTM tree is likely to be a frustrating experience, though;
 there is a definite chance that it will not even compile.
 
-The other -next tree, started more recently, is linux-next, maintained by
+The primary tree for next-cycle patch merging is linux-next, maintained by
 Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
 the mainline is expected to look like after the next merge window closes.
 Linux-next trees are announced on the linux-kernel and linux-next mailing
@@ -287,25 +293,14 @@ Some information about linux-next has been gathered at:
 
        http://linux.f-seidel.de/linux-next/pmwiki/
 
-How the linux-next tree will fit into the development process is still
-changing.  As of this writing, the first full development cycle involving
-linux-next (2.6.26) is coming to an end; thus far, it has proved to be a
-valuable resource for finding and fixing integration problems before the
-beginning of the merge window.  See http://lwn.net/Articles/287155/ for
-more information on how linux-next has worked to set up the 2.6.27 merge
-window.
-
-Some developers have begun to suggest that linux-next should be used as the
-target for future development as well.  The linux-next tree does tend to be
-far ahead of the mainline and is more representative of the tree into which
-any new work will be merged.  The downside to this idea is that the
-volatility of linux-next tends to make it a difficult development target.
-See http://lwn.net/Articles/289013/ for more information on this topic, and
-stay tuned; much is still in flux where linux-next is involved.
+Linux-next has become an integral part of the kernel development process;
+all patches merged during a given merge window should really have found
+their way into linux-next some time before the merge window opens.
+
 
 2.4.1: STAGING TREES
 
-The kernel source tree now contains the drivers/staging/ directory, where
+The kernel source tree contains the drivers/staging/ directory, where
 many sub-directories for drivers or filesystems that are on their way to
 being added to the kernel tree live.  They remain in drivers/staging while
 they still need more work; once complete, they can be moved into the
@@ -313,15 +308,23 @@ kernel proper.  This is a way to keep track of drivers that aren't
 up to Linux kernel coding or quality standards, but people may want to use
 them and track development.
 
-Greg Kroah-Hartman currently (as of 2.6.36) maintains the staging tree.
-Drivers that still need work are sent to him, with each driver having
-its own subdirectory in drivers/staging/.  Along with the driver source
-files, a TODO file should be present in the directory as well.  The TODO
-file lists the pending work that the driver needs for acceptance into
-the kernel proper, as well as a list of people that should be Cc'd for any
-patches to the driver.  Staging drivers that don't currently build should
-have their config entries depend upon CONFIG_BROKEN.  Once they can
-be successfully built without outside patches, CONFIG_BROKEN can be removed.
+Greg Kroah-Hartman currently maintains the staging tree.  Drivers that
+still need work are sent to him, with each driver having its own
+subdirectory in drivers/staging/.  Along with the driver source files, a
+TODO file should be present in the directory as well.  The TODO file lists
+the pending work that the driver needs for acceptance into the kernel
+proper, as well as a list of people that should be Cc'd for any patches to
+the driver.  Current rules require that drivers contributed to staging
+must, at a minimum, compile properly.
+
+Staging can be a relatively easy way to get new drivers into the mainline
+where, with luck, they will come to the attention of other developers and
+improve quickly.  Entry into staging is not the end of the story, though;
+code in staging which is not seeing regular progress will eventually be
+removed.  Distributors also tend to be relatively reluctant to enable
+staging drivers.  So staging is, at best, a stop on the way toward becoming
+a proper mainline driver.
+
 
 2.5: TOOLS
 
@@ -347,11 +350,7 @@ page at:
 
        http://git-scm.com/
 
-That page has pointers to documentation and tutorials.  One should be
-aware, in particular, of the Kernel Hacker's Guide to git, which has
-information specific to kernel development:
-
-       http://linux.yyz.us/git-howto.html
+That page has pointers to documentation and tutorials.
 
 Among the kernel developers who do not use git, the most popular choice is
 almost certainly Mercurial:
@@ -408,7 +407,7 @@ There are a few hints which can help with linux-kernel survival:
   important to filter on both the topic of interest (though note that
   long-running conversations can drift away from the original subject
   without changing the email subject line) and the people who are
-  participating.  
+  participating.
 
 - Do not feed the trolls.  If somebody is trying to stir up an angry
   response, ignore them.
index 307a159a70caf34b6d1c8eda88490752ed465437..f87ba7b3fbac1d3393df3e293fc637e442d00431 100644 (file)
@@ -110,8 +110,8 @@ the kernel community's standards.  Some examples include:
 
  - The AppArmor security module made use of internal virtual filesystem
    data structures in ways which were considered to be unsafe and
-   unreliable.  This code has since been significantly reworked, but
-   remains outside of the mainline.
+   unreliable.  This concern (among others) kept AppArmor out of the
+   mainline for years.
 
 In each of these cases, a great deal of pain and extra work could have been
 avoided with some early discussion with the kernel developers.
@@ -138,6 +138,19 @@ patches, and who, if anybody, is attaching Signed-off-by lines to those
 patches.  Those are the people who will be best placed to help with a new
 development project.
 
+The task of finding the right maintainer is sometimes challenging enough
+that the kernel developers have added a script to ease the process:
+
+       .../scripts/get_maintainer.pl
+
+This script will return the current maintainer(s) for a given file or
+directory when given the "-f" option.  If passed a patch on the
+command line, it will list the maintainers who should probably receive
+copies of the patch.  There are a number of options regulating how hard
+get_maintainer.pl will search for maintainers; please be careful about
+using the more aggressive options as you may end up including developers
+who have no real interest in the code you are modifying.
+
 If all else fails, talking to Andrew Morton can be an effective way to
 track down a maintainer for a specific piece of code.
 
@@ -155,11 +168,15 @@ reaction, but, instead, little or no reaction at all.  The sad truth of the
 matter is (1) kernel developers tend to be busy, (2) there is no shortage
 of people with grand plans and little code (or even prospect of code) to
 back them up, and (3) nobody is obligated to review or comment on ideas
-posted by others.  If a request-for-comments posting yields little in the
-way of comments, do not assume that it means there is no interest in the
-project.  Unfortunately, you also cannot assume that there are no problems
-with your idea.  The best thing to do in this situation is to proceed,
-keeping the community informed as you go.
+posted by others.  Beyond that, high-level designs often hide problems
+which are only reviewed when somebody actually tries to implement those
+designs; for that reason, kernel developers would rather see the code.
+
+If a request-for-comments posting yields little in the way of comments, do
+not assume that it means there is no interest in the project.
+Unfortunately, you also cannot assume that there are no problems with your
+idea.  The best thing to do in this situation is to proceed, keeping the
+community informed as you go.
 
 
 3.5: GETTING OFFICIAL BUY-IN
index 2278693c8ffa4dc56baf265514efc798fbafd2ea..f3f1a469443cd2daca59e0234952c4a4598d1000 100644 (file)
@@ -131,6 +131,11 @@ classic time/space tradeoff taught in beginning data structures classes
 often does not apply to contemporary hardware.  Space *is* time, in that a
 larger program will run slower than one which is more compact.
 
+More recent compilers take an increasingly active role in deciding whether
+a given function should actually be inlined or not.  So the liberal
+placement of "inline" keywords may not just be excessive; it could also be
+irrelevant.
+
 
 * Locking
 
@@ -285,6 +290,13 @@ be found at https://sparse.wiki.kernel.org/index.php/Main_Page if your
 distributor does not package it); it can then be run on the code by adding
 "C=1" to your make command.
 
+The "Coccinelle" tool (http://coccinelle.lip6.fr/) is able to find a wide
+variety of potential coding problems; it can also propose fixes for those
+problems.  Quite a few "semantic patches" for the kernel have been packaged
+under the scripts/coccinelle directory; running "make coccicheck" will run
+through those semantic patches and report on any problems found.  See
+Documentation/coccinelle.txt for more information.
+
 Other kinds of portability errors are best found by compiling your code for
 other architectures.  If you do not happen to have an S/390 system or a
 Blackfin development board handy, you can still perform the compilation
@@ -308,7 +320,9 @@ The first piece of documentation for any patch is its associated
 changelog.  Log entries should describe the problem being solved, the form
 of the solution, the people who worked on the patch, any relevant
 effects on performance, and anything else that might be needed to
-understand the patch.
+understand the patch.  Be sure that the changelog says *why* the patch is
+worth applying; a surprising number of developers fail to provide that
+information.
 
 Any code which adds a new user-space interface - including new sysfs or
 /proc files - should include documentation of that interface which enables
@@ -321,7 +335,7 @@ boot-time parameters.  Any patch which adds new parameters should add the
 appropriate entries to this file.
 
 Any new configuration options must be accompanied by help text which
-clearly explains the options and when the user might want to select them. 
+clearly explains the options and when the user might want to select them.
 
 Internal API information for many subsystems is documented by way of
 specially-formatted comments; these comments can be extracted and formatted
@@ -372,7 +386,8 @@ which is broken by the change.  For a widely-used function, this duty can
 lead to literally hundreds or thousands of changes - many of which are
 likely to conflict with work being done by other developers.  Needless to
 say, this can be a large job, so it is best to be sure that the
-justification is solid.
+justification is solid.  Note that the Coccinelle tool can help with
+wide-ranging API changes.
 
 When making an incompatible API change, one should, whenever possible,
 ensure that code which has not been updated is caught by the compiler.
index f622c1e9f0f926c43c54b7d0fdd6627ef3b447a6..903a2546f13890b17d309554f3cbda69c2ee9ade 100644 (file)
@@ -60,12 +60,15 @@ even in the short term.
 
 Patches must be prepared against a specific version of the kernel.  As a
 general rule, a patch should be based on the current mainline as found in
-Linus's git tree.  It may become necessary to make versions against -mm,
-linux-next, or a subsystem tree, though, to facilitate wider testing and
-review.  Depending on the area of your patch and what is going on
-elsewhere, basing a patch against these other trees can require a
-significant amount of work resolving conflicts and dealing with API
-changes.
+Linus's git tree.  When basing on mainline, start with a well-known release
+point - a stable or -rc release - rather than branching off the mainline at
+an arbitrary spot.
+
+It may become necessary to make versions against -mm, linux-next, or a
+subsystem tree, though, to facilitate wider testing and review.  Depending
+on the area of your patch and what is going on elsewhere, basing a patch
+against these other trees can require a significant amount of work
+resolving conflicts and dealing with API changes.
 
 Only the most simple changes should be formatted as a single patch;
 everything else should be made as a logical series of changes.  Splitting
@@ -100,11 +103,11 @@ rules of thumb, however, which can help considerably:
    result is a broken kernel, you will make life harder for developers and
    users who are engaging in the noble work of tracking down problems.
 
- - Do not overdo it, though.  One developer recently posted a set of edits
+ - Do not overdo it, though.  One developer once posted a set of edits
    to a single file as 500 separate patches - an act which did not make him
    the most popular person on the kernel mailing list.  A single patch can
    be reasonably large as long as it still contains a single *logical*
-   change. 
+   change.
 
  - It can be tempting to add a whole new infrastructure with a series of
    patches, but to leave that infrastructure unused until the final patch
@@ -162,7 +165,8 @@ To that end, the summary line should describe the effects of and motivation
 for the change as well as possible given the one-line constraint.  The
 detailed description can then amplify on those topics and provide any
 needed additional information.  If the patch fixes a bug, cite the commit
-which introduced the bug if possible.  If a problem is associated with
+which introduced the bug if possible (and please provide both the commit ID
+and the title when citing commits).  If a problem is associated with
 specific log or compiler output, include that output to help others
 searching for a solution to the same problem.  If the change is meant to
 support other changes coming in later patch, say so.  If internal APIs are
@@ -230,7 +234,7 @@ take care of:
    which have had gratuitous white-space changes or line wrapping performed
    by the mail client will not apply at the other end, and often will not
    be examined in any detail.  If there is any doubt at all, mail the patch
-   to yourself and convince yourself that it shows up intact.  
+   to yourself and convince yourself that it shows up intact.
 
    Documentation/email-clients.txt has some helpful hints on making
    specific mail clients work for sending patches.
@@ -287,7 +291,7 @@ something like:
 
 where "nn" is the ordinal number of the patch, "mm" is the total number of
 patches in the series, and "subsys" is the name of the affected subsystem.
-Clearly, nn/mm can be omitted for a single, standalone patch.  
+Clearly, nn/mm can be omitted for a single, standalone patch.
 
 If you have a significant series of patches, it is customary to send an
 introductory description as part zero.  This convention is not universally
@@ -299,5 +303,5 @@ In general, the second and following parts of a multi-part patch should be
 sent as a reply to the first part so that they all thread together at the
 receiving end.  Tools like git and quilt have commands to mail out a set of
 patches with the proper threading.  If you have a long series, though, and
-are using git, please provide the --no-chain-reply-to option to avoid
+are using git, please stay away from the --chain-reply-to option to avoid
 creating exceptionally deep nesting.
index a8fba3d83a8556a21c5bcb3b4b69c564ae8bf5da..41d324a9420d2e1fd2f4df284776becefc0e7cdf 100644 (file)
@@ -66,6 +66,11 @@ be easy to become blinded by your own solution to a problem to the point
 that you don't realize that something is fundamentally wrong or, perhaps,
 you're not even solving the right problem.
 
+Andrew Morton has suggested that every review comment which does not result
+in a code change should result in an additional code comment instead; that
+can help future reviewers avoid the questions which came up the first time
+around.
+
 One fatal mistake is to ignore review comments in the hope that they will
 go away.  They will not go away.  If you repost code without having
 responded to the comments you got the time before, you're likely to find
@@ -100,7 +105,7 @@ entry into a subsystem maintainer's tree.  How that works varies from one
 subsystem to the next; each maintainer has his or her own way of doing
 things.  In particular, there may be more than one tree - one, perhaps,
 dedicated to patches planned for the next merge window, and another for
-longer-term work.  
+longer-term work.
 
 For patches applying to areas for which there is no obvious subsystem tree
 (memory management patches, for example), the default tree often ends up
@@ -109,11 +114,10 @@ through the -mm tree.
 
 Inclusion into a subsystem tree can bring a higher level of visibility to a
 patch.  Now other developers working with that tree will get the patch by
-default.  Subsystem trees typically feed into -mm and linux-next as well,
-making their contents visible to the development community as a whole.  At
-this point, there's a good chance that you will get more comments from a
-new set of reviewers; these comments need to be answered as in the previous
-round.
+default.  Subsystem trees typically feed linux-next as well, making their
+contents visible to the development community as a whole.  At this point,
+there's a good chance that you will get more comments from a new set of
+reviewers; these comments need to be answered as in the previous round.
 
 What may also happen at this point, depending on the nature of your patch,
 is that conflicts with work being done by others turn up.  In the worst
index 837179447e17f0e423d5b2e5f2bc54eb04bde3db..26dc3fa196e46fc9a1f8ef9f03e303c409e5b8b2 100644 (file)
@@ -119,7 +119,7 @@ can affect your ability to get trees pulled in the future.  Quoting Linus:
        to trust things *without* then having to go and check every
        individual change by hand.
 
-(http://lwn.net/Articles/224135/).  
+(http://lwn.net/Articles/224135/).
 
 To avoid this kind of situation, ensure that all patches within a given
 branch stick closely to the associated topic; a "driver fixes" branch
@@ -138,7 +138,7 @@ When requesting a pull, be sure to give all the relevant information: where
 your tree is, what branch to pull, and what changes will result from the
 pull.  The git request-pull command can be helpful in this regard; it will
 format the request as other developers expect, and will also check to be
-sure that you have remembered to push those changes to the public server. 
+sure that you have remembered to push those changes to the public server.
 
 
 7.2: REVIEWING PATCHES
index e6c4b757025b434e33b71fa172e16f36c0f0533d..f959909d7154971d50f64cf773adea2b8afe7b6f 100644 (file)
@@ -6,7 +6,7 @@ This document describes how to use the dynamic debug (ddebug) feature.
 
 Dynamic debug is designed to allow you to dynamically enable/disable kernel
 code to obtain additional kernel information. Currently, if
-CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_debug() calls can be
+CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can be
 dynamically enabled per-callsite.
 
 Dynamic debug has even more useful features:
@@ -26,7 +26,7 @@ Dynamic debug has even more useful features:
 Controlling dynamic debug Behaviour
 ===================================
 
-The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
+The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a
 control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
 filesystem, in order to make use of this feature. Subsequently, we refer to the
 control file as: <debugfs>/dynamic_debug/control. For example, if you want to
index 4d0bc70f185225b705945405610e30301f7602e5..df02245d1419d76a1962f3a879f5480c9cf02a5f 100644 (file)
@@ -2,6 +2,10 @@ Kernel driver f71882fg
 ======================
 
 Supported chips:
+  * Fintek F71808E
+    Prefix: 'f71808e'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Not public
   * Fintek F71858FG
     Prefix: 'f71858fg'
     Addresses scanned: none, address read from Super I/O config space
@@ -26,10 +30,25 @@ Supported chips:
     Prefix: 'f71889ed'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Should become available on the Fintek website soon
+  * Fintek F71889A
+    Prefix: 'f71889a'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Should become available on the Fintek website soon
   * Fintek F8000
     Prefix: 'f8000'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Not public
+  * Fintek F81801U
+    Prefix: 'f71889fg'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Not public
+    Note: This is the 64-pin variant of the F71889FG, they have the
+         same device ID and are fully compatible as far as hardware
+         monitoring is concerned.
+  * Fintek F81865F
+    Prefix: 'f81865f'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
 
 Author: Hans de Goede <hdegoede@redhat.com>
 
index 23ce7d350d1abad3b19a382830dd4741ad3b2be9..2bd4e82e5d9ff2085f78f44c6a9351a61a2512e5 100644 (file)
@@ -14,7 +14,8 @@ Some models report hotkeys through the SNC or SPIC devices, such events are
 reported both through the ACPI subsystem as acpi events and through the INPUT
 subsystem. See the logs of acpid or /proc/acpi/event and
 /proc/bus/input/devices to find out what those events are and which input
-devices are created by the driver.
+devices are created by the driver. Additionally, loading the driver with the
+debug option will report all events in the kernel log.
 
 Backlight control:
 ------------------
@@ -64,6 +65,16 @@ powers off the sound card,
        # echo "1" > /sys/devices/platform/sony-laptop/audiopower
 powers on the sound card.
 
+
+RFkill control:
+---------------
+More recent Vaio models expose a consistent set of ACPI methods to
+control radio frequency emitting devices. If you are a lucky owner of
+such a laptop you will find the necessary rfkill devices under
+/sys/class/rfkill. Check those starting with sony-* in
+       # grep . /sys/class/rfkill/*/{state,name}
+
+
 Development:
 ------------
 
@@ -75,8 +86,21 @@ pass the option 'debug=1'.
 REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS.
 
 In your kernel logs you will find the list of all ACPI methods
-the SNC device has on your laptop. You can see the GCDP/GCDP methods
-used to pwer on/off the CD drive, but there are others.
+the SNC device has on your laptop.
+
+* For new models you will see a long list of meaningless method names,
+reading the DSDT table source should reveal that:
+(1) the SNC device uses an internal capability lookup table
+(2) SN00 is used to find values in the lookup table
+(3) SN06 and SN07 are used to call into the real methods based on
+    offsets you can obtain iterating the table using SN00
+(4) SN02 used to enable events.
+Some values in the capability lookup table are more or less known, see
+the code for all sony_call_snc_handle calls, others are more obscure.
+
+* For old models you can see the GCDP/GCDP methods used to pwer on/off
+the CD drive, but there are others and they are usually different from
+model to model.
 
 I HAVE NO IDEA WHAT THOSE METHODS DO.
 
@@ -108,9 +132,8 @@ Bugs/Limitations:
   laptop, including permanent damage.
 
 * The sony-laptop and sonypi drivers do not interact at all. In the
-  future, sonypi could use sony-laptop to do (part of) its business.
+  future, sonypi will be removed and replaced by sony-laptop.
 
 * spicctrl, which is the userspace tool used to communicate with the
-  sonypi driver (through /dev/sonypi) does not try to use the
-  sony-laptop driver. In the future, spicctrl could try sonypi first,
-  and if it isn't present, try sony-laptop instead.
+  sonypi driver (through /dev/sonypi) is deprecated as well since all
+  its features are now available under the sysfs tree via sony-laptop.
index 4fb9017b441330a997f5a0d9499a3f1d245f3524..6b4b9cdec370fef4f83ed5449329dc8339347f71 100644 (file)
@@ -548,10 +548,8 @@ S: Maintained
 F:     sound/aoa/
 
 APM DRIVER
-M:     Stephen Rothwell <sfr@canb.auug.org.au>
 L:     linux-laptop@vger.kernel.org
-W:     http://www.canb.auug.org.au/~sfr/
-S:     Supported
+S:     Orphan
 F:     arch/x86/kernel/apm_32.c
 F:     include/linux/apm_bios.h
 
@@ -1159,14 +1157,14 @@ S:      Maintained
 F:     Documentation/hwmon/asc7621
 F:     drivers/hwmon/asc7621.c
 
-ASUS ACPI EXTRAS DRIVER
+ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
 M:     Corentin Chary <corentincj@iksaif.net>
-M:     Karol Kozimor <sziwan@users.sourceforge.net>
 L:     acpi4asus-user@lists.sourceforge.net
 L:     platform-driver-x86@vger.kernel.org
 W:     http://acpi4asus.sf.net
 S:     Maintained
-F:     drivers/platform/x86/asus_acpi.c
+F:     drivers/platform/x86/asus*.c
+F:     drivers/platform/x86/eeepc*.c
 
 ASUS ASB100 HARDWARE MONITOR DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
@@ -1174,14 +1172,6 @@ L:       lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/asb100.c
 
-ASUS LAPTOP EXTRAS DRIVER
-M:     Corentin Chary <corentincj@iksaif.net>
-L:     acpi4asus-user@lists.sourceforge.net
-L:     platform-driver-x86@vger.kernel.org
-W:     http://acpi4asus.sf.net
-S:     Maintained
-F:     drivers/platform/x86/asus-laptop.c
-
 ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
 M:     Dan Williams <dan.j.williams@intel.com>
 W:     http://sourceforge.net/projects/xscaleiop
@@ -2416,22 +2406,6 @@ T:       git git://git.alsa-project.org/alsa-kernel.git
 S:     Maintained
 F:     sound/usb/misc/ua101.c
 
-EEEPC LAPTOP EXTRAS DRIVER
-M:     Corentin Chary <corentincj@iksaif.net>
-L:     acpi4asus-user@lists.sourceforge.net
-L:     platform-driver-x86@vger.kernel.org
-W:     http://acpi4asus.sf.net
-S:     Maintained
-F:     drivers/platform/x86/eeepc-laptop.c
-
-EEEPC WMI EXTRAS DRIVER
-M:     Corentin Chary <corentincj@iksaif.net>
-L:     acpi4asus-user@lists.sourceforge.net
-L:     platform-driver-x86@vger.kernel.org
-W:     http://acpi4asus.sf.net
-S:     Maintained
-F:     drivers/platform/x86/eeepc-wmi.c
-
 EFIFB FRAMEBUFFER DRIVER
 L:     linux-fbdev@vger.kernel.org
 M:     Peter Jones <pjones@redhat.com>
@@ -6633,6 +6607,7 @@ F:        drivers/media/video/zr364xx.c
 
 USER-MODE LINUX (UML)
 M:     Jeff Dike <jdike@addtoit.com>
+M:     Richard Weinberger <richard@nod.at>
 L:     user-mode-linux-devel@lists.sourceforge.net
 L:     user-mode-linux-user@lists.sourceforge.net
 W:     http://user-mode-linux.sourceforge.net
index 7d4e9c8da7295e628d8a7849b72e1d8651d8772c..ba7a55ccd890858f5771793616f5bf164a620ad3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 38
-EXTRAVERSION =
+SUBLEVEL = 39
+EXTRAVERSION = -rc1
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index cc31bec2e3163378a1084a217b78b32fbe3c854b..bd4160c571962ca9b3a1966bb5b5a7a15c792119 100644 (file)
@@ -11,6 +11,7 @@ config ALPHA
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select AUTO_IRQ_AFFINITY if SMP
+       select GENERIC_IRQ_SHOW
        select GENERIC_HARDIRQS_NO_DEPRECATED
        help
          The Alpha is a 64-bit general-purpose processor designed and
index a19d600822991c847eb65e0d943e4b8ff9dd82e1..381431a2d6d9d7be7703bfe424e08759df56c8d3 100644 (file)
@@ -67,68 +67,21 @@ int irq_select_affinity(unsigned int irq)
 }
 #endif /* CONFIG_SMP */
 
-int
-show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
        int j;
-       int irq = *(loff_t *) v;
-       struct irqaction * action;
-       struct irq_desc *desc;
-       unsigned long flags;
 
 #ifdef CONFIG_SMP
-       if (irq == 0) {
-               seq_puts(p, "           ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "CPU%d       ", j);
-               seq_putc(p, '\n');
-       }
-#endif
-
-       if (irq < ACTUAL_NR_IRQS) {
-               desc = irq_to_desc(irq);
-
-               if (!desc)
-                       return 0;
-
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               action = desc->action;
-               if (!action) 
-                       goto unlock;
-               seq_printf(p, "%3d: ", irq);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(irq));
-#else
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
+       seq_puts(p, "IPI: ");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
+       seq_putc(p, '\n');
 #endif
-               seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
-               seq_printf(p, "  %c%s",
-                       (action->flags & IRQF_DISABLED)?'+':' ',
-                       action->name);
-
-               for (action=action->next; action; action = action->next) {
-                       seq_printf(p, ", %c%s",
-                                 (action->flags & IRQF_DISABLED)?'+':' ',
-                                  action->name);
-               }
-
-               seq_putc(p, '\n');
-unlock:
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       } else if (irq == ACTUAL_NR_IRQS) {
-#ifdef CONFIG_SMP
-               seq_puts(p, "IPI: ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
-               seq_putc(p, '\n');
-#endif
-               seq_puts(p, "PMI: ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
-               seq_puts(p, "          Performance Monitoring\n");
-               seq_printf(p, "ERR: %10lu\n", irq_err_count);
-       }
+       seq_puts(p, "PMI: ");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
+       seq_puts(p, "          Performance Monitoring\n");
+       seq_printf(p, "ERR: %10lu\n", irq_err_count);
        return 0;
 }
 
index 411ca11d0a18172ba63523acc8170d337e7dadd3..1479dc6ebd97a4288ee6d0dd0334ea17dbf02049 100644 (file)
@@ -228,7 +228,7 @@ struct irqaction timer_irqaction = {
 void __init
 init_rtc_irq(void)
 {
-       set_irq_chip_and_handler_name(RTC_IRQ, &no_irq_chip,
+       irq_set_chip_and_handler_name(RTC_IRQ, &no_irq_chip,
                                      handle_simple_irq, "RTC");
        setup_irq(RTC_IRQ, &timer_irqaction);
 }
index c7cc9813e45fe002c2e39d0c7a4fe6312c8fe3ce..e1861c77dabc209f4a4ceb2fddc8709b673713dc 100644 (file)
@@ -92,7 +92,7 @@ init_i8259a_irqs(void)
        outb(0xff, 0xA1);       /* mask all of 8259A-2 */
 
        for (i = 0; i < 16; i++) {
-               set_irq_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
        }
 
        setup_irq(2, &cascade);
index b30227fa7f5f6f5e9bc2ddfeaad8942a6bc02cc7..13c97a5b31e88848ad8c496ba1e2f163a7db660f 100644 (file)
@@ -102,7 +102,7 @@ init_pyxis_irqs(unsigned long ignore_mask)
        for (i = 16; i < 48; ++i) {
                if ((ignore_mask >> i) & 1)
                        continue;
-               set_irq_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 82a47bba41c4940a8c309a932819232882d81266..a79fa30e75528cac1bedb940482f4388d99aca1a 100644 (file)
@@ -51,7 +51,7 @@ init_srm_irqs(long max, unsigned long ignore_mask)
        for (i = 16; i < max; ++i) {
                if (i < 64 && ((ignore_mask >> i) & 1))
                        continue;
-               set_irq_chip_and_handler(i, &srm_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &srm_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 }
index 88d95e872f55f9389ede1778f39952fff141d1aa..0e1439904cdb7031c8036a5875ad5d71998a0bbb 100644 (file)
@@ -125,7 +125,7 @@ alcor_init_irq(void)
                   on while IRQ probing.  */
                if (i >= 16+20 && i <= 16+30)
                        continue;
-               set_irq_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
        i8259a_irq_type.irq_ack = alcor_isa_mask_and_ack_irq;
index 57eb6307bc2759d43a07c917f7e50594c5b514c5..c8c112d5158485013b148effc52d6905a8da164c 100644 (file)
@@ -105,8 +105,8 @@ common_init_irq(void (*srm_dev_int)(unsigned long v))
                outb(0xff, 0x806);
 
                for (i = 16; i < 35; ++i) {
-                       set_irq_chip_and_handler(i, &cabriolet_irq_type,
-                               handle_level_irq);
+                       irq_set_chip_and_handler(i, &cabriolet_irq_type,
+                                                handle_level_irq);
                        irq_set_status_flags(i, IRQ_LEVEL);
                }
        }
index 481df4ecb651258ed280d062cf9c187261874857..5ac00fd4cd0cbd12ca4fe97208dbbe4809b99d7d 100644 (file)
@@ -270,7 +270,7 @@ init_tsunami_irqs(struct irq_chip * ops, int imin, int imax)
 {
        long i;
        for (i = imin; i <= imax; ++i) {
-               set_irq_chip_and_handler(i, ops, handle_level_irq);
+               irq_set_chip_and_handler(i, ops, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 }
index 402e908ffb3e130cf39d2ecba458b5c94504aaa2..a7a23b40eec53f9319e4502c30d7b99557d71a72 100644 (file)
@@ -118,7 +118,7 @@ eb64p_init_irq(void)
        init_i8259a_irqs();
 
        for (i = 16; i < 32; ++i) {
-               set_irq_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 0b44a54c1522ad87caad7c4d90853e4a37ebb7a5..a60cd5b2621eb4650041b45db5d907a78049c6a7 100644 (file)
@@ -138,7 +138,7 @@ eiger_init_irq(void)
        init_i8259a_irqs();
 
        for (i = 16; i < 128; ++i) {
-               set_irq_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 }
index 00341b75c8b25d81b0e203c8771b40bb1cfa6f14..7f1a87f176e25d469762851370e0e92c3cc813f4 100644 (file)
@@ -171,11 +171,11 @@ jensen_init_irq(void)
 {
        init_i8259a_irqs();
 
-       set_irq_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
-       set_irq_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
-       set_irq_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
-       set_irq_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
-       set_irq_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);
 
        common_init_isa_dma();
 }
index e61910734e413f997e31fcdb4db52876f983bfd4..388b99d1779d5e21a41bbc77860fe6fd5cae8baf 100644 (file)
@@ -276,7 +276,7 @@ init_io7_irqs(struct io7 *io7,
 
        /* Set up the lsi irqs.  */
        for (i = 0; i < 128; ++i) {
-               set_irq_chip_and_handler(base + i, lsi_ops, handle_level_irq);
+               irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
@@ -290,7 +290,7 @@ init_io7_irqs(struct io7 *io7,
 
        /* Set up the msi irqs.  */
        for (i = 128; i < (128 + 512); ++i) {
-               set_irq_chip_and_handler(base + i, msi_ops, handle_level_irq);
+               irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
@@ -308,8 +308,8 @@ marvel_init_irq(void)
 
        /* Reserve the legacy irqs.  */
        for (i = 0; i < 16; ++i) {
-               set_irq_chip_and_handler(i, &marvel_legacy_irq_type,
-                       handle_level_irq);
+               irq_set_chip_and_handler(i, &marvel_legacy_irq_type,
+                                        handle_level_irq);
        }
 
        /* Init the io7 irqs.  */
index cf7f43dd3147c49d7fbf922d4c59506b2bde325a..0e6e4697a02590c02b4789b58cc2d7c3a120f589 100644 (file)
@@ -98,7 +98,8 @@ mikasa_init_irq(void)
        mikasa_update_irq_hw(0);
 
        for (i = 16; i < 32; ++i) {
-               set_irq_chip_and_handler(i, &mikasa_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &mikasa_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 92bc188e94a981458f4380262cdf2042f4e12b06..a00ac7087167a88d39f54aa41e47747f11752d28 100644 (file)
@@ -127,7 +127,8 @@ noritake_init_irq(void)
        outw(0, 0x54c);
 
        for (i = 16; i < 48; ++i) {
-               set_irq_chip_and_handler(i, &noritake_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &noritake_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 936d4140ed5fc68e6addf5a9ae1437a77b011f12..7f52161f3d88996a3eacaaeb1c9c3c9d29a398dc 100644 (file)
@@ -180,7 +180,8 @@ rawhide_init_irq(void)
        }
 
        for (i = 16; i < 128; ++i) {
-               set_irq_chip_and_handler(i, &rawhide_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &rawhide_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index cea22a62913b4d9a4ea18092e98bec29a87bf8cd..216d94d9c0c12e2aac9ab92de50c895cdf64b32e 100644 (file)
@@ -99,7 +99,7 @@ rx164_init_irq(void)
 
        rx164_update_irq_hw(0);
        for (i = 16; i < 40; ++i) {
-               set_irq_chip_and_handler(i, &rx164_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &rx164_irq_type, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index a349538aabc94a1e74397a4f15fffaec64e8c86d..da714e427c5fcc383a420d41812ed991c67316a1 100644 (file)
@@ -518,8 +518,8 @@ sable_lynx_init_irq(int nr_of_irqs)
        long i;
 
        for (i = 0; i < nr_of_irqs; ++i) {
-               set_irq_chip_and_handler(i, &sable_lynx_irq_type,
-                       handle_level_irq);
+               irq_set_chip_and_handler(i, &sable_lynx_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 42a5331f13c4faa0f5c20e51099924fbb9ef27cf..a31f8cd9bd6bbde4a3e691bdff3eb52100d0c144 100644 (file)
@@ -138,7 +138,8 @@ takara_init_irq(void)
                takara_update_irq_hw(i, -1);
 
        for (i = 16; i < 128; ++i) {
-               set_irq_chip_and_handler(i, &takara_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &takara_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 
index 8c13a0c77830c576a2f9030fedb3b44951f654de..fea0e4620994455fd4a3d52471c5b89371571087 100644 (file)
@@ -179,7 +179,7 @@ init_titan_irqs(struct irq_chip * ops, int imin, int imax)
 {
        long i;
        for (i = imin; i <= imax; ++i) {
-               set_irq_chip_and_handler(i, ops, handle_level_irq);
+               irq_set_chip_and_handler(i, ops, handle_level_irq);
                irq_set_status_flags(i, IRQ_LEVEL);
        }
 }
index ca60a387ef0a60c08f904cb416063145cd6263bf..d3cb28bb8eb0e450fcd4298698b944264d7b1fc0 100644 (file)
@@ -183,17 +183,17 @@ wildfire_init_irq_per_pca(int qbbno, int pcano)
        for (i = 0; i < 16; ++i) {
                if (i == 2)
                        continue;
-               set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
-                       handle_level_irq);
+               irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
        }
 
-       set_irq_chip_and_handler(36+irq_bias, &wildfire_irq_type,
-               handle_level_irq);
+       irq_set_chip_and_handler(36 + irq_bias, &wildfire_irq_type,
+                                handle_level_irq);
        irq_set_status_flags(36 + irq_bias, IRQ_LEVEL);
        for (i = 40; i < 64; ++i) {
-               set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
-                       handle_level_irq);
+               irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
+                                        handle_level_irq);
                irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
        }
 
index 4f8f3a4e4e0df820ab19061a100f715bfebb4796..5b9f78b570e85c2f959c3d7fb1cda1bd70b2ac55 100644 (file)
@@ -28,6 +28,7 @@ config ARM
        select HAVE_C_RECORDMCOUNT
        select HAVE_GENERIC_HARDIRQS
        select HAVE_SPARSE_IRQ
+       select GENERIC_IRQ_SHOW
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -2010,6 +2011,7 @@ menu "Power management options"
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
+       depends on !ARCH_S5P64X0 && !ARCH_S5P6442
        def_bool y
 
 endmenu
index cb6b041c39d23bf877363308aaf22665b41d5b93..f70ec7dadebbae0b4bcd098fc4c824ff4b0c3eef 100644 (file)
@@ -213,8 +213,8 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
 
 static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct gic_chip_data *chip_data = get_irq_data(irq);
-       struct irq_chip *chip = get_irq_chip(irq);
+       struct gic_chip_data *chip_data = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_get_chip(irq);
        unsigned int cascade_irq, gic_irq;
        unsigned long status;
 
@@ -257,9 +257,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 {
        if (gic_nr >= MAX_GIC_NR)
                BUG();
-       if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
+       if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
                BUG();
-       set_irq_chained_handler(irq, gic_handle_cascade_irq);
+       irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
 static void __init gic_dist_init(struct gic_chip_data *gic,
@@ -319,9 +319,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
         * Setup the Linux IRQ subsystem.
         */
        for (i = irq_start; i < irq_limit; i++) {
-               set_irq_chip(i, &gic_chip);
-               set_irq_chip_data(i, gic);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &gic_chip, handle_level_irq);
+               irq_set_chip_data(i, gic);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
@@ -382,7 +381,7 @@ void __cpuinit gic_enable_ppi(unsigned int irq)
        unsigned long flags;
 
        local_irq_save(flags);
-       irq_to_desc(irq)->status |= IRQ_NOPROBE;
+       irq_set_status_flags(irq, IRQ_NOPROBE);
        gic_unmask_irq(irq_get_irq_data(irq));
        local_irq_restore(flags);
 }
index fcddd48fe9da3a287172e9ad97ebf64e6e41bc63..7a21927c52e184024b71fa48bdfbb380d8b55f55 100644 (file)
@@ -88,8 +88,8 @@ void it8152_init_irq(void)
        __raw_writel((0), IT8152_INTC_LDCNIRR);
 
        for (irq = IT8152_IRQ(0); irq <= IT8152_LAST_IRQ; irq++) {
-               set_irq_chip(irq, &it8152_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &it8152_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index a026a6bf4892fef5d535b93209e593d9444f1449..b55c3625d7ee2befcbbfff8caa6ca0ed078f92ea 100644 (file)
@@ -140,7 +140,7 @@ static struct locomo_dev_info locomo_devices[] = {
 
 static void locomo_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct locomo *lchip = get_irq_chip_data(irq);
+       struct locomo *lchip = irq_get_chip_data(irq);
        int req, i;
 
        /* Acknowledge the parent IRQ */
@@ -197,15 +197,14 @@ static void locomo_setup_irq(struct locomo *lchip)
        /*
         * Install handler for IRQ_LOCOMO_HW.
         */
-       set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
-       set_irq_chip_data(lchip->irq, lchip);
-       set_irq_chained_handler(lchip->irq, locomo_handler);
+       irq_set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
+       irq_set_chip_data(lchip->irq, lchip);
+       irq_set_chained_handler(lchip->irq, locomo_handler);
 
        /* Install handlers for IRQ_LOCOMO_* */
        for ( ; irq <= lchip->irq_base + 3; irq++) {
-               set_irq_chip(irq, &locomo_chip);
-               set_irq_chip_data(irq, lchip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &locomo_chip, handle_level_irq);
+               irq_set_chip_data(irq, lchip);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
@@ -476,8 +475,8 @@ static void __locomo_remove(struct locomo *lchip)
        device_for_each_child(lchip->dev, NULL, locomo_remove_child);
 
        if (lchip->irq != NO_IRQ) {
-               set_irq_chained_handler(lchip->irq, NULL);
-               set_irq_data(lchip->irq, NULL);
+               irq_set_chained_handler(lchip->irq, NULL);
+               irq_set_handler_data(lchip->irq, NULL);
        }
 
        iounmap(lchip->base);
index eb9796b0dab23020356b15ae14ca386286c8f478..a12b33c0dc4291a7b35d38552603ef7a51751580 100644 (file)
@@ -202,7 +202,7 @@ static void
 sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int stat0, stat1, i;
-       struct sa1111 *sachip = get_irq_data(irq);
+       struct sa1111 *sachip = irq_get_handler_data(irq);
        void __iomem *mapbase = sachip->base + SA1111_INTC;
 
        stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0);
@@ -472,25 +472,25 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
        sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
 
        for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
-               set_irq_chip(irq, &sa1111_low_chip);
-               set_irq_chip_data(irq, sachip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &sa1111_low_chip,
+                                        handle_edge_irq);
+               irq_set_chip_data(irq, sachip);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
-               set_irq_chip(irq, &sa1111_high_chip);
-               set_irq_chip_data(irq, sachip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &sa1111_high_chip,
+                                        handle_edge_irq);
+               irq_set_chip_data(irq, sachip);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /*
         * Register SA1111 interrupt
         */
-       set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
-       set_irq_data(sachip->irq, sachip);
-       set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
+       irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
+       irq_set_handler_data(sachip->irq, sachip);
+       irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
 }
 
 /*
@@ -815,8 +815,8 @@ static void __sa1111_remove(struct sa1111 *sachip)
        clk_disable(sachip->clk);
 
        if (sachip->irq != NO_IRQ) {
-               set_irq_chained_handler(sachip->irq, NULL);
-               set_irq_data(sachip->irq, NULL);
+               irq_set_chained_handler(sachip->irq, NULL);
+               irq_set_handler_data(sachip->irq, NULL);
 
                release_mem_region(sachip->phys + SA1111_INTC, 512);
        }
index ae5fe7292e0d441124367c4154f42217de65c2af..113085a77123d95b9cad64a882fff297c3f98dfe 100644 (file)
@@ -305,9 +305,9 @@ static void __init vic_set_irq_sources(void __iomem *base,
                if (vic_sources & (1 << i)) {
                        unsigned int irq = irq_start + i;
 
-                       set_irq_chip(irq, &vic_chip);
-                       set_irq_chip_data(irq, base);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &vic_chip,
+                                                handle_level_irq);
+                       irq_set_chip_data(irq, base);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
        }
index 5586b7c8ef6fd7b1f112890d07e87b03aa695257..a71b417b18568101df9def0d0ad9db84e1980e21 100644 (file)
@@ -10,14 +10,6 @@ static inline void ack_bad_irq(int irq)
        irq_err_count++;
 }
 
-/*
- * Obsolete inline function for calling irq descriptor handlers.
- */
-static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
-{
-       desc->handle_irq(irq, desc);
-}
-
 void set_irq_flags(unsigned int irq, unsigned int flags);
 
 #define IRQF_VALID     (1 << 0)
index 2ad62df377300698db90598544227c16332bdfe4..d16500110ee99526655dcf409455ea0b8e32587b 100644 (file)
@@ -1043,8 +1043,8 @@ ecard_probe(int slot, card_type_t type)
         */
        if (slot < 8) {
                ec->irq = 32 + slot;
-               set_irq_chip(ec->irq, &ecard_chip);
-               set_irq_handler(ec->irq, handle_level_irq);
+               irq_set_chip_and_handler(ec->irq, &ecard_chip,
+                                        handle_level_irq);
                set_irq_flags(ec->irq, IRQF_VALID);
        }
 
@@ -1103,7 +1103,7 @@ static int __init ecard_init(void)
 
        irqhw = ecard_probeirqhw();
 
-       set_irq_chained_handler(IRQ_EXPANSIONCARD,
+       irq_set_chained_handler(IRQ_EXPANSIONCARD,
                                irqhw ? ecard_irqexp_handler : ecard_irq_handler);
 
        ecard_proc_init();
index 3535d3793e65264b1e7ca457f530b4e1be40da95..83bbad03fcc6642f7ab5dc0bc1f8bce5a790eac9 100644 (file)
 
 unsigned long irq_err_count;
 
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int i = *(loff_t *) v, cpu;
-       struct irq_desc *desc;
-       struct irqaction * action;
-       unsigned long flags;
-       int prec, n;
-
-       for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
-               n *= 10;
-
-#ifdef CONFIG_SMP
-       if (prec < 4)
-               prec = 4;
-#endif
-
-       if (i == 0) {
-               char cpuname[12];
-
-               seq_printf(p, "%*s ", prec, "");
-               for_each_present_cpu(cpu) {
-                       sprintf(cpuname, "CPU%d", cpu);
-                       seq_printf(p, " %10s", cpuname);
-               }
-               seq_putc(p, '\n');
-       }
-
-       if (i < nr_irqs) {
-               desc = irq_to_desc(i);
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               action = desc->action;
-               if (!action)
-                       goto unlock;
-
-               seq_printf(p, "%*d: ", prec, i);
-               for_each_present_cpu(cpu)
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-               seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
-               seq_printf(p, "  %s", action->name);
-               for (action = action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-unlock:
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       } else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
-               show_fiq_list(p, prec);
+       show_fiq_list(p, prec);
 #endif
 #ifdef CONFIG_SMP
-               show_ipi_list(p, prec);
+       show_ipi_list(p, prec);
 #endif
 #ifdef CONFIG_LOCAL_TIMERS
-               show_local_irqs(p, prec);
+       show_local_irqs(p, prec);
 #endif
-               seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
-       }
+       seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
        return 0;
 }
 
@@ -144,24 +99,21 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 
 void set_irq_flags(unsigned int irq, unsigned int iflags)
 {
-       struct irq_desc *desc;
-       unsigned long flags;
+       unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
 
        if (irq >= nr_irqs) {
                printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
                return;
        }
 
-       desc = irq_to_desc(irq);
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        if (iflags & IRQF_VALID)
-               desc->status &= ~IRQ_NOREQUEST;
+               clr |= IRQ_NOREQUEST;
        if (iflags & IRQF_PROBE)
-               desc->status &= ~IRQ_NOPROBE;
+               clr |= IRQ_NOPROBE;
        if (!(iflags & IRQF_NOAUTOEN))
-               desc->status &= ~IRQ_NOAUTOEN;
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
+               clr |= IRQ_NOAUTOEN;
+       /* Order is clear bits in "clr" then set bits in "set" */
+       irq_modify_status(irq, clr, set & ~clr);
 }
 
 void __init init_IRQ(void)
index d1f775e8635346e154d95a05dd2d2d85ff8f0c8c..9ffbf3a2dfeaa07ac6fd81bd154520d977250bd2 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
                return;
 
        if (cpu_is_at91cap9_revB())
-               set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
 
        /* Enable VBus control for UHP ports */
        for (i = 0; i < data->ports; i++) {
@@ -157,7 +157,7 @@ static struct platform_device at91_usba_udc_device = {
 void __init at91_add_device_usba(struct usba_platform_data *data)
 {
        if (cpu_is_at91cap9_revB()) {
-               set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
                at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS |
                                                  AT91_MATRIX_UDPHS_BYPASS_LOCK);
        }
@@ -861,7 +861,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
                return;
 
        if (cpu_is_at91cap9_revB())
-               set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
 
        at91_set_A_periph(AT91_PIN_PC1, 0);     /* LCDHSYNC */
        at91_set_A_periph(AT91_PIN_PC2, 0);     /* LCDDOTCK */
index af818a21587ceacf383d575908d008dd69ddd03c..4615528205c8329522b360b3b95e4fee4e89279c 100644 (file)
@@ -287,7 +287,7 @@ static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
        else
                wakeups[bank] &= ~mask;
 
-       set_irq_wake(gpio_chip[bank].bank->id, state);
+       irq_set_irq_wake(gpio_chip[bank].bank->id, state);
 
        return 0;
 }
@@ -375,6 +375,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
 
 static struct irq_chip gpio_irqchip = {
        .name           = "GPIO",
+       .irq_disable    = gpio_irq_mask,
        .irq_mask       = gpio_irq_mask,
        .irq_unmask     = gpio_irq_unmask,
        .irq_set_type   = gpio_irq_type,
@@ -384,16 +385,14 @@ static struct irq_chip gpio_irqchip = {
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
        unsigned        pin;
-       struct irq_desc *gpio;
-       struct at91_gpio_chip *at91_gpio;
-       void __iomem    *pio;
+       struct irq_data *idata = irq_desc_get_irq_data(desc);
+       struct irq_chip *chip = irq_data_get_irq_chip(idata);
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+       void __iomem    *pio = at91_gpio->regbase;
        u32             isr;
 
-       at91_gpio = get_irq_chip_data(irq);
-       pio = at91_gpio->regbase;
-
        /* temporarily mask (level sensitive) parent IRQ */
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
+       chip->irq_ack(idata);
        for (;;) {
                /* Reading ISR acks pending (edge triggered) GPIO interrupts.
                 * When there none are pending, we're finished unless we need
@@ -409,27 +408,15 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                }
 
                pin = at91_gpio->chip.base;
-               gpio = &irq_desc[pin];
 
                while (isr) {
-                       if (isr & 1) {
-                               if (unlikely(gpio->depth)) {
-                                       /*
-                                        * The core ARM interrupt handler lazily disables IRQs so
-                                        * another IRQ must be generated before it actually gets
-                                        * here to be disabled on the GPIO controller.
-                                        */
-                                       gpio_irq_mask(irq_get_irq_data(pin));
-                               }
-                               else
-                                       generic_handle_irq(pin);
-                       }
+                       if (isr & 1)
+                               generic_handle_irq(pin);
                        pin++;
-                       gpio++;
                        isr >>= 1;
                }
        }
-       desc->irq_data.chip->irq_unmask(&desc->irq_data);
+       chip->irq_unmask(idata);
        /* now it may re-trigger */
 }
 
@@ -518,14 +505,14 @@ void __init at91_gpio_irq_setup(void)
                __raw_writel(~0, this->regbase + PIO_IDR);
 
                for (i = 0, pin = this->chip.base; i < 32; i++, pin++) {
-                       lockdep_set_class(&irq_desc[pin].lock, &gpio_lock_class);
+                       irq_set_lockdep_class(pin, &gpio_lock_class);
 
                        /*
                         * Can use the "simple" and not "edge" handler since it's
                         * shorter, and the AIC handles interrupts sanely.
                         */
-                       set_irq_chip(pin, &gpio_irqchip);
-                       set_irq_handler(pin, handle_simple_irq);
+                       irq_set_chip_and_handler(pin, &gpio_irqchip,
+                                                handle_simple_irq);
                        set_irq_flags(pin, IRQF_VALID);
                }
 
@@ -536,8 +523,8 @@ void __init at91_gpio_irq_setup(void)
                if (prev && prev->next == this)
                        continue;
 
-               set_irq_chip_data(id, this);
-               set_irq_chained_handler(id, gpio_irq_handler);
+               irq_set_chip_data(id, this);
+               irq_set_chained_handler(id, gpio_irq_handler);
        }
        pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
 }
index 2d9b0af9c4d5fcf69c4280ab4be2dca69ff20eea..be510cfc56bebc1d5dfc5b7cd5514a04fed9befa 100644 (file)
@@ -89,7 +89,7 @@
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
  */
-#define AT91_SDRAMC    (0xffffea00 - AT91_BASE_SYS)
+#define AT91_SDRAMC0   (0xffffea00 - AT91_BASE_SYS)
 #define AT91_SMC       (0xffffec00 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
 #define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)
index b56d6b3a40876c31840181a1d8922c531bc2d38e..9665265ec757b6c50372e45649506f1590ab01db 100644 (file)
@@ -143,8 +143,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
                /* Active Low interrupt, with the specified priority */
                at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
 
-               set_irq_chip(i, &at91_aic_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 
                /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
index 84dcda0d1d9a4997ac2d761575050627a76c59e0..c48feaf4e8e9538655a7586c2a69fe340f87d0c8 100644 (file)
@@ -93,11 +93,11 @@ static void vic_init(void __iomem *base, struct irq_chip *chip,
        unsigned int i;
        for (i = 0; i < 32; i++) {
                unsigned int irq = irq_start + i;
-               set_irq_chip(irq, chip);
-               set_irq_chip_data(irq, base);
+               irq_set_chip(irq, chip);
+               irq_set_chip_data(irq, base);
 
                if (vic_sources & (1 << i)) {
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
        }
@@ -119,9 +119,9 @@ void __init bcmring_init_irq(void)
 
        /* special cases */
        if (INTCHW_INTC1_GPIO0 & IRQ_INTC1_VALID_MASK) {
-               set_irq_handler(IRQ_GPIO0, handle_simple_irq);
+               irq_set_handler(IRQ_GPIO0, handle_simple_irq);
        }
        if (INTCHW_INTC1_GPIO1 & IRQ_INTC1_VALID_MASK) {
-               set_irq_handler(IRQ_GPIO1, handle_simple_irq);
+               irq_set_handler(IRQ_GPIO1, handle_simple_irq);
        }
 }
index 86da7a1b2bbe045cd7c2cb1b8f7d016a48a225fd..c2eceee645e3ecac1b2d66fd94fd1b26a683b3e2 100644 (file)
@@ -112,13 +112,13 @@ void __init clps711x_init_irq(void)
 
        for (i = 0; i < NR_IRQS; i++) {
                if (INT1_IRQS & (1 << i)) {
-                       set_irq_handler(i, handle_level_irq);
-                       set_irq_chip(i, &int1_chip);
+                       irq_set_chip_and_handler(i, &int1_chip,
+                                                handle_level_irq);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }
                if (INT2_IRQS & (1 << i)) {
-                       set_irq_handler(i, handle_level_irq);
-                       set_irq_chip(i, &int2_chip);
+                       irq_set_chip_and_handler(i, &int2_chip,
+                                                handle_level_irq);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }                       
        }
index 9abc80a86a22b5bb1ac6c6b4fe734af3dc5dad28..f83152d643c5d58921a7b91a826a1790b7bbe4f9 100644 (file)
@@ -167,9 +167,9 @@ void __init cp_intc_init(void)
 
        /* Set up genirq dispatching for cp_intc */
        for (i = 0; i < num_irq; i++) {
-               set_irq_chip(i, &cp_intc_irq_chip);
+               irq_set_chip(i, &cp_intc_irq_chip);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-               set_irq_handler(i, handle_edge_irq);
+               irq_set_handler(i, handle_edge_irq);
        }
 
        /* Enable global interrupt */
index 20d66e5e4663bf230ecc9a23340026adce2c3cda..a0b838894ac99b27daaf413fbfbd8f78ae842066 100644 (file)
@@ -62,7 +62,7 @@ static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
 {
        struct davinci_gpio_regs __iomem *g;
 
-       g = (__force struct davinci_gpio_regs __iomem *)get_irq_chip_data(irq);
+       g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
 
        return g;
 }
@@ -208,7 +208,7 @@ pure_initcall(davinci_gpio_setup);
 static void gpio_irq_disable(struct irq_data *d)
 {
        struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_data(d);
+       u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
        __raw_writel(mask, &g->clr_falling);
        __raw_writel(mask, &g->clr_rising);
@@ -217,8 +217,8 @@ static void gpio_irq_disable(struct irq_data *d)
 static void gpio_irq_enable(struct irq_data *d)
 {
        struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_data(d);
-       unsigned status = irq_desc[d->irq].status;
+       u32 mask = (u32) irq_data_get_irq_handler_data(d);
+       unsigned status = irqd_get_trigger_type(d);
 
        status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
        if (!status)
@@ -233,21 +233,11 @@ static void gpio_irq_enable(struct irq_data *d)
 static int gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
        struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_data(d);
+       u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
 
-       irq_desc[d->irq].status &= ~IRQ_TYPE_SENSE_MASK;
-       irq_desc[d->irq].status |= trigger;
-
-       /* don't enable the IRQ if it's currently disabled */
-       if (irq_desc[d->irq].depth == 0) {
-               __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
-                            ? &g->set_falling : &g->clr_falling);
-               __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
-                            ? &g->set_rising : &g->clr_rising);
-       }
        return 0;
 }
 
@@ -256,6 +246,7 @@ static struct irq_chip gpio_irqchip = {
        .irq_enable     = gpio_irq_enable,
        .irq_disable    = gpio_irq_disable,
        .irq_set_type   = gpio_irq_type,
+       .flags          = IRQCHIP_SET_TYPE_MASKED,
 };
 
 static void
@@ -285,7 +276,7 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                        status >>= 16;
 
                /* now demux them to the right lowlevel handler */
-               n = (int)get_irq_data(irq);
+               n = (int)irq_get_handler_data(irq);
                while (status) {
                        res = ffs(status);
                        n += res;
@@ -323,7 +314,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
 static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
 {
        struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_data(d);
+       u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
@@ -395,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
                irq = bank_irq;
-               gpio_irqchip_unbanked = *get_irq_desc_chip(irq_to_desc(irq));
+               gpio_irqchip_unbanked = *irq_get_chip(irq);
                gpio_irqchip_unbanked.name = "GPIO-AINTC";
                gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
 
@@ -406,10 +397,10 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* set the direct IRQs up to use that irqchip */
                for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-                       set_irq_chip(irq, &gpio_irqchip_unbanked);
-                       set_irq_data(irq, (void *) __gpio_mask(gpio));
-                       set_irq_chip_data(irq, (__force void *) g);
-                       irq_desc[irq].status |= IRQ_TYPE_EDGE_BOTH;
+                       irq_set_chip(irq, &gpio_irqchip_unbanked);
+                       irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+                       irq_set_chip_data(irq, (__force void *)g);
+                       irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
                }
 
                goto done;
@@ -430,15 +421,15 @@ static int __init davinci_gpio_irq_setup(void)
                __raw_writel(~0, &g->clr_rising);
 
                /* set up all irqs in this bank */
-               set_irq_chained_handler(bank_irq, gpio_irq_handler);
-               set_irq_chip_data(bank_irq, (__force void *) g);
-               set_irq_data(bank_irq, (void *) irq);
+               irq_set_chained_handler(bank_irq, gpio_irq_handler);
+               irq_set_chip_data(bank_irq, (__force void *)g);
+               irq_set_handler_data(bank_irq, (void *)irq);
 
                for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
-                       set_irq_chip(irq, &gpio_irqchip);
-                       set_irq_chip_data(irq, (__force void *) g);
-                       set_irq_data(irq, (void *) __gpio_mask(gpio));
-                       set_irq_handler(irq, handle_simple_irq);
+                       irq_set_chip(irq, &gpio_irqchip);
+                       irq_set_chip_data(irq, (__force void *)g);
+                       irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+                       irq_set_handler(irq, handle_simple_irq);
                        set_irq_flags(irq, IRQF_VALID);
                }
 
index 5e05c9b64e1fa17e0c74d40e299b3babc9f68581..e6269a6e0014fb49b92a5ee8bd5820397885913c 100644 (file)
@@ -154,11 +154,11 @@ void __init davinci_irq_init(void)
 
        /* set up genirq dispatch for ARM INTC */
        for (i = 0; i < davinci_soc_info.intc_irq_num; i++) {
-               set_irq_chip(i, &davinci_irq_chip_0);
+               irq_set_chip(i, &davinci_irq_chip_0);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                if (i != IRQ_TINT1_TINT34)
-                       set_irq_handler(i, handle_edge_irq);
+                       irq_set_handler(i, handle_edge_irq);
                else
-                       set_irq_handler(i, handle_level_irq);
+                       irq_set_handler(i, handle_level_irq);
        }
 }
index 101707fa2e2c431dee218820370a9a4dbca6a8d2..f07fd16e0c9b010243f6df4765743633797ad472 100644 (file)
@@ -86,8 +86,7 @@ static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
                if (!(cause & (1 << irq)))
                        continue;
                irq = pmu_to_irq(irq);
-               desc = irq_desc + irq;
-               desc_handle_irq(irq, desc);
+               generic_handle_irq(irq);
        }
 }
 
@@ -103,14 +102,14 @@ void __init dove_init_irq(void)
         */
        orion_gpio_init(0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START);
-       set_irq_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
 
        orion_gpio_init(32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START + 32);
-       set_irq_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
 
        orion_gpio_init(64, 8, DOVE_GPIO2_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START + 64);
@@ -122,10 +121,9 @@ void __init dove_init_irq(void)
        writel(0, PMU_INTERRUPT_CAUSE);
 
        for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) {
-               set_irq_chip(i, &pmu_irq_chip);
-               set_irq_handler(i, handle_level_irq);
-               irq_desc[i].status |= IRQ_LEVEL;
+               irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq);
+               irq_set_status_flags(i, IRQ_LEVEL);
                set_irq_flags(i, IRQF_VALID);
        }
-       set_irq_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
+       irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
 }
index 7df083f37fa761b4bead3f52d1b65f27e4265c1b..087bc771ac23dfb770baf717e8487dbece2b5cce 100644 (file)
@@ -66,8 +66,8 @@ static void __init ebsa110_init_irq(void)
        local_irq_restore(flags);
 
        for (irq = 0; irq < NR_IRQS; irq++) {
-               set_irq_chip(irq, &ebsa110_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ebsa110_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index 34e071d79761131a3897a94436c6d00432470ffe..180b8a9d0d2154ef60e680d278e05456f3b67dd4 100644 (file)
@@ -117,7 +117,7 @@ static void ep93xx_gpio_irq_ack(struct irq_data *d)
        int port = line >> 3;
        int port_mask = 1 << (line & 7);
 
-       if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+       if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
                gpio_int_type2[port] ^= port_mask; /* switch edge direction */
                ep93xx_gpio_update_int_params(port);
        }
@@ -131,7 +131,7 @@ static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
        int port = line >> 3;
        int port_mask = 1 << (line & 7);
 
-       if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+       if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
                gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 
        gpio_int_unmasked[port] &= ~port_mask;
@@ -165,10 +165,10 @@ static void ep93xx_gpio_irq_unmask(struct irq_data *d)
  */
 static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
-       struct irq_desc *desc = irq_desc + d->irq;
        const int gpio = irq_to_gpio(d->irq);
        const int port = gpio >> 3;
        const int port_mask = 1 << (gpio & 7);
+       irq_flow_handler_t handler;
 
        gpio_direction_input(gpio);
 
@@ -176,22 +176,22 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
        case IRQ_TYPE_EDGE_RISING:
                gpio_int_type1[port] |= port_mask;
                gpio_int_type2[port] |= port_mask;
-               desc->handle_irq = handle_edge_irq;
+               handler = handle_edge_irq;
                break;
        case IRQ_TYPE_EDGE_FALLING:
                gpio_int_type1[port] |= port_mask;
                gpio_int_type2[port] &= ~port_mask;
-               desc->handle_irq = handle_edge_irq;
+               handler = handle_edge_irq;
                break;
        case IRQ_TYPE_LEVEL_HIGH:
                gpio_int_type1[port] &= ~port_mask;
                gpio_int_type2[port] |= port_mask;
-               desc->handle_irq = handle_level_irq;
+               handler = handle_level_irq;
                break;
        case IRQ_TYPE_LEVEL_LOW:
                gpio_int_type1[port] &= ~port_mask;
                gpio_int_type2[port] &= ~port_mask;
-               desc->handle_irq = handle_level_irq;
+               handler = handle_level_irq;
                break;
        case IRQ_TYPE_EDGE_BOTH:
                gpio_int_type1[port] |= port_mask;
@@ -200,17 +200,16 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
                        gpio_int_type2[port] &= ~port_mask; /* falling */
                else
                        gpio_int_type2[port] |= port_mask; /* rising */
-               desc->handle_irq = handle_edge_irq;
+               handler = handle_edge_irq;
                break;
        default:
                pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
                return -EINVAL;
        }
 
-       gpio_int_enabled[port] |= port_mask;
+       __irq_set_handler_locked(d->irq, handler);
 
-       desc->status &= ~IRQ_TYPE_SENSE_MASK;
-       desc->status |= type & IRQ_TYPE_SENSE_MASK;
+       gpio_int_enabled[port] |= port_mask;
 
        ep93xx_gpio_update_int_params(port);
 
@@ -232,20 +231,29 @@ void __init ep93xx_gpio_init_irq(void)
 
        for (gpio_irq = gpio_to_irq(0);
             gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
-               set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
-               set_irq_handler(gpio_irq, handle_level_irq);
+               irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(gpio_irq, IRQF_VALID);
        }
 
-       set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
-       set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
+                               ep93xx_gpio_ab_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
+                               ep93xx_gpio_f_irq_handler);
+       irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
+                               ep93xx_gpio_f_irq_handler);
 }
 
 
index a021b5240bbad60d3d53f09a60ff4b1ade3e770f..e849f67be47da3bba5210d8d1f5b509d8c5a67b4 100644 (file)
@@ -20,6 +20,11 @@ config EXYNOS4_MCT
        help
          Use MCT (Multi Core Timer) as kernel timers
 
+config EXYNOS4_DEV_AHCI
+       bool
+       help
+         Compile in platform device definitions for AHCI
+
 config EXYNOS4_DEV_PD
        bool
        help
@@ -134,9 +139,9 @@ config MACH_ARMLEX4210
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
+       select EXYNOS4_DEV_AHCI
        select EXYNOS4_DEV_SYSMMU
        select EXYNOS4_SETUP_SDHCI
-       select SATA_AHCI_PLATFORM
        help
          Machine support for Samsung ARMLEX4210 based on EXYNOS4210
 
index b8f0e7d82d7e5fed41fe5f470efa3879d0622ceb..9be104f63c0b9626bb3bc5b96835efffe8229ffe 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_MACH_NURI)                       += mach-nuri.o
 # device support
 
 obj-y                                  += dev-audio.o
+obj-$(CONFIG_EXYNOS4_DEV_AHCI)         += dev-ahci.o
 obj-$(CONFIG_EXYNOS4_DEV_PD)           += dev-pd.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)       += dev-sysmmu.o
 
@@ -53,4 +54,3 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7)      += setup-i2c7.o
 obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)     += setup-keypad.o
 obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)      += setup-sdhci.o
 obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
-obj-$(CONFIG_SATA_AHCI_PLATFORM)       += dev-ahci.o
index 58bbd049a6c44ef494a1d25eb688dd92863f038e..a442ef861167866c638cde508d9ca3af87a9298b 100644 (file)
@@ -21,8 +21,8 @@
         */
 
        .macro addruart, rp, rv
-               ldreq   \rp, = S3C_PA_UART
-               ldrne   \rv, = S3C_VA_UART
+               ldr     \rp, = S3C_PA_UART
+               ldr     \rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
                add     \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
                add     \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
index 31618d91ce15902cd00b4bea30e24999aa00e078..f488b66d6806286d6d5a48fd0f11f677b9ebb0a8 100644 (file)
@@ -54,8 +54,8 @@ static void combiner_unmask_irq(struct irq_data *data)
 
 static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct combiner_chip_data *chip_data = get_irq_data(irq);
-       struct irq_chip *chip = get_irq_chip(irq);
+       struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_get_chip(irq);
        unsigned int cascade_irq, combiner_irq;
        unsigned long status;
 
@@ -93,9 +93,9 @@ void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
 {
        if (combiner_nr >= MAX_COMBINER_NR)
                BUG();
-       if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
+       if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
                BUG();
-       set_irq_chained_handler(irq, combiner_handle_cascade_irq);
+       irq_set_chained_handler(irq, combiner_handle_cascade_irq);
 }
 
 void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
@@ -119,9 +119,8 @@ void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
 
        for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
                                + MAX_IRQ_IN_COMBINER; i++) {
-               set_irq_chip(i, &combiner_chip);
-               set_irq_chip_data(i, &combiner_data[combiner_nr]);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
+               irq_set_chip_data(i, &combiner_data[combiner_nr]);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 }
index 4f7ad4a796e4ce87e6d8dfe7966720b50b4fe9b0..9d87d2ac7f687303547a57aece1fd19f10d91384 100644 (file)
@@ -190,8 +190,8 @@ static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 
 static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
-       u32 *irq_data = get_irq_data(irq);
-       struct irq_chip *chip = get_irq_chip(irq);
+       u32 *irq_data = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_get_chip(irq);
 
        chip->irq_mask(&desc->irq_data);
 
@@ -208,18 +208,19 @@ int __init exynos4_init_irq_eint(void)
        int irq;
 
        for (irq = 0 ; irq <= 31 ; irq++) {
-               set_irq_chip(IRQ_EINT(irq), &exynos4_irq_eint);
-               set_irq_handler(IRQ_EINT(irq), handle_level_irq);
+               irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
+                                        handle_level_irq);
                set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
        }
 
-       set_irq_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+       irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
 
        for (irq = 0 ; irq <= 15 ; irq++) {
                eint0_15_data[irq] = IRQ_EINT(irq);
 
-               set_irq_data(exynos4_get_irq_nr(irq), &eint0_15_data[irq]);
-               set_irq_chained_handler(exynos4_get_irq_nr(irq),
+               irq_set_handler_data(exynos4_get_irq_nr(irq),
+                                    &eint0_15_data[irq]);
+               irq_set_chained_handler(exynos4_get_irq_nr(irq),
                                        exynos4_irq_eint0_15);
        }
 
index 25a256818122c0ae135544022bbb358f54942bfd..e645f7a955f0dd504788547fc9753fabbe0178ae 100644 (file)
@@ -125,7 +125,7 @@ static struct resource smdkc210_smsc911x_resources[] = {
 };
 
 static struct smsc911x_platform_config smsc9215_config = {
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
        .flags          = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
        .phy_interface  = PHY_INTERFACE_MODE_MII,
index 88e0275143be3e769888aaa48615ee9a1105904e..152676471b67d4fb7f219c3bedf1eaa5de560ca5 100644 (file)
@@ -127,7 +127,7 @@ static struct resource smdkv310_smsc911x_resources[] = {
 };
 
 static struct smsc911x_platform_config smsc9215_config = {
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
        .flags          = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
        .phy_interface  = PHY_INTERFACE_MODE_MII,
index 84c5f258f2d87d40e1de00055c2957daee8b4e6f..38a44f9b9da255affb155c4503e4641a5974b42a 100644 (file)
@@ -102,8 +102,7 @@ static void __init __fb_init_irq(void)
        *CSR_FIQ_DISABLE = -1;
 
        for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
-               set_irq_chip(irq, &fb_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index a921fe92b858c730d5c5669602b8aa58f435f588..5f1f9867fc70eedff4620119fead758eb7c0e2b2 100644 (file)
@@ -30,7 +30,7 @@ static int cksrc_dc21285_enable(struct clocksource *cs)
        return 0;
 }
 
-static int cksrc_dc21285_disable(struct clocksource *cs)
+static void cksrc_dc21285_disable(struct clocksource *cs)
 {
        *CSR_TIMER2_CNTL = 0;
 }
index de7a5cb5dbe1abe9a578d10dcdf7b0c467bce63d..c3a0abbc9049a67db7a539c2540572d3033ccef9 100644 (file)
@@ -151,14 +151,14 @@ void __init isa_init_irq(unsigned int host_irq)
 
        if (host_irq != (unsigned int)-1) {
                for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
-                       set_irq_chip(irq, &isa_lo_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &isa_lo_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
 
                for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
-                       set_irq_chip(irq, &isa_hi_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &isa_hi_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
 
@@ -166,7 +166,7 @@ void __init isa_init_irq(unsigned int host_irq)
                request_resource(&ioport_resource, &pic2_resource);
                setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
 
-               set_irq_chained_handler(host_irq, isa_irq_handler);
+               irq_set_chained_handler(host_irq, isa_irq_handler);
 
                /*
                 * On the NetWinder, don't automatically
index fa3d333f21e1e54c9f237f52c7b845ec4917050e..fdc7ef1391d3868a96bba536fa05fe294cf168ce 100644 (file)
@@ -127,8 +127,8 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
 
 static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
+       unsigned int port = (unsigned int)irq_desc_get_handler_data(desc);
        unsigned int gpio_irq_no, irq_stat;
-       unsigned int port = (unsigned int)get_irq_data(irq);
 
        irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);
 
@@ -138,9 +138,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                if ((irq_stat & 1) == 0)
                        continue;
 
-               BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
-               irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
-                               &irq_desc[gpio_irq_no]);
+               generic_handle_irq(gpio_irq_no);
        }
 }
 
@@ -219,13 +217,13 @@ void __init gemini_gpio_init(void)
 
                for (j = GPIO_IRQ_BASE + i * 32;
                     j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
-                       set_irq_chip(j, &gpio_irq_chip);
-                       set_irq_handler(j, handle_edge_irq);
+                       irq_set_chip_and_handler(j, &gpio_irq_chip,
+                                                handle_edge_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
 
-               set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
-               set_irq_data(IRQ_GPIO(i), (void *)i);
+               irq_set_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
+               irq_set_handler_data(IRQ_GPIO(i), (void *)i);
        }
 
        BUG_ON(gpiochip_add(&gemini_gpio_chip));
index 96bc227dd8496c802db1f4e19745cb403e9b3a88..9485a8fdf851cf2a6c50f7530dd9d3c8b330fc16 100644 (file)
@@ -81,13 +81,13 @@ void __init gemini_init_irq(void)
        request_resource(&iomem_resource, &irq_resource);
 
        for (i = 0; i < NR_IRQS; i++) {
-               set_irq_chip(i, &gemini_irq_chip);
+               irq_set_chip(i, &gemini_irq_chip);
                if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) {
-                       set_irq_handler(i, handle_edge_irq);
+                       irq_set_handler(i, handle_edge_irq);
                        mode |= 1 << i;
                        level |= 1 << i;
                } else {                        
-                       set_irq_handler(i, handle_level_irq);
+                       irq_set_handler(i, handle_level_irq);
                }
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
index 1f28c90932c754d082848af2f85e9fba45f75b08..51d4e44ab9734bad131efb0f4c11c399b729eedc 100644 (file)
@@ -199,29 +199,29 @@ void __init h720x_init_irq (void)
 
        /* Initialize global IRQ's, fast path */
        for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
-               set_irq_chip(irq, &h720x_global_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &h720x_global_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /* Initialize multiplexed IRQ's, slow path */
        for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
-               set_irq_chip(irq, &h720x_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &h720x_gpio_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
-       set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
-       set_irq_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
-       set_irq_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
-       set_irq_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
+       irq_set_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
+       irq_set_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
+       irq_set_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
+       irq_set_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
 
 #ifdef CONFIG_CPU_H7202
        for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
-               set_irq_chip(irq, &h720x_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &h720x_gpio_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
-       set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
+       irq_set_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
 #endif
 
        /* Enable multiplexed irq's */
index ac3f91442376f2999f971e08e023f705143fe34d..c37d570b852dcb24410d382cc7322affea8dddef 100644 (file)
@@ -141,13 +141,18 @@ h7202_timer_interrupt(int irq, void *dev_id)
 /*
  * mask multiplexed timer IRQs
  */
-static void inline mask_timerx_irq(struct irq_data *d)
+static void inline __mask_timerx_irq(unsigned int irq)
 {
        unsigned int bit;
-       bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
+       bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
 }
 
+static void inline mask_timerx_irq(struct irq_data *d)
+{
+       __mask_timerx_irq(d->irq);
+}
+
 /*
  * unmask multiplexed timer IRQs
  */
@@ -196,12 +201,12 @@ void __init h7202_init_irq (void)
 
        for (irq = IRQ_TIMER1;
                          irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
-               mask_timerx_irq(irq);
-               set_irq_chip(irq, &h7202_timerx_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               __mask_timerx_irq(irq);
+               irq_set_chip_and_handler(irq, &h7202_timerx_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
-       set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
+       irq_set_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
 
        h720x_init_irq();
 }
index a233470dd10c8486031ced12f37b0ce31ab18ddb..bc739701c3014861fce43f525f0273e7dd8502e9 100644 (file)
@@ -224,15 +224,15 @@ void __init iop13xx_init_irq(void)
 
        for(i = 0; i <= IRQ_IOP13XX_HPI; i++) {
                if (i < 32)
-                       set_irq_chip(i, &iop13xx_irqchip1);
+                       irq_set_chip(i, &iop13xx_irqchip1);
                else if (i < 64)
-                       set_irq_chip(i, &iop13xx_irqchip2);
+                       irq_set_chip(i, &iop13xx_irqchip2);
                else if (i < 96)
-                       set_irq_chip(i, &iop13xx_irqchip3);
+                       irq_set_chip(i, &iop13xx_irqchip3);
                else
-                       set_irq_chip(i, &iop13xx_irqchip4);
+                       irq_set_chip(i, &iop13xx_irqchip4);
 
-               set_irq_handler(i, handle_level_irq);
+               irq_set_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
index c9c02e3698bc6d0cb2f348125c802788c6af3aed..560d5b2dec2270c00e06bebbe8bac54d7caa8585 100644 (file)
@@ -118,7 +118,7 @@ static void iop13xx_msi_handler(unsigned int irq, struct irq_desc *desc)
 
 void __init iop13xx_msi_init(void)
 {
-       set_irq_chained_handler(IRQ_IOP13XX_INBD_MSI, iop13xx_msi_handler);
+       irq_set_chained_handler(IRQ_IOP13XX_INBD_MSI, iop13xx_msi_handler);
 }
 
 /*
@@ -178,7 +178,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
+       irq_set_msi_desc(irq, desc);
 
        msg.address_hi = 0x0;
        msg.address_lo = IOP13XX_MU_MIMR_PCI;
@@ -187,7 +187,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
        msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f);
 
        write_msi_msg(irq, &msg);
-       set_irq_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
+       irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
 
        return 0;
 }
index d3426a120599e95617e8c82b954208244184ad09..d7ee2789d890a19b1db52f3015db818188de4c78 100644 (file)
@@ -68,8 +68,7 @@ void __init iop32x_init_irq(void)
                *IOP3XX_PCIIRSR = 0x0f;
 
        for (i = 0; i < NR_IRQS; i++) {
-               set_irq_chip(i, &ext_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &ext_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 }
index 0ff2f74363a51313cbb8c5d1e601bba3e5384370..f7f5d3e451c7a8cad27dbd4000c96cd085a36b60 100644 (file)
@@ -110,8 +110,9 @@ void __init iop33x_init_irq(void)
                *IOP3XX_PCIIRSR = 0x0f;
 
        for (i = 0; i < NR_IRQS; i++) {
-               set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i,
+                                        (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 }
index 5fc4e064b6504268122f988438de1c9d10ab0552..4068166c899384903206e2f4325049639712a480 100644 (file)
@@ -476,8 +476,8 @@ void __init ixp2000_init_irq(void)
         */
        for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
                if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
-                       set_irq_chip(irq, &ixp2000_irq_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &ixp2000_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                } else set_irq_flags(irq, 0);
        }
@@ -485,21 +485,21 @@ void __init ixp2000_init_irq(void)
        for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
                if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
                                IXP2000_VALID_ERR_IRQ_MASK) {
-                       set_irq_chip(irq, &ixp2000_err_irq_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &ixp2000_err_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                }
                else
                        set_irq_flags(irq, 0);
        }
-       set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
+       irq_set_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
 
        for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
-               set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ixp2000_GPIO_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
-       set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
+       irq_set_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
 
        /*
         * Enable PCI irqs.  The actual PCI[AB] decoding is done in
@@ -508,8 +508,8 @@ void __init ixp2000_init_irq(void)
         */
        ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
        for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
-               set_irq_chip(irq, &ixp2000_pci_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ixp2000_pci_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
index 7d90d3f13ee87046b40651bf1bf529a8530b7500..235638f800e55795629597f1de58d82ed1456715 100644 (file)
@@ -158,13 +158,13 @@ void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigne
        *board_irq_mask = 0xffffffff;
 
        for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
-               set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ixdp2x00_cpld_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
        /* Hook into PCI interrupt */
-       set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
+       irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
 }
 
 /*************************************************************************
index 34b1b2af37c82fe9f78774749e5b48709d5b4928..84835b2095579a671d8bfb4a270d22c712a52bbb 100644 (file)
@@ -115,8 +115,8 @@ void __init ixdp2x01_init_irq(void)
 
        for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
                if (irq & valid_irq_mask) {
-                       set_irq_chip(irq, &ixdp2x01_irq_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &ixdp2x01_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                } else {
                        set_irq_flags(irq, 0);
@@ -124,7 +124,7 @@ void __init ixdp2x01_init_irq(void)
        }
 
        /* Hook into PCI interrupts */
-       set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
+       irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
 }
 
 
index 9c8a3390321675a656a3a54d424e8f3e8bf82a91..a1bee33d183ea871f72d9ffaef8f4265c3a8b40f 100644 (file)
@@ -289,12 +289,12 @@ static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
 {
        switch (type) {
        case IXP23XX_IRQ_LEVEL:
-               set_irq_chip(irq, &ixp23xx_irq_level_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ixp23xx_irq_level_chip,
+                                        handle_level_irq);
                break;
        case IXP23XX_IRQ_EDGE:
-               set_irq_chip(irq, &ixp23xx_irq_edge_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &ixp23xx_irq_edge_chip,
+                                        handle_edge_irq);
                break;
        }
        set_irq_flags(irq, IRQF_VALID);
@@ -324,12 +324,12 @@ void __init ixp23xx_init_irq(void)
        }
 
        for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
-               set_irq_chip(irq, &ixp23xx_pci_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &ixp23xx_pci_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
+       irq_set_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
 }
 
 
index 181116aa6591236715b138951208e9860576da04..8dcba17c81e78489f751058506b1fc959d477d0c 100644 (file)
@@ -136,8 +136,8 @@ void __init ixdp2351_init_irq(void)
             irq++) {
                if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
                        set_irq_flags(irq, IRQF_VALID);
-                       set_irq_handler(irq, handle_level_irq);
-                       set_irq_chip(irq, &ixdp2351_inta_chip);
+                       irq_set_chip_and_handler(irq, &ixdp2351_inta_chip,
+                                                handle_level_irq);
                }
        }
 
@@ -147,13 +147,13 @@ void __init ixdp2351_init_irq(void)
             irq++) {
                if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
                        set_irq_flags(irq, IRQF_VALID);
-                       set_irq_handler(irq, handle_level_irq);
-                       set_irq_chip(irq, &ixdp2351_intb_chip);
+                       irq_set_chip_and_handler(irq, &ixdp2351_intb_chip,
+                                                handle_level_irq);
                }
        }
 
-       set_irq_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
-       set_irq_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
+       irq_set_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
+       irq_set_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
 }
 
 /*
index 76c61ba73218778987cec85683909e70ccf897fa..8fe0c6273262bbe26029736fc968a55d074b2495 100644 (file)
@@ -110,8 +110,8 @@ static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 
 static void __init roadrunner_pci_preinit(void)
 {
-       set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
 
        ixp23xx_pci_preinit();
 }
index 845e1b5005484d0bfb79c6e8a0993951d3dc0341..162043ff29ff5af56ac045ec55732c205f048d81 100644 (file)
 
 void __init avila_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 9fd894271d5d0b353ca1e5214af258d22f99f686..ed19bc3143184571b3ffebe8a821947be58fd4f1 100644 (file)
@@ -252,8 +252,8 @@ void __init ixp4xx_init_irq(void)
 
         /* Default to all level triggered */
        for(i = 0; i < NR_IRQS; i++) {
-               set_irq_chip(i, &ixp4xx_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &ixp4xx_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 }
index b978ea8bd6f09ed723aa18d2d7b7f23ceef93363..37fda7d6e83da4896746b60552e411e0265ff022 100644 (file)
@@ -32,8 +32,8 @@
 
 void __init coyote_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index fa70fed462babf1a20dc2a0eba30313b726666b4..c7612010b3fc982c9cdc002ab3b998356e7e95b9 100644 (file)
 
 void __init dsmg600_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 5a810c930624cb0768259fc19043d32f8cfbda46..44ccde9d4879b02c79eec491e8864677de8c4853 100644 (file)
@@ -32,9 +32,9 @@
 
 void __init fsg_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 7e93a0975c4d0ef4de231d67a5650fa43eb6b15c..fc11241688740df0077c036f1cc4f46574d3ff74 100644 (file)
@@ -29,8 +29,8 @@
 
 void __init gateway7001_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index d0e4861ac03d5bc39c0f201d60e956f43559c28a..3e8c0e33b59ce46db2c83169ee2c616b809937e5 100644 (file)
@@ -420,8 +420,8 @@ static void __init gmlr_init(void)
        gpio_line_config(GPIO_HSS1_RTS_N, IXP4XX_GPIO_OUT);
        gpio_line_config(GPIO_HSS0_DCD_N, IXP4XX_GPIO_IN);
        gpio_line_config(GPIO_HSS1_DCD_N, IXP4XX_GPIO_IN);
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
 
        set_control(CONTROL_HSS0_DTR_N, 1);
        set_control(CONTROL_HSS1_DTR_N, 1);
@@ -441,10 +441,10 @@ static void __init gmlr_init(void)
 #ifdef CONFIG_PCI
 static void __init gmlr_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 25d2c333c2045f2e353b26ce3f74292a2cf69d4e..38cc0725dbd855cc4a6d147450ec5c0176479626 100644 (file)
@@ -43,8 +43,8 @@
  */
 void __init gtwx5715_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 1ba165a6edaca3b0b77583a7e7380c3ffe021f01..58f400417eaff182302164431a6dce138fccd527 100644 (file)
 
 void __init ixdp425_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 4ed7ac6149209448cba57dd42d49c28bb2a9eb7e..e64f6d04148866fe321ee5e9c91c29baa07a6495 100644 (file)
@@ -25,8 +25,8 @@
 
 void __init ixdpg425_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index d0cea34cf61e4987d164895eee0b2208af004b0b..428d1202b7990e0df6c29f59a24e9df923ebc556 100644 (file)
 
 void __init nas100d_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 1eb5a90470bc58e031d29942dcdfb66955352799..2e85f76b950de0711c3e94f6d176dba22961ba9a 100644 (file)
@@ -32,9 +32,9 @@
 
 void __init nslu2_pci_preinit(void)
 {
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index f3111c6840efe6c110108bd7e24ba6b221651e94..03bdec5140a79f4515b8ed17018ab4fb77e3e68e 100644 (file)
@@ -38,8 +38,8 @@ void __init vulcan_pci_preinit(void)
        pr_info("Vulcan PCI: limiting CardBus memory size to %dMB\n",
                (int)(pci_cardbus_mem_size >> 20));
 #endif
-       set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
        ixp4xx_pci_preinit();
 }
 
index 9b59ed03b15133713a0cf91939122d6e7569276b..17f3cf59a31beb95e6651c6c01aa0de070709090 100644 (file)
@@ -29,8 +29,8 @@
 
 void __init wg302v2_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index cbdb5863d13b0df2e44d1618583ba43783d8f683..05d193a25b250d73c90830c52050e106e70eddca 100644 (file)
@@ -35,14 +35,15 @@ void __init kirkwood_init_irq(void)
         */
        orion_gpio_init(0, 32, GPIO_LOW_VIRT_BASE, 0,
                        IRQ_KIRKWOOD_GPIO_START);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
 
        orion_gpio_init(32, 18, GPIO_HIGH_VIRT_BASE, 0,
                        IRQ_KIRKWOOD_GPIO_START + 32);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23,
+                               gpio_irq_handler);
 }
index 55fbf7111a5bd3fb5e720fd68e2c023b965f9dcb..31e456508a6f4d83adbf06d256216a717dd1b96c 100644 (file)
@@ -80,7 +80,7 @@ int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
        local_irq_restore(flags);
 
        /* Set IRQ triggering type */
-       set_irq_type(gpio_irq[pin], type);
+       irq_set_irq_type(gpio_irq[pin], type);
 
        /* enable interrupt mode */
        ks8695_gpio_mode(pin, 0);
index 7998ccaa63331bd06939326d14a0182c82b8df66..a78092dcd6fb88333221727c6e95b54f4dda088d 100644 (file)
@@ -115,12 +115,12 @@ static int ks8695_irq_set_type(struct irq_data *d, unsigned int type)
        }
 
        if (level_triggered) {
-               set_irq_chip(d->irq, &ks8695_irq_level_chip);
-               set_irq_handler(d->irq, handle_level_irq);
+               irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip,
+                                        handle_level_irq);
        }
        else {
-               set_irq_chip(d->irq, &ks8695_irq_edge_chip);
-               set_irq_handler(d->irq, handle_edge_irq);
+               irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip,
+                                        handle_edge_irq);
        }
 
        __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
@@ -158,16 +158,18 @@ void __init ks8695_init_irq(void)
                        case KS8695_IRQ_UART_RX:
                        case KS8695_IRQ_COMM_TX:
                        case KS8695_IRQ_COMM_RX:
-                               set_irq_chip(irq, &ks8695_irq_level_chip);
-                               set_irq_handler(irq, handle_level_irq);
+                               irq_set_chip_and_handler(irq,
+                                                        &ks8695_irq_level_chip,
+                                                        handle_level_irq);
                                break;
 
                        /* Edge-triggered interrupts */
                        default:
                                /* clear pending bit */
                                ks8695_irq_ack(irq_get_irq_data(irq));
-                               set_irq_chip(irq, &ks8695_irq_edge_chip);
-                               set_irq_handler(irq, handle_edge_irq);
+                               irq_set_chip_and_handler(irq,
+                                                        &ks8695_irq_edge_chip,
+                                                        handle_edge_irq);
                }
 
                set_irq_flags(irq, IRQF_VALID);
index 316ecbf6c586a6874e1855e3e5a9cb81f7238069..4eae566dfdc710934e7e834cabd7b2e83c1184cd 100644 (file)
@@ -290,7 +290,7 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
        }
 
        /* Ok to use the level handler for all types */
-       set_irq_handler(d->irq, handle_level_irq);
+       irq_set_handler(d->irq, handle_level_irq);
 
        return 0;
 }
@@ -390,8 +390,8 @@ void __init lpc32xx_init_irq(void)
 
        /* Configure supported IRQ's */
        for (i = 0; i < NR_IRQS; i++) {
-               set_irq_chip(i, &lpc32xx_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
@@ -406,8 +406,8 @@ void __init lpc32xx_init_irq(void)
        __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
 
        /* MIC SUBIRQx interrupts will route handling to the chain handlers */
-       set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
-       set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
+       irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
+       irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
 
        /* Initially disable all wake events */
        __raw_writel(0, LPC32XX_CLKPWR_P01_ER);
index fa037038e7b839632f905b489356b33201bb6d39..d21c5441a3d0c7c8e0649376b4556d29b6e44cd5 100644 (file)
@@ -110,9 +110,9 @@ static void init_mux_irq(struct irq_chip *chip, int start, int num)
                if (chip->irq_ack)
                        chip->irq_ack(d);
 
-               set_irq_chip(irq, chip);
+               irq_set_chip(irq, chip);
                set_irq_flags(irq, IRQF_VALID);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_handler(irq, handle_level_irq);
        }
 }
 
@@ -122,7 +122,7 @@ void __init mmp2_init_icu(void)
 
        for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
                icu_mask_irq(irq_get_irq_data(irq));
-               set_irq_chip(irq, &icu_irq_chip);
+               irq_set_chip(irq, &icu_irq_chip);
                set_irq_flags(irq, IRQF_VALID);
 
                switch (irq) {
@@ -133,7 +133,7 @@ void __init mmp2_init_icu(void)
                case IRQ_MMP2_SSP_MUX:
                        break;
                default:
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_handler(irq, handle_level_irq);
                        break;
                }
        }
@@ -149,9 +149,9 @@ void __init mmp2_init_icu(void)
        init_mux_irq(&misc_irq_chip, IRQ_MMP2_MISC_BASE, 15);
        init_mux_irq(&ssp_irq_chip, IRQ_MMP2_SSP_BASE, 2);
 
-       set_irq_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
-       set_irq_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
-       set_irq_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
-       set_irq_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
-       set_irq_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
+       irq_set_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
+       irq_set_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
+       irq_set_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
+       irq_set_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
+       irq_set_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
 }
index f86b450cb93c86daf0923f7fdbf086e17df16ebd..89706a0d08f1541c5293bee6ae7dfbdf30b151ad 100644 (file)
@@ -48,8 +48,7 @@ void __init icu_init_irq(void)
 
        for (irq = 0; irq < 64; irq++) {
                icu_mask_irq(irq_get_irq_data(irq));
-               set_irq_chip(irq, &icu_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
index 1993721d472edf422f35e2ff7b1423b16866f7ab..35c7ceeb3f29bfa1b7cb7aa606dfe7930a543712 100644 (file)
@@ -53,7 +53,7 @@ static void __init msm8960_init_irq(void)
         */
        for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
                if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-                       set_irq_handler(i, handle_percpu_irq);
+                       irq_set_handler(i, handle_percpu_irq);
        }
 }
 
index b3c55f138fce8909250cc51d642f462d91a1c524..1163b6fd05d2ceb71ae21b5b3bef550a65ba3ca6 100644 (file)
@@ -56,7 +56,7 @@ static void __init msm8x60_init_irq(void)
         */
        for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
                if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-                       set_irq_handler(i, handle_percpu_irq);
+                       irq_set_handler(i, handle_percpu_irq);
        }
 }
 
index 31117a4499c4bcb543904e0fbad05202df7111d6..87e1d01edecc5d35046f2e4b7fe56b3011fd3c7c 100644 (file)
@@ -214,17 +214,17 @@ int __init trout_init_gpio(void)
 {
        int i;
        for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
-               set_irq_chip(i, &trout_gpio_irq_chip);
-               set_irq_handler(i, handle_edge_irq);
+               irq_set_chip_and_handler(i, &trout_gpio_irq_chip,
+                                        handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
        for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
                gpiochip_add(&msm_gpio_banks[i].chip);
 
-       set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
-       set_irq_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
-       set_irq_wake(MSM_GPIO_TO_INT(17), 1);
+       irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
+       irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
+       irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1);
 
        return 0;
 }
index 44be8464657b323b9a49921a6ad39ab02b27a0f2..f7a9724788b0f54fe7dc7e239d895d9ed6162ffa 100644 (file)
@@ -174,7 +174,7 @@ int __init trout_init_mmc(unsigned int sys_rev)
        if (IS_ERR(vreg_sdslot))
                return PTR_ERR(vreg_sdslot);
 
-       set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1);
+       irq_set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1);
 
        if (!opt_disable_sdcard)
                msm_add_sdcc(2, &trout_sdslot_data,
index 0de19ec74e3432d5ffa0c1c87c7b9e446d6a5bd7..56a964e52ad3fa10f1a7d83f46b6958a38a64880 100644 (file)
@@ -230,18 +230,18 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio)
               val, val2);
 }
 
-static void msm_gpio_irq_ack(unsigned int irq)
+static void msm_gpio_irq_ack(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 
        writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
        if (test_bit(gpio, msm_gpio.dual_edge_irqs))
                msm_gpio_update_dual_edge_pos(gpio);
 }
 
-static void msm_gpio_irq_mask(unsigned int irq)
+static void msm_gpio_irq_mask(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -251,9 +251,9 @@ static void msm_gpio_irq_mask(unsigned int irq)
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
 
-static void msm_gpio_irq_unmask(unsigned int irq)
+static void msm_gpio_irq_unmask(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -263,9 +263,9 @@ static void msm_gpio_irq_unmask(unsigned int irq)
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
 
-static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
        uint32_t bits;
 
@@ -275,14 +275,14 @@ static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
 
        if (flow_type & IRQ_TYPE_EDGE_BOTH) {
                bits |= BIT(INTR_DECT_CTL);
-               irq_desc[irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
                if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
                        __set_bit(gpio, msm_gpio.dual_edge_irqs);
                else
                        __clear_bit(gpio, msm_gpio.dual_edge_irqs);
        } else {
                bits &= ~BIT(INTR_DECT_CTL);
-               irq_desc[irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
                __clear_bit(gpio, msm_gpio.dual_edge_irqs);
        }
 
@@ -309,6 +309,7 @@ static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
  */
 static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        unsigned long i;
 
        for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
@@ -318,21 +319,21 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
                        generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
                                                           i));
        }
-       desc->chip->ack(irq);
+       data->chip->irq_ack(data);
 }
 
-static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 
        if (on) {
                if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
-                       set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
+                       irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
                set_bit(gpio, msm_gpio.wake_irqs);
        } else {
                clear_bit(gpio, msm_gpio.wake_irqs);
                if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
-                       set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
+                       irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
        }
 
        return 0;
@@ -340,11 +341,11 @@ static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
 
 static struct irq_chip msm_gpio_irq_chip = {
        .name           = "msmgpio",
-       .mask           = msm_gpio_irq_mask,
-       .unmask         = msm_gpio_irq_unmask,
-       .ack            = msm_gpio_irq_ack,
-       .set_type       = msm_gpio_irq_set_type,
-       .set_wake       = msm_gpio_irq_set_wake,
+       .irq_mask       = msm_gpio_irq_mask,
+       .irq_unmask     = msm_gpio_irq_unmask,
+       .irq_ack        = msm_gpio_irq_ack,
+       .irq_set_type   = msm_gpio_irq_set_type,
+       .irq_set_wake   = msm_gpio_irq_set_wake,
 };
 
 static int __devinit msm_gpio_probe(struct platform_device *dev)
@@ -361,12 +362,12 @@ static int __devinit msm_gpio_probe(struct platform_device *dev)
 
        for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
                irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-               set_irq_chip(irq, &msm_gpio_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       set_irq_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
+       irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
                                msm_summary_irq_handler);
        return 0;
 }
@@ -378,7 +379,7 @@ static int __devexit msm_gpio_remove(struct platform_device *dev)
        if (ret < 0)
                return ret;
 
-       set_irq_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
+       irq_set_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
 
        return 0;
 }
index 176af9dcb8ee4fee77f75cb88b356e40cc277d42..5ea273b00da8e4e1fe4273867bf037ecd12cc57f 100644 (file)
@@ -293,10 +293,10 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
        val = readl(msm_chip->regs.int_edge);
        if (flow_type & IRQ_TYPE_EDGE_BOTH) {
                writel(val | mask, msm_chip->regs.int_edge);
-               irq_desc[d->irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        } else {
                writel(val & ~mask, msm_chip->regs.int_edge);
-               irq_desc[d->irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        }
        if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
                msm_chip->both_edge_detect |= mask;
@@ -354,9 +354,9 @@ static int __init msm_init_gpio(void)
                        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);
+               irq_set_chip_data(i, &msm_gpio_chips[j]);
+               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
+                                        handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
@@ -366,10 +366,10 @@ static int __init msm_init_gpio(void)
                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);
+       irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+       irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+       irq_set_irq_wake(INT_GPIO_GROUP1, 1);
+       irq_set_irq_wake(INT_GPIO_GROUP2, 2);
        return 0;
 }
 
index 68c28bbdc9695ff77d130765ed163c0a2ad42754..1b54f807c2d0d573dc87e15bb1ba90102577a580 100644 (file)
@@ -313,11 +313,11 @@ static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
        type = msm_irq_shadow_reg[index].int_type;
        if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
                type |= b;
-               irq_desc[d->irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        }
        if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
                type &= ~b;
-               irq_desc[d->irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        }
        writel(type, treg);
        msm_irq_shadow_reg[index].int_type = type;
@@ -357,8 +357,7 @@ void __init msm_init_irq(void)
        writel(3, VIC_INT_MASTEREN);
 
        for (n = 0; n < NR_MSM_IRQS; n++) {
-               set_irq_chip(n, &msm_irq_chip);
-               set_irq_handler(n, handle_level_irq);
+               irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
                set_irq_flags(n, IRQF_VALID);
        }
 }
index 0b27d899f40e768f4dd7e6d9794b8e4e094d17ea..ea514be390c6112887d253839323fb940a55628c 100644 (file)
@@ -100,11 +100,11 @@ static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
        if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
                writel(readl(treg) | b, treg);
-               irq_desc[d->irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        }
        if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
                writel(readl(treg) & (~b), treg);
-               irq_desc[d->irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        }
        return 0;
 }
@@ -145,8 +145,7 @@ void __init msm_init_irq(void)
        writel(1, VIC_INT_MASTEREN);
 
        for (n = 0; n < NR_MSM_IRQS; n++) {
-               set_irq_chip(n, &msm_irq_chip);
-               set_irq_handler(n, handle_level_irq);
+               irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
                set_irq_flags(n, IRQF_VALID);
        }
 }
index 11b54c7aeb09a35749d14994ce237b1e627ec5d3..689e78c95f38809010b3346da986c3a7931f5ca2 100644 (file)
@@ -105,10 +105,10 @@ static int sirc_irq_set_type(struct irq_data *d, unsigned int flow_type)
        val = readl(sirc_regs.int_type);
        if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
                val |= mask;
-               irq_desc[d->irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        } else {
                val &= ~mask;
-               irq_desc[d->irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        }
 
        writel(val, sirc_regs.int_type);
@@ -158,15 +158,14 @@ void __init msm_init_sirc(void)
        wake_enable = 0;
 
        for (i = FIRST_SIRC_IRQ; i < LAST_SIRC_IRQ; i++) {
-               set_irq_chip(i, &sirc_irq_chip);
-               set_irq_handler(i, handle_edge_irq);
+               irq_set_chip_and_handler(i, &sirc_irq_chip, handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
        for (i = 0; i < ARRAY_SIZE(sirc_reg_table); i++) {
-               set_irq_chained_handler(sirc_reg_table[i].cascade_irq,
+               irq_set_chained_handler(sirc_reg_table[i].cascade_irq,
                                        sirc_irq_handler);
-               set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
+               irq_set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
        }
        return;
 }
index 08da497c39c2db2d927cff8f8adeb61bfa5c52e8..3e24431bb5eaf929c28ed46cd77b62286711c512 100644 (file)
@@ -38,8 +38,8 @@ void __init mv78xx0_init_irq(void)
        orion_gpio_init(0, 32, GPIO_VIRT_BASE,
                        mv78xx0_core_index() ? 0x18 : 0,
                        IRQ_MV78XX0_GPIO_START);
-       set_irq_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
 }
index 4e4b780c481df9c371e12bc8d18217440c78bbe4..3d095d69bc68363bf81e6b4b3bcc5cc7330ff02b 100644 (file)
@@ -199,12 +199,11 @@ static void __init mx31ads_init_expio(void)
        __raw_writew(0xFFFF, PBC_INTSTATUS_REG);
        for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
             i++) {
-               set_irq_chip(i, &expio_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
-       set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
-       set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+       irq_set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
+       irq_set_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
 }
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
index e83ffadb65f862934f39c6b5ee1b0cd94acbaff4..4a8550529b04f6aa6fbb4a2c3a635da7c7467d2e 100644 (file)
@@ -212,7 +212,7 @@ void __init eukrea_mbimx51_baseboard_init(void)
 
        gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
        gpio_direction_input(MBIMX51_TSC2007_GPIO);
-       set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
+       irq_set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
        i2c_register_board_info(1, mbimx51_i2c_devices,
                                ARRAY_SIZE(mbimx51_i2c_devices));
 
index 56fa2ed15222654446a6bb317818542bbe7ecb4f..2c950fef71a87ef9d39f7f79ec2831cf94ba1e7f 100644 (file)
@@ -136,7 +136,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_stat;
-       struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq);
+       struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
        u32 gpio_irq_no_base = port->virtual_irq_start;
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -265,14 +265,14 @@ int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
 
                for (j = port[i].virtual_irq_start;
                        j < port[i].virtual_irq_start + 32; j++) {
-                       set_irq_chip(j, &gpio_irq_chip);
-                       set_irq_handler(j, handle_level_irq);
+                       irq_set_chip_and_handler(j, &gpio_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
 
                /* setup one handler for each entry */
-               set_irq_chained_handler(port[i].irq, mxs_gpio_irq_handler);
-               set_irq_data(port[i].irq, &port[i]);
+               irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
+               irq_set_handler_data(port[i].irq, &port[i]);
 
                /* register gpio chip */
                port[i].chip.direction_input = mxs_gpio_direction_input;
index 0f4c120fc169f0098710ac8ce433046f32563258..23ca9d083b2c09551a63e6628069a53daa4d0590 100644 (file)
@@ -74,8 +74,7 @@ void __init icoll_init_irq(void)
        mxs_reset_block(icoll_base + HW_ICOLL_CTRL);
 
        for (i = 0; i < MXS_INTERNAL_IRQS; i++) {
-               set_irq_chip(i, &mxs_icoll_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &mxs_icoll_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 }
index 29ffa750fbe6413d178cdf008323cf89b02b93f9..00023b5cf12b640f01291ba4f56b0e87941831cd 100644 (file)
@@ -171,13 +171,13 @@ void __init netx_init_irq(void)
        vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
 
        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
-               set_irq_chip(irq, &netx_hif_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &netx_hif_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
        writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
-       set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
+       irq_set_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
 }
 
 static int __init netx_init(void)
index 0c0d5248c3687734a5296184eb33f6f8b6fb0093..e27687d53504a985c379c53a4f0a07dae9f477d6 100644 (file)
@@ -107,8 +107,8 @@ void __init board_a9m9750dev_init_irq(void)
                                __func__);
 
        for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
-               set_irq_chip(i, &a9m9750dev_fpga_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &a9m9750dev_fpga_chip,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
@@ -118,8 +118,8 @@ void __init board_a9m9750dev_init_irq(void)
        REGSET(eic, SYS_EIC, LVEDG, LEVEL);
        __raw_writel(eic, SYS_EIC(2));
 
-       set_irq_chained_handler(IRQ_NS9XXX_EXT2,
-                       a9m9750dev_fpga_demux_handler);
+       irq_set_chained_handler(IRQ_NS9XXX_EXT2,
+                               a9m9750dev_fpga_demux_handler);
 }
 
 void __init board_a9m9750dev_init_machine(void)
index f7e9196eb9abb2dce89c7c4b9e8048a6cd84ff58..19ca6de46a452fbd4c0708685647b11c283d36f1 100644 (file)
 #include <asm/mach-types.h>
 
 #define board_is_a9m9750dev()  (0                      \
-               || machine_is_cc9p9360dev()             \
                || machine_is_cc9p9750dev()             \
                )
 
 #define board_is_a9mvali()     (0                      \
-               || machine_is_cc9p9360val()             \
                || machine_is_cc9p9750val()             \
                )
 
index f851a6b7da6cbfed57aab8f073844cba3704345c..628e9752589bc72c8c4be09fe37021e5ab85b103 100644 (file)
@@ -18,7 +18,6 @@
                )
 
 #define module_is_cc9c()       (0                      \
-               || machine_is_cc9c()                    \
                )
 
 #define module_is_cc9p9210()   (0                      \
                )
 
 #define module_is_cc9p9360()   (0                      \
-               || machine_is_a9m9360()                 \
                || machine_is_cc9p9360dev()             \
                || machine_is_cc9p9360js()              \
-               || machine_is_cc9p9360val()             \
                )
 
 #define module_is_cc9p9750()   (0                      \
                || machine_is_a9m9750()                 \
-               || machine_is_cc9p9750dev()             \
                || machine_is_cc9p9750js()              \
                || machine_is_cc9p9750val()             \
                )
 
 #define module_is_ccw9c()      (0                      \
-               || machine_is_ccw9c()                   \
                )
 
 #define module_is_inc20otter() (0                      \
index 389fa5c669de74760534429134ca2ef02f6c09f4..37ab0a2b83ad59b3b83a0b35c9047f508333d497 100644 (file)
@@ -31,17 +31,11 @@ static void ns9xxx_mask_irq(struct irq_data *d)
        __raw_writel(ic, SYS_IC(prio / 4));
 }
 
-static void ns9xxx_ack_irq(struct irq_data *d)
+static void ns9xxx_eoi_irq(struct irq_data *d)
 {
        __raw_writel(0, SYS_ISRADDR);
 }
 
-static void ns9xxx_maskack_irq(struct irq_data *d)
-{
-       ns9xxx_mask_irq(d);
-       ns9xxx_ack_irq(d);
-}
-
 static void ns9xxx_unmask_irq(struct irq_data *d)
 {
        /* XXX: better use cpp symbols */
@@ -52,56 +46,11 @@ static void ns9xxx_unmask_irq(struct irq_data *d)
 }
 
 static struct irq_chip ns9xxx_chip = {
-       .irq_ack        = ns9xxx_ack_irq,
+       .irq_eoi        = ns9xxx_eoi_irq,
        .irq_mask       = ns9xxx_mask_irq,
-       .irq_mask_ack   = ns9xxx_maskack_irq,
        .irq_unmask     = ns9xxx_unmask_irq,
 };
 
-#if 0
-#define handle_irq handle_level_irq
-#else
-static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
-{
-       struct irqaction *action;
-       irqreturn_t action_ret;
-
-       raw_spin_lock(&desc->lock);
-
-       BUG_ON(desc->status & IRQ_INPROGRESS);
-
-       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-       kstat_incr_irqs_this_cpu(irq, desc);
-
-       action = desc->action;
-       if (unlikely(!action || (desc->status & IRQ_DISABLED)))
-               goto out_mask;
-
-       desc->status |= IRQ_INPROGRESS;
-       raw_spin_unlock(&desc->lock);
-
-       action_ret = handle_IRQ_event(irq, action);
-
-       /* XXX: There is no direct way to access noirqdebug, so check
-        * unconditionally for spurious irqs...
-        * Maybe this function should go to kernel/irq/chip.c? */
-       note_interrupt(irq, desc, action_ret);
-
-       raw_spin_lock(&desc->lock);
-       desc->status &= ~IRQ_INPROGRESS;
-
-       if (desc->status & IRQ_DISABLED)
-out_mask:
-               desc->irq_data.chip->irq_mask(&desc->irq_data);
-
-       /* ack unconditionally to unmask lower prio irqs */
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-       raw_spin_unlock(&desc->lock);
-}
-#define handle_irq handle_prio_irq
-#endif
-
 void __init ns9xxx_init_irq(void)
 {
        int i;
@@ -118,8 +67,8 @@ void __init ns9xxx_init_irq(void)
                __raw_writel(prio2irq(i), SYS_IVA(i));
 
        for (i = 0; i <= 31; ++i) {
-               set_irq_chip(i, &ns9xxx_chip);
-               set_irq_handler(i, handle_irq);
+               irq_set_chip_and_handler(i, &ns9xxx_chip, handle_fasteoi_irq);
                set_irq_flags(i, IRQF_VALID);
+               irq_set_status_flags(i, IRQ_LEVEL);
        }
 }
index 1f8a05a228345246bce7f2ae6b4e9c622ec0140f..aa279f23e342af3437b8a5af84f2dcbe5c83fc0b 100644 (file)
@@ -59,8 +59,8 @@ void __init nuc93x_init_irq(void)
        __raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
 
        for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
-               set_irq_chip(irqno, &nuc93x_irq_chip);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 }
index 7c5e2112c776ecc47c480a4afd27805a77a989e4..e68dfde1918e7dd437808e49c8e7fcf93089586c 100644 (file)
@@ -276,7 +276,7 @@ static void __init osk_init_cf(void)
                return;
        }
        /* the CF I/O IRQ is really active-low */
-       set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
+       irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
 }
 
 static void __init osk_init_irq(void)
@@ -482,7 +482,7 @@ static void __init osk_mistral_init(void)
        omap_cfg_reg(P20_1610_GPIO4);   /* PENIRQ */
        gpio_request(4, "ts_int");
        gpio_direction_input(4);
-       set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING);
+       irq_set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING);
 
        spi_register_board_info(mistral_boardinfo,
                        ARRAY_SIZE(mistral_boardinfo));
@@ -500,7 +500,7 @@ static void __init osk_mistral_init(void)
                int irq = gpio_to_irq(OMAP_MPUIO(2));
 
                gpio_direction_input(OMAP_MPUIO(2));
-               set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 #ifdef CONFIG_PM
                /* share the IRQ in case someone wants to use the
                 * button for more than wakeup from system sleep.
index d7bbbe721a75f7ae8339863ce41fc9b69cfd871c..45f01d2c3a7a0c812c06d134cbd829f2277f11d6 100644 (file)
@@ -256,12 +256,12 @@ palmz71_powercable(int irq, void *dev_id)
 {
        if (gpio_get_value(PALMZ71_USBDETECT_GPIO)) {
                printk(KERN_INFO "PM: Power cable connected\n");
-               set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-                               IRQ_TYPE_EDGE_FALLING);
+               irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+                                IRQ_TYPE_EDGE_FALLING);
        } else {
                printk(KERN_INFO "PM: Power cable disconnected\n");
-               set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-                               IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+                                IRQ_TYPE_EDGE_RISING);
        }
        return IRQ_HANDLED;
 }
index bdc0ac8dc21f4069bcaeddb00d7a080c61724da1..65d24204937a9da268fb333bfda122448cc050ad 100644 (file)
@@ -279,10 +279,10 @@ static void __init voiceblue_init(void)
        gpio_request(13, "16C554 irq");
        gpio_request(14, "16C554 irq");
        gpio_request(15, "16C554 irq");
-       set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
 
        platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
        omap_board_config = voiceblue_config;
index 0ace7998aaa5301f1b4b5881482644cffec1d622..cddbf8b089cef4c08e2d9138e886b7cd0f086e06 100644 (file)
@@ -156,17 +156,17 @@ void omap1510_fpga_init_irq(void)
                         * The touchscreen interrupt is level-sensitive, so
                         * we'll use the regular mask_ack routine for it.
                         */
-                       set_irq_chip(i, &omap_fpga_irq_ack);
+                       irq_set_chip(i, &omap_fpga_irq_ack);
                }
                else {
                        /*
                         * All FPGA interrupts except the touchscreen are
                         * edge-sensitive, so we won't mask them.
                         */
-                       set_irq_chip(i, &omap_fpga_irq);
+                       irq_set_chip(i, &omap_fpga_irq);
                }
 
-               set_irq_handler(i, handle_edge_irq);
+               irq_set_handler(i, handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
@@ -183,6 +183,6 @@ void omap1510_fpga_init_irq(void)
                return;
        }
        gpio_direction_input(13);
-       set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
-       set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
+       irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+       irq_set_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
index 731dd33bff511ad412e5e314bc6be36771d2eded..5d3da7a63af308496fc11dde8e15b5a2dd152e42 100644 (file)
@@ -230,8 +230,8 @@ void __init omap_init_irq(void)
                        irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
                        omap_irq_set_cfg(j, 0, 0, irq_trigger);
 
-                       set_irq_chip(j, &omap_irq_chip);
-                       set_irq_handler(j, handle_level_irq);
+                       irq_set_chip_and_handler(j, &omap_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
        }
index c936c6d7ded08f49e5d6b3e713656f7497cbe1ac..f3a7b1011914c7958e5fdd5ce51b2790c74702ea 100644 (file)
@@ -285,19 +285,6 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
        return 0;
 }
 
-static struct regulator_init_data omap4_panda_vaux1 = {
-       .constraints = {
-               .min_uV                 = 1000000,
-               .max_uV                 = 3000000,
-               .apply_uV               = true,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask  = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-};
-
 static struct regulator_init_data omap4_panda_vaux2 = {
        .constraints = {
                .min_uV                 = 1200000,
@@ -353,19 +340,6 @@ static struct regulator_init_data omap4_panda_vpp = {
        },
 };
 
-static struct regulator_init_data omap4_panda_vusim = {
-       .constraints = {
-               .min_uV                 = 1200000,
-               .max_uV                 = 2900000,
-               .apply_uV               = true,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask  = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-};
-
 static struct regulator_init_data omap4_panda_vana = {
        .constraints = {
                .min_uV                 = 2100000,
@@ -424,12 +398,10 @@ static struct twl4030_platform_data omap4_panda_twldata = {
        /* Regulators */
        .vmmc           = &omap4_panda_vmmc,
        .vpp            = &omap4_panda_vpp,
-       .vusim          = &omap4_panda_vusim,
        .vana           = &omap4_panda_vana,
        .vcxio          = &omap4_panda_vcxio,
        .vdac           = &omap4_panda_vdac,
        .vusb           = &omap4_panda_vusb,
-       .vaux1          = &omap4_panda_vaux1,
        .vaux2          = &omap4_panda_vaux2,
        .vaux3          = &omap4_panda_vaux3,
        .clk32kg        = &omap4_panda_clk32kg,
index e97851492847058f36c2c9056caddc6e830bbf9a..84d1b735fe80d47d2150f7b3f4bd1a2a79af2ba6 100644 (file)
@@ -66,7 +66,7 @@ static int __init omap3_l3_init(void)
 
        WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
 
-       return PTR_ERR(od);
+       return IS_ERR(od) ? PTR_ERR(od) : 0;
 }
 postcore_initcall(omap3_l3_init);
 
index 674174365f787ccb3f5139a1a1afff2defefc82f..130034bf01d5f880541976cf3210de7e74293ce1 100644 (file)
@@ -693,6 +693,7 @@ static int __init gpmc_init(void)
 {
        u32 l, irq;
        int cs, ret = -EINVAL;
+       int gpmc_irq;
        char *ck = NULL;
 
        if (cpu_is_omap24xx()) {
@@ -701,12 +702,15 @@ static int __init gpmc_init(void)
                        l = OMAP2420_GPMC_BASE;
                else
                        l = OMAP34XX_GPMC_BASE;
+               gpmc_irq = INT_34XX_GPMC_IRQ;
        } else if (cpu_is_omap34xx()) {
                ck = "gpmc_fck";
                l = OMAP34XX_GPMC_BASE;
+               gpmc_irq = INT_34XX_GPMC_IRQ;
        } else if (cpu_is_omap44xx()) {
                ck = "gpmc_ck";
                l = OMAP44XX_GPMC_BASE;
+               gpmc_irq = OMAP44XX_IRQ_GPMC;
        }
 
        if (WARN_ON(!ck))
@@ -739,16 +743,17 @@ static int __init gpmc_init(void)
        /* initalize the irq_chained */
        irq = OMAP_GPMC_IRQ_BASE;
        for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-               set_irq_handler(irq, handle_simple_irq);
+               irq_set_chip_and_handler(irq, &dummy_irq_chip,
+                                               handle_simple_irq);
                set_irq_flags(irq, IRQF_VALID);
                irq++;
        }
 
-       ret = request_irq(INT_34XX_GPMC_IRQ,
+       ret = request_irq(gpmc_irq,
                        gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base);
        if (ret)
                pr_err("gpmc: irq-%d could not claim: err %d\n",
-                                               INT_34XX_GPMC_IRQ, ret);
+                                               gpmc_irq, ret);
        return ret;
 }
 postcore_initcall(gpmc_init);
@@ -757,8 +762,6 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
        u8 cs;
 
-       if (irq != INT_34XX_GPMC_IRQ)
-               return IRQ_HANDLED;
        /* check cs to invoke the irq */
        cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
        if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
index bc524b94fd592ed47259335e299cd1cdc59231b0..237e4530abf2320121451cf7f77bc293b7944eb9 100644 (file)
@@ -223,8 +223,7 @@ void __init omap_init_irq(void)
               nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
 
        for (i = 0; i < nr_of_irqs; i++) {
-               set_irq_chip(i, &omap_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &omap_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 }
index 265bff3acb9e7c09dc19f7cf75ffea573aa417bf..5f2da7565b68b917dd439c4574ab98402ed1790c 100644 (file)
@@ -226,7 +226,6 @@ static int __init omap3_l3_probe(struct platform_device *pdev)
        struct omap3_l3         *l3;
        struct resource         *res;
        int                     ret;
-       int                     irq;
 
        l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
        if (!l3) {
@@ -249,18 +248,17 @@ static int __init omap3_l3_probe(struct platform_device *pdev)
                goto err2;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       ret = request_irq(irq, omap3_l3_app_irq,
+       l3->debug_irq = platform_get_irq(pdev, 0);
+       ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
                IRQF_DISABLED | IRQF_TRIGGER_RISING,
                "l3-debug-irq", l3);
        if (ret) {
                dev_err(&pdev->dev, "couldn't request debug irq\n");
                goto err3;
        }
-       l3->debug_irq = irq;
 
-       irq = platform_get_irq(pdev, 1);
-       ret = request_irq(irq, omap3_l3_app_irq,
+       l3->app_irq = platform_get_irq(pdev, 1);
+       ret = request_irq(l3->app_irq, omap3_l3_app_irq,
                IRQF_DISABLED | IRQF_TRIGGER_RISING,
                "l3-app-irq", l3);
 
@@ -269,7 +267,6 @@ static int __init omap3_l3_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       l3->app_irq = irq;
        goto err0;
 
 err4:
index c10a117153767a5f113d4d1cf35dca19a8d2cc3d..b7d4591214e0ba35361f136c3cb30c8321809abd 100644 (file)
@@ -213,7 +213,7 @@ void __init db88f5281_pci_preinit(void)
        pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
        if (gpio_request(pin, "PCI Int1") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "db88f5281_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
@@ -226,7 +226,7 @@ void __init db88f5281_pci_preinit(void)
        pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
        if (gpio_request(pin, "PCI Int2") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "db88f5281_pci_preinit faield "
                                        "to set_irq_type pin %d\n", pin);
index ed85891f86997afeada549a7f0f2f7301c866469..43cf8bc9767bbe8cb5fab72f06b11da74c804d8d 100644 (file)
@@ -34,8 +34,8 @@ void __init orion5x_init_irq(void)
         * Initialize gpiolib for GPIOs 0-31.
         */
        orion_gpio_init(0, 32, GPIO_VIRT_BASE, 0, IRQ_ORION5X_GPIO_START);
-       set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
-       set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
+       irq_set_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
 }
index 67ec6959b26770577f1089b7d7d4c6a0568c9594..4fc46772a0870f0c7f16b25c8b4c48588af5cc5e 100644 (file)
@@ -148,7 +148,7 @@ void __init rd88f5182_pci_preinit(void)
        pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
        if (gpio_request(pin, "PCI IntA") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "rd88f5182_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
@@ -161,7 +161,7 @@ void __init rd88f5182_pci_preinit(void)
        pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
        if (gpio_request(pin, "PCI IntB") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "rd88f5182_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
index 5653ee6c71d800d55c66ce1412d59a35d2fb1b16..616004143912159e4b6bba85057ec69f1aa86248 100644 (file)
@@ -88,7 +88,7 @@ void __init tsp2_pci_preinit(void)
        pin = TSP2_PCI_SLOT0_IRQ_PIN;
        if (gpio_request(pin, "PCI Int1") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "tsp2_pci_preinit failed "
                                        "to set_irq_type pin %d\n", pin);
index 8bbd27ea673556d55cf4deb11f1bfc5def9aa3a5..f0f43e13ac873a4f3375e0215721d73e01d901c6 100644 (file)
@@ -117,7 +117,7 @@ void __init qnap_ts209_pci_preinit(void)
        pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
        if (gpio_request(pin, "PCI Int1") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
                                        "set_irq_type pin %d\n", pin);
@@ -131,7 +131,7 @@ void __init qnap_ts209_pci_preinit(void)
        pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
        if (gpio_request(pin, "PCI Int2") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "qnap_ts209_pci_preinit failed "
                                        "to set_irq_type pin %d\n", pin);
index c69c180aec76b474668311406c986a3a5c586ce0..7608c7a288cfbabf3f69ebc0ff7f43daaf41b017 100644 (file)
@@ -58,22 +58,22 @@ static int pnx4008_set_irq_type(struct irq_data *d, unsigned int type)
        case IRQ_TYPE_EDGE_RISING:
                __raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));       /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));       /*rising edge */
-               set_irq_handler(d->irq, handle_edge_irq);
+               irq_set_handler(d->irq, handle_edge_irq);
                break;
        case IRQ_TYPE_EDGE_FALLING:
                __raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));       /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));      /*falling edge */
-               set_irq_handler(d->irq, handle_edge_irq);
+               irq_set_handler(d->irq, handle_edge_irq);
                break;
        case IRQ_TYPE_LEVEL_LOW:
                __raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));      /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));      /*low level */
-               set_irq_handler(d->irq, handle_level_irq);
+               irq_set_handler(d->irq, handle_level_irq);
                break;
        case IRQ_TYPE_LEVEL_HIGH:
                __raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));      /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));       /* high level */
-               set_irq_handler(d->irq, handle_level_irq);
+               irq_set_handler(d->irq, handle_level_irq);
                break;
 
        /* IRQ_TYPE_EDGE_BOTH is not supported */
@@ -98,7 +98,7 @@ void __init pnx4008_init_irq(void)
        /* configure IRQ's */
        for (i = 0; i < NR_IRQS; i++) {
                set_irq_flags(i, IRQF_VALID);
-               set_irq_chip(i, &pnx4008_irq_chip);
+               irq_set_chip(i, &pnx4008_irq_chip);
                pnx4008_set_irq_type(irq_get_irq_data(i), pnx4008_irq_type[i]);
        }
 
index c6661b1d30b25d7f5be1f07875b94ad3f80f172e..bfbecec6d05fbd5a3f3457185675720e00ab74d1 100644 (file)
@@ -527,13 +527,13 @@ static void __init balloon3_init_irq(void)
        pxa27x_init_irq();
        /* setup extra Balloon3 irqs */
        for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) {
-               set_irq_chip(irq, &balloon3_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &balloon3_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
-       set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);
+       irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
+       irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);
 
        pr_debug("%s: chained handler installed - irq %d automatically "
                "enabled\n", __func__, BALLOON3_AUX_NIRQ);
index a2380cd76f80188247e637e5b9678b0570c16557..8b1a30959fae3e0426bd1475114cc042d7b08856 100644 (file)
@@ -70,9 +70,10 @@ void __cmx2xx_pci_init_irq(int irq_gpio)
 
        cmx2xx_it8152_irq_gpio = irq_gpio;
 
-       set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
 
-       set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx2xx_it8152_irq_demux);
+       irq_set_chained_handler(gpio_to_irq(irq_gpio),
+                               cmx2xx_it8152_irq_demux);
 }
 
 #ifdef CONFIG_PM
index 7a8edba0dcdf1959cc60d7d74fc6866891caaa36..b2248e76ec8b713b9bf1f8a01ca84aca2e845d9c 100644 (file)
@@ -765,7 +765,7 @@ static void __init cm_x300_init_da9030(void)
 {
        pxa3xx_set_i2c_power_info(&cm_x300_pwr_i2c_info);
        i2c_register_board_info(1, &cm_x300_pmic_info, 1);
-       set_irq_wake(IRQ_WAKEUP0, 1);
+       irq_set_irq_wake(IRQ_WAKEUP0, 1);
 }
 
 static void __init cm_x300_init_wi2wi(void)
index 2693e3c3776fc32283ad29ed191cebe2446f4f09..6251e3f5c62c0399a8c019d71e576de1cab49974 100644 (file)
@@ -137,9 +137,9 @@ static void __init pxa_init_low_gpio_irq(set_wake_t fn)
        GEDR0 = 0x3;
 
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-               set_irq_chip(irq, &pxa_low_gpio_chip);
-               set_irq_chip_data(irq, irq_base(0));
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &pxa_low_gpio_chip,
+                                        handle_edge_irq);
+               irq_set_chip_data(irq, irq_base(0));
                set_irq_flags(irq, IRQF_VALID);
        }
 
@@ -165,9 +165,9 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
                                __raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
 
                        irq = PXA_IRQ(i);
-                       set_irq_chip(irq, &pxa_internal_irq_chip);
-                       set_irq_chip_data(irq, base);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &pxa_internal_irq_chip,
+                                                handle_level_irq);
+                       irq_set_chip_data(irq, base);
                        set_irq_flags(irq, IRQF_VALID);
                }
        }
index 8aebc58c9f1d689706e167f3a207b67f61095d45..f5de541725b1525024e6a469492934ce4e9c1be5 100644 (file)
@@ -149,12 +149,12 @@ static void __init lpd270_init_irq(void)
 
        /* setup extra LogicPD PXA270 irqs */
        for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
-               set_irq_chip(irq, &lpd270_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &lpd270_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
-       set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+       irq_set_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
+       irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 
index 12a2a56b2157a0b9f3e6513f93e430fb5340f640..3ede978c83d9573128ae409723d5387ed66de49b 100644 (file)
@@ -165,13 +165,13 @@ static void __init lubbock_init_irq(void)
 
        /* setup extra lubbock irqs */
        for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
-               set_irq_chip(irq, &lubbock_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &lubbock_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+       irq_set_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
+       irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
index 8306b227e61c22f73b4b7e01cab164e7b90d91ca..95163baca29ec04dcf77d76e0b87b35ef67d5294 100644 (file)
@@ -166,8 +166,8 @@ static void __init mainstone_init_irq(void)
 
        /* setup extra Mainstone irqs */
        for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
-               set_irq_chip(irq, &mainstone_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &mainstone_irq_chip,
+                                        handle_level_irq);
                if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
                else
@@ -179,8 +179,8 @@ static void __init mainstone_init_irq(void)
        MST_INTMSKENA = 0;
        MST_INTSETCLR = 0;
 
-       set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+       irq_set_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
+       irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
index a70fb848dcde975de3ad09b2a331197b2771e50e..6d5b7e0621248d50dcb4dd90c0f876c6ec7471f5 100644 (file)
@@ -281,16 +281,16 @@ static void __init pcm990_init_irq(void)
 
        /* setup extra PCM990 irqs */
        for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) {
-               set_irq_chip(irq, &pcm990_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &pcm990_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        PCM990_INTMSKENA = 0x00;        /* disable all Interrupts */
        PCM990_INTSETCLR = 0xFF;
 
-       set_irq_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
-       set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
+       irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
+       irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
 }
 
 static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
index f374247b8466d358fab0ed529f3b2d1704806978..8dd107391157489a8ea651d7386cd37f1da61638 100644 (file)
@@ -362,8 +362,8 @@ static void __init pxa_init_ext_wakeup_irq(set_wake_t fn)
        int irq;
 
        for (irq = IRQ_WAKEUP0; irq <= IRQ_WAKEUP1; irq++) {
-               set_irq_chip(irq, &pxa_ext_wakeup_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &pxa_ext_wakeup_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
index 0fbe78df846138f53942ed1e7e7ac8281a0550f1..b523f119e0f0183ddff38bfb28ce4fb8a69f8b52 100644 (file)
@@ -310,14 +310,14 @@ static void __init viper_init_irq(void)
        /* setup ISA IRQs */
        for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) {
                isa_irq = viper_bit_to_irq(level);
-               set_irq_chip(isa_irq, &viper_irq_chip);
-               set_irq_handler(isa_irq, handle_edge_irq);
+               irq_set_chip_and_handler(isa_irq, &viper_irq_chip,
+                                        handle_edge_irq);
                set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO),
+       irq_set_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO),
                                viper_irq_handler);
-       set_irq_type(gpio_to_irq(VIPER_CPLD_GPIO), IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(gpio_to_irq(VIPER_CPLD_GPIO), IRQ_TYPE_EDGE_BOTH);
 }
 
 /* Flat Panel */
index 5891590126f7e6ea0c5ffe398fee6d910c209613..00363c7ac1828c58e45035f7d37a5ea0bcbcfcf5 100644 (file)
@@ -136,22 +136,23 @@ static void __init zeus_init_irq(void)
 
        /* Peripheral IRQs. It would be nice to move those inside driver
           configuration, but it is not supported at the moment. */
-       set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO),       IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO),     IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO),        IRQ_TYPE_EDGE_RISING);
-       set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO),    IRQ_TYPE_EDGE_FALLING);
-       set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO),        IRQ_TYPE_EDGE_FALLING);
+       irq_set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO), IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO),
+                        IRQ_TYPE_EDGE_FALLING);
+       irq_set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO), IRQ_TYPE_EDGE_FALLING);
 
        /* Setup ISA IRQs */
        for (level = 0; level < ARRAY_SIZE(zeus_isa_irqs); level++) {
                isa_irq = zeus_bit_to_irq(level);
-               set_irq_chip(isa_irq, &zeus_irq_chip);
-               set_irq_handler(isa_irq, handle_edge_irq);
+               irq_set_chip_and_handler(isa_irq, &zeus_irq_chip,
+                                        handle_edge_irq);
                set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
-       set_irq_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
+       irq_set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
+       irq_set_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
 }
 
 
index d29cd9b737fc0aaca7522cfed688c85f16ecebbe..2e1b5309fbab54a32d7df58f2193244a17b7cee8 100644 (file)
@@ -133,25 +133,25 @@ void __init rpc_init_irq(void)
 
                switch (irq) {
                case 0 ... 7:
-                       set_irq_chip(irq, &iomd_a_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &iomd_a_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 8 ... 15:
-                       set_irq_chip(irq, &iomd_b_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &iomd_b_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 16 ... 21:
-                       set_irq_chip(irq, &iomd_dma_chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_and_handler(irq, &iomd_dma_chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 64 ... 71:
-                       set_irq_chip(irq, &iomd_fiq_chip);
+                       irq_set_chip(irq, &iomd_fiq_chip);
                        set_irq_flags(irq, IRQF_VALID);
                        break;
                }
index 606cb6b1cc4714f1932a30b4557eded86c3cb586..bc53d2d16d1a3917ef05a9f703028b0509ed64ee 100644 (file)
@@ -147,15 +147,15 @@ static __init int bast_irq_init(void)
 
                __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
 
-               set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
+               irq_set_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
 
                /* register our IRQs */
 
                for (i = 0; i < 4; i++) {
                        unsigned int irqno = bast_pc104_irqs[i];
 
-                       set_irq_chip(irqno, &bast_pc104_chip);
-                       set_irq_handler(irqno, handle_level_irq);
+                       irq_set_chip_and_handler(irqno, &bast_pc104_chip,
+                                                handle_level_irq);
                        set_irq_flags(irqno, IRQF_VALID);
                }
        }
index eddb52ba5b656efb5aef7d20cbc1e36750689b50..f3355d2ec634f9aa9e544c48104e0b938c906543 100644 (file)
@@ -175,18 +175,18 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
        unsigned int irqno;
 
        for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-               set_irq_chip(irqno, &s3c2412_irq_eint0t4);
-               set_irq_handler(irqno, handle_edge_irq);
+               irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
+                                        handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        /* add demux support for CF/SDI */
 
-       set_irq_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
+       irq_set_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
 
        for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
-               set_irq_chip(irqno, &s3c2412_irq_cfsdi);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c2412_irq_cfsdi,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
@@ -195,7 +195,7 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
        s3c2412_irq_rtc_chip = s3c_irq_chip;
        s3c2412_irq_rtc_chip.irq_set_wake = s3c2412_irq_rtc_wake;
 
-       set_irq_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
+       irq_set_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
 
        return 0;
 }
index 680fe386aca58471ee2207210a69f43041cfa920..77b38f2381c1ac3fd1aa159646e0e93501ede996 100644 (file)
@@ -202,13 +202,11 @@ static int __init s3c2416_add_sub(unsigned int base,
 {
        unsigned int irqno;
 
-       set_irq_chip(base, &s3c_irq_level_chip);
-       set_irq_handler(base, handle_level_irq);
-       set_irq_chained_handler(base, demux);
+       irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+       irq_set_chained_handler(base, demux);
 
        for (irqno = start; irqno <= end; irqno++) {
-               set_irq_chip(irqno, chip);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, chip, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index acad4428bef05881969644dd6411356c2a604a50..eb1cc0f0705e348905d982004fef868602bb3521 100644 (file)
@@ -100,13 +100,13 @@ static int s3c2440_irq_add(struct sys_device *sysdev)
 
        /* add new chained handler for wdt, ac7 */
 
-       set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_WDT, handle_level_irq);
-       set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
+       irq_set_chip_and_handler(IRQ_WDT, &s3c_irq_level_chip,
+                                handle_level_irq);
+       irq_set_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
 
        for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
-               set_irq_chip(irqno, &s3c_irq_wdtac97);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_wdtac97,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 83daf4ece76464773a3604dabd1540a5570377fd..de07c2feaa321995bced42ae009a32895396ae64 100644 (file)
@@ -95,19 +95,19 @@ static int s3c244x_irq_add(struct sys_device *sysdev)
 {
        unsigned int irqno;
 
-       set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_NFCON, handle_level_irq);
+       irq_set_chip_and_handler(IRQ_NFCON, &s3c_irq_level_chip,
+                                handle_level_irq);
        set_irq_flags(IRQ_NFCON, IRQF_VALID);
 
        /* add chained handler for camera */
 
-       set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_CAM, handle_level_irq);
-       set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+       irq_set_chip_and_handler(IRQ_CAM, &s3c_irq_level_chip,
+                                handle_level_irq);
+       irq_set_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
 
        for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-               set_irq_chip(irqno, &s3c_irq_cam);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_cam,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index c7820f9c135231105c08a50f2b58cb1d4115a588..83ecb1173fb139a27940c2943fa70a45c7999bf0 100644 (file)
@@ -230,13 +230,11 @@ static int __init s3c2443_add_sub(unsigned int base,
 {
        unsigned int irqno;
 
-       set_irq_chip(base, &s3c_irq_level_chip);
-       set_irq_handler(base, handle_level_irq);
-       set_irq_chained_handler(base, demux);
+       irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+       irq_set_chained_handler(base, demux);
 
        for (irqno = start; irqno <= end; irqno++) {
-               set_irq_chip(irqno, chip);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, chip, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 2ead8189da7438d900c573eb62ca447968dd7e09..4d203be1f4c38b400c91000c601398ad61e9bd52 100644 (file)
@@ -197,16 +197,15 @@ static int __init s3c64xx_init_irq_eint(void)
        int irq;
 
        for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
-               set_irq_chip(irq, &s3c_irq_eint);
-               set_irq_chip_data(irq, (void *)eint_irq_to_bit(irq));
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
+               irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
-       set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
-       set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
-       set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
+       irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
+       irq_set_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
+       irq_set_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
+       irq_set_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
 
        return 0;
 }
index b8d02eb4cf30efeb5ed749eb755cd29d44461ed6..a5c00952ea35c71047c1362e29735179bd4ac261 100644 (file)
@@ -119,7 +119,7 @@ void __init s5p6450_map_io(void)
        s3c_adc_setname("s3c64xx-adc");
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
-       iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+       iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
 }
 
 /*
index 26710b35ef87184f5a4c66f295d00c93847e0508..b9f9ec33384d6cecc1633a90e9aabb3492d556b0 100644 (file)
@@ -99,9 +99,9 @@
 #define IRQ_TC                 IRQ_PENDN
 #define IRQ_KEYPAD             S5P_IRQ_VIC2(25)
 #define IRQ_CG                 S5P_IRQ_VIC2(26)
-#define IRQ_SEC                        S5P_IRQ_VIC2(27)
-#define IRQ_SECRX              S5P_IRQ_VIC2(28)
-#define IRQ_SECTX              S5P_IRQ_VIC2(29)
+#define IRQ_SSS_INT            S5P_IRQ_VIC2(27)
+#define IRQ_SSS_HASH           S5P_IRQ_VIC2(28)
+#define IRQ_PCM2               S5P_IRQ_VIC2(29)
 #define IRQ_SDMIRQ             S5P_IRQ_VIC2(30)
 #define IRQ_SDMFIQ             S5P_IRQ_VIC2(31)
 
index bc08ac42e7cc7bcd41b29d46cf7837656b236c9c..c6a9e86c2d5ced263e25e5580a2fc53b7115a469 100644 (file)
@@ -44,7 +44,6 @@
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
-#include <plat/gpio-cfg.h>
 #include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
index 98d780608c7e98ffb3a64fb285301cc88731a6b5..7f3da4b11ec90fd7caeff810d65ea3ffc010546e 100644 (file)
@@ -96,7 +96,7 @@ static struct resource cerf_flash_resource = {
 static void __init cerf_init_irq(void)
 {
        sa1100_init_irq();
-       set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
 }
 
 static struct map_desc cerf_io_desc[] __initdata = {
index 3d85dfad9c1fc60fabace59e90b26afa0b66db63..423ddb3d65e9c8e0b50743414559852d4b9197b0 100644 (file)
@@ -323,28 +323,28 @@ void __init sa1100_init_irq(void)
        ICCR = 1;
 
        for (irq = 0; irq <= 10; irq++) {
-               set_irq_chip(irq, &sa1100_low_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        for (irq = 12; irq <= 31; irq++) {
-               set_irq_chip(irq, &sa1100_normal_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &sa1100_normal_chip,
+                                        handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
        for (irq = 32; irq <= 48; irq++) {
-               set_irq_chip(irq, &sa1100_high_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /*
         * Install handler for GPIO 11-27 edge detect interrupts
         */
-       set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
-       set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
+       irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
+       irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
 
        sa1100_init_gpio();
 }
index 4aad01f73660eada599be0d1ed61b0e86d87745b..b4fa53a1427e437a8592c9d4f8f947ba32742ad2 100644 (file)
@@ -145,8 +145,8 @@ static int __devinit neponset_probe(struct platform_device *dev)
        /*
         * Install handler for GPIO25.
         */
-       set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
-       set_irq_chained_handler(IRQ_GPIO25, neponset_irq_handler);
+       irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
+       irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler);
 
        /*
         * We would set IRQ_GPIO25 to be a wake-up IRQ, but
@@ -161,9 +161,9 @@ static int __devinit neponset_probe(struct platform_device *dev)
         * Setup other Neponset IRQs.  SA1111 will be done by the
         * generic SA1111 code.
         */
-       set_irq_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
+       irq_set_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
        set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
-       set_irq_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
+       irq_set_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
        set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
 
        /*
index 42b80400c1006b8927f8c71046ab090ae536447c..65161f2bea29132632a468328c0616c66e6f84b2 100644 (file)
@@ -142,7 +142,7 @@ static void __init pleb_map_io(void)
 
        GPDR &= ~GPIO_ETH0_IRQ;
 
-       set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
+       irq_set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
 }
 
 MACHINE_START(PLEB, "PLEB")
index 831fc66dfa4dc34ae96c238593edb9c1b4f1dbd8..5dce13e429f3daae015b7f5e3b1ddbd27650de48 100644 (file)
@@ -80,8 +80,7 @@ void __init shark_init_irq(void)
        int irq;
 
        for (irq = 0; irq < NR_IRQS; irq++) {
-               set_irq_chip(irq, &fb_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &fb_chip, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index a94f29da5d308adaf216159fbc9184a5f1eb75b3..783b66fa95fb03427c1844de5102bb8a8ae02e87 100644 (file)
@@ -24,9 +24,9 @@
 #include <linux/irq.h>
 #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/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
@@ -312,7 +312,7 @@ static struct resource sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0xe6850000,
-               .end    = 0xe68501ff,
+               .end    = 0xe68500ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -345,7 +345,7 @@ static struct resource sdhi1_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0xe6860000,
-               .end    = 0xe68601ff,
+               .end    = 0xe68600ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1255,7 +1255,7 @@ static void __init ap4evb_init(void)
        gpio_request(GPIO_FN_KEYIN4,     NULL);
 
        /* enable TouchScreen */
-       set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
 
        tsc_device.irq = IRQ28;
        i2c_register_board_info(1, &tsc_device, 1);
@@ -1311,7 +1311,7 @@ static void __init ap4evb_init(void)
        lcdc_info.ch[0].lcd_size_cfg.height     = 91;
 
        /* enable TouchScreen */
-       set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
 
        tsc_device.irq = IRQ7;
        i2c_register_board_info(0, &tsc_device, 1);
index dee3e9231fb9a039548f2fe6a37a62371bd72863..c87a7b7c583278f2f43bbf964c74c02f8b7f84d0 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/mmc/host.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
@@ -205,7 +205,7 @@ static struct resource sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0xe6d50000,
-               .end    = 0xe6d501ff,
+               .end    = 0xe6d50nff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -232,7 +232,7 @@ static struct resource sdhi1_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0xe6d60000,
-               .end    = 0xe6d601ff,
+               .end    = 0xe6d600ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index 49bc07482179b3c5fd64bd1bbc14ff558de2da06..8184d4d4f234dddd7cf219114a1d57787332391b 100644 (file)
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
@@ -690,7 +690,7 @@ static struct resource sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0xe6850000,
-               .end    = 0xe68501ff,
+               .end    = 0xe68500ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -725,7 +725,7 @@ static struct resource sdhi1_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0xe6860000,
-               .end    = 0xe68601ff,
+               .end    = 0xe68600ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -768,7 +768,7 @@ static struct resource sdhi2_resources[] = {
        [0] = {
                .name   = "SDHI2",
                .start  = 0xe6870000,
-               .end    = 0xe68701ff,
+               .end    = 0xe68700ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1124,15 +1124,15 @@ static void __init mackerel_init(void)
 
        /* enable Keypad */
        gpio_request(GPIO_FN_IRQ9_42,   NULL);
-       set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
+       irq_set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
 
        /* enable Touchscreen */
        gpio_request(GPIO_FN_IRQ7_40,   NULL);
-       set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
 
        /* enable Accelerometer */
        gpio_request(GPIO_FN_IRQ21,     NULL);
-       set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
+       irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
 
        /* enable SDHI0 */
        gpio_request(GPIO_FN_SDHICD0, NULL);
index 2fe9704d5ea1cf081ca862a1b53f9d7034258b49..cc442d198cdc302b907e731233fcbef8186e16e2 100644 (file)
@@ -421,7 +421,7 @@ static struct intc_desc intcs_desc __initdata = {
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-       void __iomem *reg = (void *)get_irq_data(irq);
+       void __iomem *reg = (void *)irq_get_handler_data(irq);
        unsigned int evtcodeas = ioread32(reg);
 
        generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -435,6 +435,6 @@ void __init sh7367_init_irq(void)
        register_intc_controller(&intcs_desc);
 
        /* demux using INTEVTSA */
-       set_irq_data(evt2irq(0xf80), (void *)intevtsa);
-       set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
+       irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
+       irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
index ca5f9d17b39abd6cb1f92ce2d33c09bf5f9e86b8..7a4960f9c1e3fcb313cf103fcacd3ccbfe3fab71 100644 (file)
@@ -601,7 +601,7 @@ static struct intc_desc intcs_desc __initdata = {
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-       void __iomem *reg = (void *)get_irq_data(irq);
+       void __iomem *reg = (void *)irq_get_handler_data(irq);
        unsigned int evtcodeas = ioread32(reg);
 
        generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -615,6 +615,6 @@ void __init sh7372_init_irq(void)
        register_intc_controller(&intcs_desc);
 
        /* demux using INTEVTSA */
-       set_irq_data(evt2irq(0xf80), (void *)intevtsa);
-       set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
+       irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
+       irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
index dd568382cc9f7bacdad0dbb6e60fc70e2a6391ee..fe45154ce660a420d55bf0b31b73c3f684a0f886 100644 (file)
@@ -626,7 +626,7 @@ static struct intc_desc intcs_desc __initdata = {
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-       void __iomem *reg = (void *)get_irq_data(irq);
+       void __iomem *reg = (void *)irq_get_handler_data(irq);
        unsigned int evtcodeas = ioread32(reg);
 
        generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -641,6 +641,6 @@ void __init sh7377_init_irq(void)
        register_intc_controller(&intcs_desc);
 
        /* demux using INTEVTSA */
-       set_irq_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
-       set_irq_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
+       irq_set_handler_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
+       irq_set_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
 }
index aa9231f4fc6e7cbe91d62ece3b4aeaf16f945122..209fa5c65d4cee50bafa54e6a5d38b120472c33d 100644 (file)
@@ -102,10 +102,10 @@ void __init tcc8k_init_irq(void)
 
        for (irqno = 0; irqno < NR_IRQS; irqno++) {
                if (irqno < 32)
-                       set_irq_chip(irqno, &tcc8000_irq_chip0);
+                       irq_set_chip(irqno, &tcc8000_irq_chip0);
                else
-                       set_irq_chip(irqno, &tcc8000_irq_chip1);
-               set_irq_handler(irqno, handle_level_irq);
+                       irq_set_chip(irqno, &tcc8000_irq_chip1);
+               irq_set_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 }
index 12090a2cf3e04e52b7cec262f075a56e6d4636d6..76a3f654220f2f012b842b9e2794811fba2a4710 100644 (file)
@@ -208,9 +208,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __set_irq_handler_unlocked(d->irq, handle_level_irq);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __set_irq_handler_unlocked(d->irq, handle_edge_irq);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
 
        return 0;
 }
@@ -224,7 +224,7 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-       bank = get_irq_data(irq);
+       bank = irq_get_handler_data(irq);
 
        for (port = 0; port < 4; port++) {
                int gpio = tegra_gpio_compose(bank->bank, port, 0);
@@ -275,13 +275,6 @@ void tegra_gpio_resume(void)
        }
 
        local_irq_restore(flags);
-
-       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-               struct irq_desc *desc = irq_to_desc(i);
-               if (!desc || (desc->status & IRQ_WAKEUP))
-                       continue;
-               enable_irq(i);
-       }
 }
 
 void tegra_gpio_suspend(void)
@@ -289,18 +282,6 @@ void tegra_gpio_suspend(void)
        unsigned long flags;
        int b, p, i;
 
-       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-               struct irq_desc *desc = irq_to_desc(i);
-               if (!desc)
-                       continue;
-               if (desc->status & IRQ_WAKEUP) {
-                       int gpio = i - INT_GPIO_BASE;
-                       pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
-                       continue;
-               }
-               disable_irq(i);
-       }
-
        local_irq_save(flags);
        for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
                struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
@@ -320,7 +301,7 @@ void tegra_gpio_suspend(void)
 static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
        struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       return set_irq_wake(bank->irq, enable);
+       return irq_set_irq_wake(bank->irq, enable);
 }
 #endif
 
@@ -359,18 +340,18 @@ static int __init tegra_gpio_init(void)
        for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
                bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
 
-               lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
-               set_irq_chip_data(i, bank);
-               set_irq_chip(i, &tegra_gpio_irq_chip);
-               set_irq_handler(i, handle_simple_irq);
+               irq_set_lockdep_class(i, &gpio_lock_class);
+               irq_set_chip_data(i, bank);
+               irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+                                        handle_simple_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
        for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
                bank = &tegra_gpio_banks[i];
 
-               set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
-               set_irq_data(bank->irq, bank);
+               irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
+               irq_set_handler_data(bank->irq, bank);
 
                for (j = 0; j < 4; j++)
                        spin_lock_init(&bank->lvl_lock[j]);
index dfbc219ea4923ad920b27918cf6fc76fff813f1e..4330d8995b2799f1375e78d52bcfb65ea8661341 100644 (file)
@@ -144,7 +144,7 @@ void __init tegra_init_irq(void)
        gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
                 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
-       gic = get_irq_chip(29);
+       gic = irq_get_chip(29);
        tegra_gic_unmask_irq = gic->irq_unmask;
        tegra_gic_mask_irq = gic->irq_mask;
        tegra_gic_ack_irq = gic->irq_ack;
@@ -154,8 +154,7 @@ void __init tegra_init_irq(void)
 
        for (i = 0; i < INT_MAIN_NR; i++) {
                irq = INT_PRI_BASE + i;
-               set_irq_chip(irq, &tegra_irq);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &tegra_irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
index 203b986280f54d8987f74f7b9a92d9bf5a10bc02..58626013aa322874bd0ebd33eb5ce22f2bb3ab1f 100644 (file)
@@ -23,6 +23,7 @@ menu "Ux500 target platform"
 config MACH_U8500
        bool "U8500 Development platform"
        depends on UX500_SOC_DB8500
+       select TPS6105X
        help
          Include support for the mop500 development platform.
 
index 875c91b2f8a4e008f9b92f6ca751fa013a2a85eb..9ed0f90cfe2368d33dc89f1b2a8679c69a8ddd8d 100644 (file)
 #include <linux/regulator/ab8500.h>
 #include "board-mop500-regulators.h"
 
+/*
+ * TPS61052 regulator
+ */
+static struct regulator_consumer_supply tps61052_vaudio_consumers[] = {
+       /*
+        * Boost converter supply to raise voltage on audio speaker, this
+        * is actually connected to three pins, VInVhfL (left amplifier)
+        * VInVhfR (right amplifier) and VIntDClassInt - all three must
+        * be connected to the same voltage.
+        */
+       REGULATOR_SUPPLY("vintdclassint", "ab8500-codec.0"),
+};
+
+struct regulator_init_data tps61052_regulator = {
+       .constraints = {
+               .name = "vaudio-hf",
+               .min_uV = 4500000,
+               .max_uV = 4500000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps61052_vaudio_consumers),
+       .consumer_supplies = tps61052_vaudio_consumers,
+};
+
 static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
        /* External displays, connector on board 2v5 power supply */
        REGULATOR_SUPPLY("vaux12v5", "mcde.0"),
@@ -62,6 +86,182 @@ static struct regulator_consumer_supply ab8500_vana_consumers[] = {
        REGULATOR_SUPPLY("vsmps2", "mcde.0"),
 };
 
+/* ab8500 regulator register initialization */
+struct ab8500_regulator_reg_init
+ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
+       /*
+        * VanaRequestCtrl          = HP/LP depending on VxRequest
+        * VextSupply1RequestCtrl   = HP/LP depending on VxRequest
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00),
+       /*
+        * VextSupply2RequestCtrl   = HP/LP depending on VxRequest
+        * VextSupply3RequestCtrl   = HP/LP depending on VxRequest
+        * Vaux1RequestCtrl         = HP/LP depending on VxRequest
+        * Vaux2RequestCtrl         = HP/LP depending on VxRequest
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00),
+       /*
+        * Vaux3RequestCtrl         = HP/LP depending on VxRequest
+        * SwHPReq                  = Control through SWValid disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00),
+       /*
+        * VanaSysClkReq1HPValid    = disabled
+        * Vaux1SysClkReq1HPValid   = disabled
+        * Vaux2SysClkReq1HPValid   = disabled
+        * Vaux3SysClkReq1HPValid   = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x00),
+       /*
+        * VextSupply1SysClkReq1HPValid = disabled
+        * VextSupply2SysClkReq1HPValid = disabled
+        * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40),
+       /*
+        * VanaHwHPReq1Valid        = disabled
+        * Vaux1HwHPreq1Valid       = disabled
+        * Vaux2HwHPReq1Valid       = disabled
+        * Vaux3HwHPReqValid        = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00),
+       /*
+        * VextSupply1HwHPReq1Valid = disabled
+        * VextSupply2HwHPReq1Valid = disabled
+        * VextSupply3HwHPReq1Valid = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00),
+       /*
+        * VanaHwHPReq2Valid        = disabled
+        * Vaux1HwHPReq2Valid       = disabled
+        * Vaux2HwHPReq2Valid       = disabled
+        * Vaux3HwHPReq2Valid       = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00),
+       /*
+        * VextSupply1HwHPReq2Valid = disabled
+        * VextSupply2HwHPReq2Valid = disabled
+        * VextSupply3HwHPReq2Valid = HWReq2 controlled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04),
+       /*
+        * VanaSwHPReqValid         = disabled
+        * Vaux1SwHPReqValid        = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00),
+       /*
+        * Vaux2SwHPReqValid        = disabled
+        * Vaux3SwHPReqValid        = disabled
+        * VextSupply1SwHPReqValid  = disabled
+        * VextSupply2SwHPReqValid  = disabled
+        * VextSupply3SwHPReqValid  = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00),
+       /*
+        * SysClkReq2Valid1         = SysClkReq2 controlled
+        * SysClkReq3Valid1         = disabled
+        * SysClkReq4Valid1         = SysClkReq4 controlled
+        * SysClkReq5Valid1         = disabled
+        * SysClkReq6Valid1         = SysClkReq6 controlled
+        * SysClkReq7Valid1         = disabled
+        * SysClkReq8Valid1         = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a),
+       /*
+        * SysClkReq2Valid2         = disabled
+        * SysClkReq3Valid2         = disabled
+        * SysClkReq4Valid2         = disabled
+        * SysClkReq5Valid2         = disabled
+        * SysClkReq6Valid2         = SysClkReq6 controlled
+        * SysClkReq7Valid2         = disabled
+        * SysClkReq8Valid2         = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20),
+       /*
+        * VTVoutEna                = disabled
+        * Vintcore12Ena            = disabled
+        * Vintcore12Sel            = 1.25 V
+        * Vintcore12LP             = inactive (HP)
+        * VTVoutLP                 = inactive (HP)
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10),
+       /*
+        * VaudioEna                = disabled
+        * VdmicEna                 = disabled
+        * Vamic1Ena                = disabled
+        * Vamic2Ena                = disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00),
+       /*
+        * Vamic1_dzout             = high-Z when Vamic1 is disabled
+        * Vamic2_dzout             = high-Z when Vamic2 is disabled
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00),
+       /*
+        * VPll                     = Hw controlled
+        * VanaRegu                 = force off
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02),
+       /*
+        * VrefDDREna               = disabled
+        * VrefDDRSleepMode         = inactive (no pulldown)
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00),
+       /*
+        * VextSupply1Regu          = HW control
+        * VextSupply2Regu          = HW control
+        * VextSupply3Regu          = HW control
+        * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
+        * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
+        */
+       INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x2a),
+       /*
+        * Vaux1Regu                = force HP
+        * Vaux2Regu                = force off
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01),
+       /*
+        * Vaux3regu                = force off
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x00),
+       /*
+        * Vsmps1                   = 1.15V
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24),
+       /*
+        * Vaux1Sel                 = 2.5 V
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08),
+       /*
+        * Vaux2Sel                 = 2.9 V
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d),
+       /*
+        * Vaux3Sel                 = 2.91 V
+        */
+       INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07),
+       /*
+        * VextSupply12LP           = disabled (no LP)
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00),
+       /*
+        * Vaux1Disch               = short discharge time
+        * Vaux2Disch               = short discharge time
+        * Vaux3Disch               = short discharge time
+        * Vintcore12Disch          = short discharge time
+        * VTVoutDisch              = short discharge time
+        * VaudioDisch              = short discharge time
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00),
+       /*
+        * VanaDisch                = short discharge time
+        * VdmicPullDownEna         = pulldown disabled when Vdmic is disabled
+        * VdmicDisch               = short discharge time
+        */
+       INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00),
+};
+
 /* AB8500 regulators */
 struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
        /* supplies to the display/camera */
@@ -72,6 +272,7 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
                        .max_uV = 2900000,
                        .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
                                          REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1, /* must be on for display */
                },
                .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
                .consumer_supplies = ab8500_vaux1_consumers,
index 2675fae52537d9444654b51ce9cb3f8272d45c1a..94992158d96230ad42f65aca2fdfd5e05ceeb5ae 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
 
+extern struct ab8500_regulator_reg_init
+ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
 extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
+extern struct regulator_init_data tps61052_regulator;
 
 #endif
index 8790d984cac81550373c61d46ab9ee0a425c8452..dc8746d7826ebd52407aa8a04d0f14edf7fa7af9 100644 (file)
 #include <linux/amba/serial.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
+#include <linux/regulator/ab8500.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/mfd/tps6105x.h>
+#include <linux/mfd/ab8500/gpio.h>
 #include <linux/leds-lp5521.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
+static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
+       .gpio_base              = MOP500_AB8500_GPIO(0),
+       .irq_base               = MOP500_AB8500_VIR_GPIO_IRQ_BASE,
+       /* config_reg is the initial configuration of ab8500 pins.
+        * The pins can be configured as GPIO or alt functions based
+        * on value present in GpioSel1 to GpioSel6 and AlternatFunction
+        * register. This is the array of 7 configuration settings.
+        * One has to compile time decide these settings. Below is the
+        * explaination of these setting
+        * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO
+        * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO
+        * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO
+        * GpioSel4 = 0x01 => Pin GPIo25 is configured as GPIO
+        * GpioSel5 = 0x7A => Pins GPIO34, GPIO36 to GPIO39 are conf as GPIO
+        * GpioSel6 = 0x00 => Pins GPIO41 & GPIo42 are not configured as GPIO
+        * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured
+        * as GPIO then this register selectes the alternate fucntions
+        */
+       .config_reg             = {0x00, 0x1E, 0x80, 0x01,
+                                       0x7A, 0x00, 0x00},
+};
+
 static struct ab8500_platform_data ab8500_platdata = {
        .irq_base       = MOP500_AB8500_IRQ_BASE,
+       .regulator_reg_init = ab8500_regulator_reg_init,
+       .num_regulator_reg_init = ARRAY_SIZE(ab8500_regulator_reg_init),
        .regulator      = ab8500_regulators,
        .num_regulator  = ARRAY_SIZE(ab8500_regulators),
+       .gpio           = &ab8500_gpio_pdata,
 };
 
 static struct resource ab8500_resources[] = {
@@ -65,6 +93,15 @@ struct platform_device ab8500_device = {
        .resource = ab8500_resources,
 };
 
+/*
+ * TPS61052
+ */
+
+static struct tps6105x_platform_data mop500_tps61052_data = {
+       .mode = TPS6105X_MODE_VOLTAGE,
+       .regulator_data = &tps61052_regulator,
+};
+
 /*
  * TC35892
  */
@@ -135,7 +172,7 @@ static struct lp5521_platform_data __initdata lp5521_sec_data = {
        .clock_mode     = LP5521_CLOCK_EXT,
 };
 
-static struct i2c_board_info mop500_i2c0_devices[] = {
+static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
        {
                I2C_BOARD_INFO("tc3589x", 0x42),
                .irq            = NOMADIK_GPIO_TO_IRQ(217),
@@ -143,6 +180,14 @@ static struct i2c_board_info mop500_i2c0_devices[] = {
        },
 };
 
+/* I2C0 devices only available prior to HREFv60 */
+static struct i2c_board_info __initdata mop500_i2c0_old_devices[] = {
+       {
+               I2C_BOARD_INFO("tps61052", 0x33),
+               .platform_data  = &mop500_tps61052_data,
+       },
+};
+
 static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
        {
                /* lp5521 LED driver, 1st device */
@@ -405,6 +450,9 @@ static void __init mop500_init_machine(void)
 
        i2c_register_board_info(0, mop500_i2c0_devices,
                                ARRAY_SIZE(mop500_i2c0_devices));
+       if (!machine_is_hrefv60())
+               i2c_register_board_info(0, mop500_i2c0_old_devices,
+                                       ARRAY_SIZE(mop500_i2c0_old_devices));
        i2c_register_board_info(2, mop500_i2c2_devices,
                                ARRAY_SIZE(mop500_i2c2_devices));
 }
index 56722f4be71b96a5cc0af9e9d20be8d79c6dd757..03a31cc9b0841243c48fd57cbe555b1507a68efe 100644 (file)
 #define GPIO_BU21013_CS                        MOP500_EGPIO(13)
 #define GPIO_SDMMC_EN                  MOP500_EGPIO(17)
 #define GPIO_SDMMC_1V8_3V_SEL          MOP500_EGPIO(18)
+#define MOP500_EGPIO_END               MOP500_EGPIO(24)
+
+/* GPIOs on the AB8500 mixed-signals circuit */
+#define MOP500_AB8500_GPIO(x)          (MOP500_EGPIO_END + (x))
 
 struct i2c_board_info;
 
index 7cdeb2af0ebb7691a395be014bd5a96be17691da..97ef55f8493496486723c8fb4fa4ada65717e785 100644 (file)
 #define MOP500_STMPE1601_IRQBASE        MOP500_EGPIO_IRQ_END
 #define MOP500_STMPE1601_IRQ(x)         (MOP500_STMPE1601_IRQBASE + (x))
 
-#define MOP500_NR_IRQS          MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
+#define MOP500_STMPE1601_IRQ_END       \
+       MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
 
-#define MOP500_IRQ_END          MOP500_NR_IRQS
+/* AB8500 virtual gpio IRQ */
+#define AB8500_VIR_GPIO_NR_IRQS                        16
+
+#define MOP500_AB8500_VIR_GPIO_IRQ_BASE                \
+       MOP500_STMPE1601_IRQ_END
+#define MOP500_AB8500_VIR_GPIO_IRQ_END         \
+       (MOP500_AB8500_VIR_GPIO_IRQ_BASE + AB8500_VIR_GPIO_NR_IRQS)
+
+#define MOP500_NR_IRQS         MOP500_AB8500_VIR_GPIO_IRQ_END
+
+#define MOP500_IRQ_END         MOP500_NR_IRQS
 
 #if MOP500_IRQ_END > IRQ_BOARD_END
 #undef IRQ_BOARD_END
index e1296a7447c8493eabccf5ce189b4a0aaf1a6ed6..6b86416c94c92080e2120bec011882d1a1481666 100644 (file)
@@ -90,8 +90,7 @@ static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
 
 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);
+       irq_set_chip_and_handler(irq, modem_irq_chip, handle_simple_irq);
        set_irq_flags(irq, IRQF_VALID);
 
        pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
index eb7ffa0ee8b544d77caf42cc542892413b055952..96e59e3ee4f551d0c72e3f0960ea5ebe953ff308 100644 (file)
@@ -314,7 +314,7 @@ static struct mmci_platform_data mmc0_plat_data = {
        .gpio_cd        = -1,
 };
 
-static struct resource char_lcd_resources[] = {
+static struct resource chalcd_resources[] = {
        {
                .start = VERSATILE_CHAR_LCD_BASE,
                .end   = (VERSATILE_CHAR_LCD_BASE + SZ_4K - 1),
index 5f4ddde4f02ab8b2a0c2ece6c4d743dcab0fd4e9..245140c0df107d5b00830032f3351fe6cc82ff88 100644 (file)
@@ -97,15 +97,15 @@ static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type)
                return -EINVAL;
        case IRQF_TRIGGER_HIGH:
                dctr |= VT8500_TRIGGER_HIGH;
-               irq_desc[orig_irq].handle_irq = handle_level_irq;
+               __irq_set_handler_locked(orig_irq, handle_level_irq);
                break;
        case IRQF_TRIGGER_FALLING:
                dctr |= VT8500_TRIGGER_FALLING;
-               irq_desc[orig_irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(orig_irq, handle_edge_irq);
                break;
        case IRQF_TRIGGER_RISING:
                dctr |= VT8500_TRIGGER_RISING;
-               irq_desc[orig_irq].handle_irq = handle_edge_irq;
+               __irq_set_handler_locked(orig_irq, handle_edge_irq);
                break;
        }
        writeb(dctr, base + VT8500_IC_DCTR + irq);
@@ -136,8 +136,8 @@ void __init vt8500_init_irq(void)
                        /* Disable all interrupts and route them to IRQ */
                        writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
 
-                       set_irq_chip(i, &vt8500_irq_chip);
-                       set_irq_handler(i, handle_level_irq);
+                       irq_set_chip_and_handler(i, &vt8500_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(i, IRQF_VALID);
                }
        } else {
@@ -167,8 +167,8 @@ void __init wm8505_init_irq(void)
                                writeb(0x00, sic_regbase + VT8500_IC_DCTR
                                                                + i - 64);
 
-                       set_irq_chip(i, &vt8500_irq_chip);
-                       set_irq_handler(i, handle_level_irq);
+                       irq_set_chip_and_handler(i, &vt8500_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(i, IRQF_VALID);
                }
        } else {
index 9c350103dcdab4e35fff1475a6ef6ee253898ce3..7bf143c443f15c27ec30f079b9864304db8ae881 100644 (file)
@@ -207,8 +207,8 @@ void __init nuc900_init_irq(void)
        __raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
 
        for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) {
-               set_irq_chip(irqno, &nuc900_irq_chip);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &nuc900_irq_chip,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 }
index c856fa397606be1d0036fb2897a92ddb62225c73..f0ba0726306cb4f60efe8091ee8b09f60804131e 100644 (file)
@@ -100,14 +100,9 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
 
        expio_irq = MXC_BOARD_IRQ_START;
        for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
-               struct irq_desc *d;
                if ((int_valid & 1) == 0)
                        continue;
-               d = irq_desc + expio_irq;
-               if (unlikely(!(d->handle_irq)))
-                       pr_err("\nEXPIO irq: %d unhandled\n", expio_irq);
-               else
-                       d->handle_irq(expio_irq, d);
+               generic_handle_irq(expio_irq);
        }
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -186,12 +181,11 @@ int __init mxc_expio_init(u32 base, u32 p_irq)
        __raw_writew(0x1F, brd_io + INTR_MASK_REG);
        for (i = MXC_EXP_IO_BASE;
             i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); i++) {
-               set_irq_chip(i, &expio_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
-       set_irq_type(p_irq, IRQF_TRIGGER_LOW);
-       set_irq_chained_handler(p_irq, mxc_expio_irq_handler);
+       irq_set_irq_type(p_irq, IRQF_TRIGGER_LOW);
+       irq_set_chained_handler(p_irq, mxc_expio_irq_handler);
 
        /* Register Lan device on the debugboard */
        smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
index deb284bc7c4bbc31bc0af8730efcf7604debae73..09e2bd0fcdca742a41b004d3c846fa16b298a309 100644 (file)
@@ -139,8 +139,8 @@ void __init mxc_init_irq(void __iomem *irqbase)
        __raw_writel(0, avic_base + AVIC_INTTYPEH);
        __raw_writel(0, avic_base + AVIC_INTTYPEL);
        for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-               set_irq_chip(i, &mxc_avic_chip.base);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &mxc_avic_chip.base,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
index 57d59855f9ecbc1e603fc9ab2cecd9779ea1bb48..7a107246fd98849b6f8efe34316d977629f4bef8 100644 (file)
@@ -175,7 +175,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_stat;
-       struct mxc_gpio_port *port = get_irq_data(irq);
+       struct mxc_gpio_port *port = irq_get_handler_data(irq);
 
        irq_stat = __raw_readl(port->base + GPIO_ISR) &
                        __raw_readl(port->base + GPIO_IMR);
@@ -188,7 +188,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        int i;
        u32 irq_msk, irq_stat;
-       struct mxc_gpio_port *port = get_irq_data(irq);
+       struct mxc_gpio_port *port = irq_get_handler_data(irq);
 
        /* walk through all interrupt status registers */
        for (i = 0; i < gpio_table_size; i++) {
@@ -311,8 +311,8 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
                __raw_writel(~0, port[i].base + GPIO_ISR);
                for (j = port[i].virtual_irq_start;
                        j < port[i].virtual_irq_start + 32; j++) {
-                       set_irq_chip(j, &gpio_irq_chip);
-                       set_irq_handler(j, handle_level_irq);
+                       irq_set_chip_and_handler(j, &gpio_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
 
@@ -331,21 +331,23 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 
                if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
                        /* setup one handler for each entry */
-                       set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler);
-                       set_irq_data(port[i].irq, &port[i]);
+                       irq_set_chained_handler(port[i].irq,
+                                               mx3_gpio_irq_handler);
+                       irq_set_handler_data(port[i].irq, &port[i]);
                        if (port[i].irq_high) {
                                /* setup handler for GPIO 16 to 31 */
-                               set_irq_chained_handler(port[i].irq_high,
-                                               mx3_gpio_irq_handler);
-                               set_irq_data(port[i].irq_high, &port[i]);
+                               irq_set_chained_handler(port[i].irq_high,
+                                                       mx3_gpio_irq_handler);
+                               irq_set_handler_data(port[i].irq_high,
+                                                    &port[i]);
                        }
                }
        }
 
        if (cpu_is_mx2()) {
                /* setup one handler for all GPIO interrupts */
-               set_irq_chained_handler(port[0].irq, mx2_gpio_irq_handler);
-               set_irq_data(port[0].irq, port);
+               irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
+               irq_set_handler_data(port[0].irq, port);
        }
 
        return 0;
index 0c799ac27730883dfc37aa633605d528262bc13f..e1c6eff7258ae4728bb4d09e19fbbd1153c5e3f1 100644 (file)
@@ -29,7 +29,7 @@ int imx_irq_set_priority(unsigned char irq, unsigned char prio)
 
        ret = -ENOSYS;
 
-       base = get_irq_chip(irq);
+       base = irq_get_chip(irq);
        if (base) {
                chip = container_of(base, struct mxc_irq_chip, base);
                if (chip->set_priority)
@@ -48,7 +48,7 @@ int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 
        ret = -ENOSYS;
 
-       base = get_irq_chip(irq);
+       base = irq_get_chip(irq);
        if (base) {
                chip = container_of(base, struct mxc_irq_chip, base);
                if (chip->set_irq_fiq)
index bc3a6be8a27fe210dd0ed45d67f75b884a86289a..57f9395f87ceaddb2cbd522e6b27a4555af6140d 100644 (file)
@@ -167,8 +167,8 @@ void __init tzic_init_irq(void __iomem *irqbase)
        /* all IRQ no FIQ Warning :: No selection */
 
        for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-               set_irq_chip(i, &mxc_tzic_chip.base);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, &mxc_tzic_chip.base,
+                                        handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
index 80643bc38e10deb1695d210d9ec29bab823275ab..f49748eca1a3ad605c57e5effb170cde76b999e5 100644 (file)
@@ -54,6 +54,7 @@ struct nmk_gpio_chip {
        u32 rwimsc;
        u32 fwimsc;
        u32 slpm;
+       u32 enabled;
 };
 
 static struct nmk_gpio_chip *
@@ -318,7 +319,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
                struct nmk_gpio_chip *nmk_chip;
                int pin = PIN_NUM(cfgs[i]);
 
-               nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+               nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
                if (!nmk_chip) {
                        ret = -EINVAL;
                        break;
@@ -397,7 +398,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
        if (!nmk_chip)
                return -EINVAL;
 
@@ -430,7 +431,7 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
        if (!nmk_chip)
                return -EINVAL;
 
@@ -456,7 +457,7 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
        if (!nmk_chip)
                return -EINVAL;
 
@@ -473,7 +474,7 @@ int nmk_gpio_get_mode(int gpio)
        struct nmk_gpio_chip *nmk_chip;
        u32 afunc, bfunc, bit;
 
-       nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
        if (!nmk_chip)
                return -EINVAL;
 
@@ -541,13 +542,6 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
                                int gpio, bool on)
 {
-#ifdef CONFIG_ARCH_U8500
-       if (cpu_is_u8500v2()) {
-               __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
-                                   on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
-                                      : NMK_GPIO_SLPM_WAKEUP_DISABLE);
-       }
-#endif
        __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
 }
 
@@ -564,6 +558,11 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
        if (!nmk_chip)
                return -EINVAL;
 
+       if (enable)
+               nmk_chip->enabled |= bitmask;
+       else
+               nmk_chip->enabled &= ~bitmask;
+
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
@@ -590,8 +589,6 @@ static void nmk_gpio_irq_unmask(struct irq_data *d)
 
 static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
-       bool enabled = !(desc->status & IRQ_DISABLED);
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
        u32 bitmask;
@@ -606,7 +603,7 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
-       if (!enabled)
+       if (!(nmk_chip->enabled & bitmask))
                __nmk_gpio_set_wake(nmk_chip, gpio, on);
 
        if (on)
@@ -622,9 +619,7 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 
 static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
-       bool enabled = !(desc->status & IRQ_DISABLED);
-       bool wake = desc->wake_depth;
+       bool enabled, wake = irqd_is_wakeup_set(d);
        int gpio;
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
@@ -641,6 +636,8 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        if (type & IRQ_TYPE_LEVEL_LOW)
                return -EINVAL;
 
+       enabled = nmk_chip->enabled & bitmask;
+
        spin_lock_irqsave(&nmk_chip->lock, flags);
 
        if (enabled)
@@ -681,7 +678,7 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
                                   u32 status)
 {
        struct nmk_gpio_chip *nmk_chip;
-       struct irq_chip *host_chip = get_irq_chip(irq);
+       struct irq_chip *host_chip = irq_get_chip(irq);
        unsigned int first_irq;
 
        if (host_chip->irq_mask_ack)
@@ -692,7 +689,7 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
                        host_chip->irq_ack(&desc->irq_data);
        }
 
-       nmk_chip = get_irq_data(irq);
+       nmk_chip = irq_get_handler_data(irq);
        first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
        while (status) {
                int bit = __ffs(status);
@@ -706,7 +703,7 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
 
 static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
+       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
        u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
 
        __nmk_gpio_irq_handler(irq, desc, status);
@@ -715,7 +712,7 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 static void nmk_gpio_secondary_irq_handler(unsigned int irq,
                                           struct irq_desc *desc)
 {
-       struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
+       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
        u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
 
        __nmk_gpio_irq_handler(irq, desc, status);
@@ -728,20 +725,20 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
 
        first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
        for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
-               set_irq_chip(i, &nmk_gpio_irq_chip);
-               set_irq_handler(i, handle_edge_irq);
+               irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
+                                        handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
-               set_irq_chip_data(i, nmk_chip);
-               set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
+               irq_set_chip_data(i, nmk_chip);
+               irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
        }
 
-       set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
-       set_irq_data(nmk_chip->parent_irq, nmk_chip);
+       irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
+       irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
 
        if (nmk_chip->secondary_parent_irq >= 0) {
-               set_irq_chained_handler(nmk_chip->secondary_parent_irq,
+               irq_set_chained_handler(nmk_chip->secondary_parent_irq,
                                        nmk_gpio_secondary_irq_handler);
-               set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip);
+               irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
        }
 
        return 0;
index 971d186369423c7eacb03e580a74714ad35e6f26..d2adcdda23cf41c351fe418e31097fe2e4773df3 100644 (file)
@@ -755,18 +755,12 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
        bank = irq_data_get_irq_chip_data(d);
        spin_lock_irqsave(&bank->lock, flags);
        retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
-       if (retval == 0) {
-               struct irq_desc *desc = irq_to_desc(d->irq);
-
-               desc->status &= ~IRQ_TYPE_SENSE_MASK;
-               desc->status |= type;
-       }
        spin_unlock_irqrestore(&bank->lock, flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __set_irq_handler_unlocked(d->irq, handle_level_irq);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __set_irq_handler_unlocked(d->irq, handle_edge_irq);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
 
        return retval;
 }
@@ -1146,7 +1140,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-       bank = get_irq_data(irq);
+       bank = irq_get_handler_data(irq);
 #ifdef CONFIG_ARCH_OMAP1
        if (bank->method == METHOD_MPUIO)
                isr_reg = bank->base +
@@ -1270,8 +1264,7 @@ static void gpio_unmask_irq(struct irq_data *d)
        unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned int irq_mask = 1 << get_gpio_index(gpio);
-       struct irq_desc *desc = irq_to_desc(d->irq);
-       u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK;
+       u32 trigger = irqd_get_trigger_type(d);
 
        if (trigger)
                _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
@@ -1672,19 +1665,17 @@ static void __init omap_gpio_chip_init(struct gpio_bank *bank)
 
        for (j = bank->virtual_irq_start;
                     j < bank->virtual_irq_start + bank_width; j++) {
-               struct irq_desc *d = irq_to_desc(j);
-
-               lockdep_set_class(&d->lock, &gpio_lock_class);
-               set_irq_chip_data(j, bank);
+               irq_set_lockdep_class(j, &gpio_lock_class);
+               irq_set_chip_data(j, bank);
                if (bank_is_mpuio(bank))
-                       set_irq_chip(j, &mpuio_irq_chip);
+                       irq_set_chip(j, &mpuio_irq_chip);
                else
-                       set_irq_chip(j, &gpio_irq_chip);
-               set_irq_handler(j, handle_simple_irq);
+                       irq_set_chip(j, &gpio_irq_chip);
+               irq_set_handler(j, handle_simple_irq);
                set_irq_flags(j, IRQF_VALID);
        }
-       set_irq_chained_handler(bank->irq, gpio_irq_handler);
-       set_irq_data(bank->irq, bank);
+       irq_set_chained_handler(bank->irq, gpio_irq_handler);
+       irq_set_handler_data(bank->irq, bank);
 }
 
 static int __devinit omap_gpio_probe(struct platform_device *pdev)
index d7792837046318c8ccbf96459874af73a64c9116..5a25098ea7ea8ed3b8d30fcd3f1518dfa66db7f7 100644 (file)
 
 /* GPMC related */
 #define OMAP_GPMC_IRQ_BASE     (TWL_IRQ_END)
-#define OMAP_GPMC_NR_IRQS      7
+#define OMAP_GPMC_NR_IRQS      8
 #define OMAP_GPMC_IRQ_END      (OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS)
 
 
index cbe897ca7f9ed395376b45f36267d33513378713..2858667d2e4f7505502c5e3a8317ff0bdfb4fbe6 100644 (file)
@@ -32,6 +32,7 @@ struct omap_onenand_platform_data {
        int                     dma_channel;
        u8                      flags;
        u8                      regulator_can_sleep;
+       u8                      skip_initial_unlocking;
 };
 
 #define ONENAND_MAX_PARTITIONS 8
index 078894bc3b9a2f59e59b941d7d1259749a8ff2a8..a431a138f4027b238e21cc80bbc5144e8bffab21 100644 (file)
@@ -324,9 +324,8 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
 static void gpio_irq_ack(struct irq_data *d)
 {
        struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type;
+       int type = irqd_get_trigger_type(d);
 
-       type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
                int pin = d->irq - ochip->secondary_irq_base;
 
@@ -337,11 +336,10 @@ static void gpio_irq_ack(struct irq_data *d)
 static void gpio_irq_mask(struct irq_data *d)
 {
        struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type;
+       int type = irqd_get_trigger_type(d);
        void __iomem *reg;
        int pin;
 
-       type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
                reg = GPIO_EDGE_MASK(ochip);
        else
@@ -355,11 +353,10 @@ static void gpio_irq_mask(struct irq_data *d)
 static void gpio_irq_unmask(struct irq_data *d)
 {
        struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type;
+       int type = irqd_get_trigger_type(d);
        void __iomem *reg;
        int pin;
 
-       type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
                reg = GPIO_EDGE_MASK(ochip);
        else
@@ -389,9 +386,9 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
         * Set edge/level type.
         */
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-               set_irq_handler(d->irq, handle_edge_irq);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               set_irq_handler(d->irq, handle_level_irq);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
        } else {
                printk(KERN_ERR "failed to set irq=%d (type=%d)\n",
                       d->irq, type);
@@ -477,10 +474,10 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
        for (i = 0; i < ngpio; i++) {
                unsigned int irq = secondary_irq_base + i;
 
-               set_irq_chip(irq, &orion_gpio_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_chip_data(irq, ochip);
-               irq_desc[irq].status |= IRQ_LEVEL;
+               irq_set_chip_and_handler(irq, &orion_gpio_irq_chip,
+                                        handle_level_irq);
+               irq_set_chip_data(irq, ochip);
+               irq_set_status_flags(irq, IRQ_LEVEL);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
@@ -488,7 +485,7 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
 void orion_gpio_irq_handler(int pinoff)
 {
        struct orion_gpio_chip *ochip;
-       u32 cause;
+       u32 cause, type;
        int i;
 
        ochip = orion_gpio_chip_find(pinoff);
@@ -500,15 +497,14 @@ void orion_gpio_irq_handler(int pinoff)
 
        for (i = 0; i < ochip->chip.ngpio; i++) {
                int irq;
-               struct irq_desc *desc;
 
                irq = ochip->secondary_irq_base + i;
 
                if (!(cause & (1 << i)))
                        continue;
 
-               desc = irq_desc + irq;
-               if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+               type = irqd_get_trigger_type(irq_get_irq_data(irq));
+               if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
                        /* Swap polarity (race with GPIO line) */
                        u32 polarity;
 
@@ -516,7 +512,6 @@ void orion_gpio_irq_handler(int pinoff)
                        polarity ^= 1 << i;
                        writel(polarity, GPIO_IN_POL(ochip));
                }
-
-               desc_handle_irq(irq, desc);
+               generic_handle_irq(irq);
        }
 }
index 7d0c7eb59f0971cc273aebfd1f24ba0a80684d99..d8d638e09f8fd7d958324df5b74a5db0d9df0218 100644 (file)
@@ -56,10 +56,10 @@ void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
        for (i = 0; i < 32; i++) {
                unsigned int irq = irq_start + i;
 
-               set_irq_chip(irq, &orion_irq_chip);
-               set_irq_chip_data(irq, maskaddr);
-               set_irq_handler(irq, handle_level_irq);
-               irq_desc[irq].status |= IRQ_LEVEL;
+               irq_set_chip_and_handler(irq, &orion_irq_chip,
+                                        handle_level_irq);
+               irq_set_chip_data(irq, maskaddr);
+               irq_set_status_flags(irq, IRQ_LEVEL);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
index e7de6ae2a1e816212407476b784defd76fd94758..dce088f4567819f3d6574f5632d4b065ef3e54bf 100644 (file)
@@ -284,13 +284,13 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
        }
 
        for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
-               set_irq_chip(irq, &pxa_muxed_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+                                        handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /* Install handler for GPIO>=2 edge detect interrupts */
-       set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
+       irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
        pxa_muxed_gpio_chip.irq_set_wake = fn;
 }
 
index 01a8448e471c8b4317452d3f4f208d64e27799bc..442301fe48b4176d3403de8f535837317ec7213d 100644 (file)
@@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset {
 };
 
 struct pxa3xx_nand_flash {
+       char            *name;
        uint32_t        chip_id;
        unsigned int    page_per_block; /* Pages per block (PG_PER_BLK) */
        unsigned int    page_size;      /* Page size in bytes (PAGE_SZ) */
@@ -37,7 +38,6 @@ struct pxa3xx_nand_flash {
        unsigned int    dfc_width;      /* Width of flash controller(DWIDTH_C) */
        unsigned int    num_blocks;     /* Number of physical blocks in Flash */
 
-       struct pxa3xx_nand_cmdset *cmdset;      /* NAND command set */
        struct pxa3xx_nand_timing *timing;      /* NAND Flash timing */
 };
 
index 4434cb56bd9ad898a76ca54c31fb4ca07af52fc1..9aee7e1668b1e464a908af6243ea62f6b5f9e76b 100644 (file)
@@ -592,8 +592,8 @@ void __init s3c24xx_init_irq(void)
                case IRQ_UART1:
                case IRQ_UART2:
                case IRQ_ADCPARENT:
-                       set_irq_chip(irqno, &s3c_irq_level_chip);
-                       set_irq_handler(irqno, handle_level_irq);
+                       irq_set_chip_and_handler(irqno, &s3c_irq_level_chip,
+                                                handle_level_irq);
                        break;
 
                case IRQ_RESERVED6:
@@ -603,35 +603,35 @@ void __init s3c24xx_init_irq(void)
 
                default:
                        //irqdbf("registering irq %d (s3c irq)\n", irqno);
-                       set_irq_chip(irqno, &s3c_irq_chip);
-                       set_irq_handler(irqno, handle_edge_irq);
+                       irq_set_chip_and_handler(irqno, &s3c_irq_chip,
+                                                handle_edge_irq);
                        set_irq_flags(irqno, IRQF_VALID);
                }
        }
 
        /* setup the cascade irq handlers */
 
-       set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
-       set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+       irq_set_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+       irq_set_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
 
-       set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
-       set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
-       set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-       set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+       irq_set_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+       irq_set_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+       irq_set_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+       irq_set_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
        /* external interrupts */
 
        for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
                irqdbf("registering irq %d (ext int)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_eint0t4);
-               set_irq_handler(irqno, handle_edge_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4,
+                                        handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
                irqdbf("registering irq %d (extended s3c irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irqext_chip);
-               set_irq_handler(irqno, handle_edge_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irqext_chip,
+                                        handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
@@ -641,29 +641,28 @@ void __init s3c24xx_init_irq(void)
 
        for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
                irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart0);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_uart0,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
                irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart1);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_uart1,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
                irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart2);
-               set_irq_handler(irqno, handle_level_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_uart2,
+                                        handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
                irqdbf("registering irq %d (s3c adc irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_adc);
-               set_irq_handler(irqno, handle_edge_irq);
+               irq_set_chip_and_handler(irqno, &s3c_irq_adc, handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index c3bfe9b13acf0c64c671e725395a8ba4d8ab423d..5cf5e721e6caf83234bd556936286a632961ff48 100644 (file)
@@ -39,7 +39,7 @@ static const char name_exynos4210[] = "EXYNOS4210";
 static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x56440100,
-               .idmask         = 0xffffff00,
+               .idmask         = 0xfffff000,
                .map_io         = s5p6440_map_io,
                .init_clocks    = s5p6440_init_clocks,
                .init_uarts     = s5p6440_init_uarts,
@@ -47,7 +47,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .name           = name_s5p6440,
        }, {
                .idcode         = 0x36442000,
-               .idmask         = 0xffffff00,
+               .idmask         = 0xfffff000,
                .map_io         = s5p6442_map_io,
                .init_clocks    = s5p6442_init_clocks,
                .init_uarts     = s5p6442_init_uarts,
@@ -55,7 +55,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .name           = name_s5p6442,
        }, {
                .idcode         = 0x36450000,
-               .idmask         = 0xffffff00,
+               .idmask         = 0xfffff000,
                .map_io         = s5p6450_map_io,
                .init_clocks    = s5p6450_init_clocks,
                .init_uarts     = s5p6450_init_uarts,
@@ -79,7 +79,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .name           = name_s5pv210,
        }, {
                .idcode         = 0x43210000,
-               .idmask         = 0xfffff000,
+               .idmask         = 0xfffe0000,
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
index 225aa25405db4701d42c01abc2fb40d53b45faed..b5bb774985b0c7db17eaf3aa91e805d05c1ffdfd 100644 (file)
@@ -205,15 +205,14 @@ int __init s5p_init_irq_eint(void)
        int irq;
 
        for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
-               set_irq_chip(irq, &s5p_irq_vic_eint);
+               irq_set_chip(irq, &s5p_irq_vic_eint);
 
        for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
-               set_irq_chip(irq, &s5p_irq_eint);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       set_irq_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
+       irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
        return 0;
 }
 
index cd87d3256e033b553fb5540ff1da308c880c4792..46dd078147d8b13e0750e11bd6f047c18ac033e6 100644 (file)
@@ -43,13 +43,13 @@ LIST_HEAD(banks);
 
 static int s5p_gpioint_get_offset(struct irq_data *data)
 {
-       struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+       struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
        return data->irq - chip->irq_base;
 }
 
 static void s5p_gpioint_ack(struct irq_data *data)
 {
-       struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+       struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
        int group, offset, pend_offset;
        unsigned int value;
 
@@ -64,7 +64,7 @@ static void s5p_gpioint_ack(struct irq_data *data)
 
 static void s5p_gpioint_mask(struct irq_data *data)
 {
-       struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+       struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
        int group, offset, mask_offset;
        unsigned int value;
 
@@ -79,7 +79,7 @@ static void s5p_gpioint_mask(struct irq_data *data)
 
 static void s5p_gpioint_unmask(struct irq_data *data)
 {
-       struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+       struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
        int group, offset, mask_offset;
        unsigned int value;
 
@@ -100,7 +100,7 @@ static void s5p_gpioint_mask_ack(struct irq_data *data)
 
 static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 {
-       struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+       struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
        int group, offset, con_offset;
        unsigned int value;
 
@@ -149,7 +149,7 @@ static struct irq_chip s5p_gpioint = {
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct s5p_gpioint_bank *bank = get_irq_data(irq);
+       struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
        int group, pend_offset, mask_offset;
        unsigned int pend, mask;
 
@@ -200,8 +200,8 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
                if (!bank->chips)
                        return -ENOMEM;
 
-               set_irq_chained_handler(bank->irq, s5p_gpioint_handler);
-               set_irq_data(bank->irq, bank);
+               irq_set_chained_handler(bank->irq, s5p_gpioint_handler);
+               irq_set_handler_data(bank->irq, bank);
                bank->handler = s5p_gpioint_handler;
                printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
                       bank->irq);
@@ -219,9 +219,9 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
        bank->chips[group - bank->start] = chip;
        for (i = 0; i < chip->chip.ngpio; i++) {
                irq = chip->irq_base + i;
-               set_irq_chip(irq, &s5p_gpioint);
-               set_irq_data(irq, chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip(irq, &s5p_gpioint);
+               irq_set_handler_data(irq, chip);
+               irq_set_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
        return 0;
index 6790edfaca6f49aad661fb34cffafc4115dff9f6..79d10fca9090268b4e817cc299f2021634a27d17 100644 (file)
@@ -36,7 +36,7 @@ static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
                                                unsigned int count)
 {
        for (; count != 0; count--, tab++) {
-               if ((idcode & tab->idmask) == tab->idcode)
+               if ((idcode & tab->idmask) == (tab->idcode & tab->idmask))
                        return tab;
        }
 
index 4e770355ccbc847ac904652727cb7eddc09af45b..4d4e571af5530dfd8ff5d72ef74be8d25b8a9b55 100644 (file)
@@ -107,7 +107,6 @@ static struct irq_chip s3c_irq_uart = {
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
 {
-       struct irq_desc *desc = irq_to_desc(uirq->parent_irq);
        void __iomem *reg_base = uirq->regs;
        unsigned int irq;
        int offs;
@@ -118,14 +117,13 @@ static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
        for (offs = 0; offs < 3; offs++) {
                irq = uirq->base_irq + offs;
 
-               set_irq_chip(irq, &s3c_irq_uart);
-               set_irq_chip_data(irq, uirq);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &s3c_irq_uart, handle_level_irq);
+               irq_set_chip_data(irq, uirq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       desc->irq_data.handler_data = uirq;
-       set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
+       irq_set_handler_data(uirq->parent_irq, uirq);
+       irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
 }
 
 /**
index dd8692ae5c4cecf7ea01f17fc3392aeaf584c63e..d6ad66ab9290464964789f9e68caa725f243bb67 100644 (file)
@@ -77,14 +77,11 @@ static struct irq_chip s3c_irq_timer = {
 void __init s3c_init_vic_timer_irq(unsigned int parent_irq,
                                   unsigned int timer_irq)
 {
-       struct irq_desc *desc = irq_to_desc(parent_irq);
 
-       set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
+       irq_set_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
+       irq_set_handler_data(parent_irq, (void *)timer_irq);
 
-       set_irq_chip(timer_irq, &s3c_irq_timer);
-       set_irq_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
-       set_irq_handler(timer_irq, handle_level_irq);
+       irq_set_chip_and_handler(timer_irq, &s3c_irq_timer, handle_level_irq);
+       irq_set_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
        set_irq_flags(timer_irq, IRQF_VALID);
-
-       desc->irq_data.handler_data = (void *)timer_irq;
 }
index 2e09b6ad84ca4af1e9f0caaa55556e4ce86af919..dc814037297ba3dfa61d9a214bc4b1781ce9eaf7 100644 (file)
@@ -22,7 +22,7 @@
 void samsung_sync_wakemask(void __iomem *reg,
                           struct samsung_wakeup_mask *mask, int nr_mask)
 {
-       struct irq_desc *desc;
+       struct irq_data *data;
        u32 val;
 
        val = __raw_readl(reg);
@@ -33,10 +33,10 @@ void samsung_sync_wakemask(void __iomem *reg,
                        continue;
                }
 
-               desc = irq_to_desc(mask->irq);
+               data = irq_get_irq_data(mask->irq);
 
-               /* bit of a liberty to read this directly from irq_desc. */
-               if (desc->wake_depth > 0)
+               /* bit of a liberty to read this directly from irq_data. */
+               if (irqd_is_wakeup_set(data))
                        val &= ~mask->bit;
                else
                        val |= mask->bit;
index 78189035e7f109202272419bee7d1169b1e38c0f..961fb7261243faf87baf47ce6ca420fc19b30d02 100644 (file)
@@ -68,7 +68,7 @@ static struct irq_chip shirq_chip = {
 static void shirq_handler(unsigned irq, struct irq_desc *desc)
 {
        u32 i, val, mask;
-       struct spear_shirq *shirq = get_irq_data(irq);
+       struct spear_shirq *shirq = irq_get_handler_data(irq);
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
        while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
@@ -105,14 +105,14 @@ int spear_shirq_register(struct spear_shirq *shirq)
        if (!shirq->dev_count)
                return -EINVAL;
 
-       set_irq_chained_handler(shirq->irq, shirq_handler);
+       irq_set_chained_handler(shirq->irq, shirq_handler);
        for (i = 0; i < shirq->dev_count; i++) {
-               set_irq_chip(shirq->dev_config[i].virq, &shirq_chip);
-               set_irq_handler(shirq->dev_config[i].virq, handle_simple_irq);
+               irq_set_chip_and_handler(shirq->dev_config[i].virq,
+                                        &shirq_chip, handle_simple_irq);
                set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
-               set_irq_chip_data(shirq->dev_config[i].virq, shirq);
+               irq_set_chip_data(shirq->dev_config[i].virq, shirq);
        }
 
-       set_irq_data(shirq->irq, shirq);
+       irq_set_handler_data(shirq->irq, shirq);
        return 0;
 }
index aaa168683d4e5734a24485a5807f4f8871a720c0..6fdf9acf82ed50ad70472c1c056106f59a5fa8c2 100644 (file)
@@ -35,8 +35,7 @@ void __init stmp3xxx_init_irq(struct irq_chip *chip)
        /* Disable all interrupts initially */
        for (i = 0; i < NR_REAL_IRQS; i++) {
                chip->irq_mask(irq_get_irq_data(i));
-               set_irq_chip(i, chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip_and_handler(i, chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
index 66d5bac3ace20046cbf237e93c758798b1d952b6..3def03b3217d009b51d30c03e88e81c797c24105 100644 (file)
@@ -489,14 +489,13 @@ static void stmp3xxx_gpio_free(struct gpio_chip *chip, unsigned offset)
 
 static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
 {
-       struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
+       struct stmp3xxx_pinmux_bank *pm = irq_get_handler_data(irq);
        int gpio_irq = pm->virq;
        u32 stat = __raw_readl(pm->irqstat);
 
        while (stat) {
                if (stat & 1)
-                       irq_desc[gpio_irq].handle_irq(gpio_irq,
-                               &irq_desc[gpio_irq]);
+                       generic_handle_irq(gpio_irq);
                gpio_irq++;
                stat >>= 1;
        }
@@ -534,15 +533,15 @@ int __init stmp3xxx_pinmux_init(int virtual_irq_start)
 
                for (virq = pm->virq; virq < pm->virq; virq++) {
                        gpio_irq_chip.irq_mask(irq_get_irq_data(virq));
-                       set_irq_chip(virq, &gpio_irq_chip);
-                       set_irq_handler(virq, handle_level_irq);
+                       irq_set_chip_and_handler(virq, &gpio_irq_chip,
+                                                handle_level_irq);
                        set_irq_flags(virq, IRQF_VALID);
                }
                r = gpiochip_add(&pm->chip);
                if (r < 0)
                        break;
-               set_irq_chained_handler(pm->irq, stmp3xxx_gpio_irq);
-               set_irq_data(pm->irq, pm);
+               irq_set_chained_handler(pm->irq, stmp3xxx_gpio_irq);
+               irq_set_handler_data(pm->irq, pm);
        }
        return r;
 }
index 31d945d37e4f10011421488c6b45deaa04a99c71..f0cc8e19b0943dcfb96078895b14d1232bf7ab79 100644 (file)
@@ -30,7 +30,7 @@ static void fpga_irq_unmask(struct irq_data *d)
 
 static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
 {
-       struct fpga_irq_data *f = get_irq_desc_data(desc);
+       struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
        u32 status = readl(f->base + IRQ_STATUS);
 
        if (status == 0) {
@@ -55,17 +55,17 @@ void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
        f->chip.irq_unmask = fpga_irq_unmask;
 
        if (parent_irq != -1) {
-               set_irq_data(parent_irq, f);
-               set_irq_chained_handler(parent_irq, fpga_irq_handle);
+               irq_set_handler_data(parent_irq, f);
+               irq_set_chained_handler(parent_irq, fpga_irq_handle);
        }
 
        for (i = 0; i < 32; i++) {
                if (valid & (1 << i)) {
                        unsigned int irq = f->irq_start + i;
 
-                       set_irq_chip_data(irq, f);
-                       set_irq_chip(irq, &f->chip);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip_data(irq, f);
+                       irq_set_chip_and_handler(irq, &f->chip,
+                                                handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
        }
index 8f079392aff07796ac1cc46edef17ba829649b10..1696d34f51c2ab369e54b2b319da1c2663e74358 100644 (file)
@@ -48,7 +48,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%3d: ", i);
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-               seq_printf(p, " %8s", get_irq_desc_chip(desc)->name);
+               seq_printf(p, " %8s", irq_desc_get_chip(desc)->name);
                seq_printf(p, "  %s", action->name);
                for (action = action->next; action; action = action->next)
                        seq_printf(p, "  %s", action->name);
index 05b550891ce563f72db45d3700c38fde46eecba8..050db44fe919ab0268a4c7bf519dac90ecb58cfe 100644 (file)
@@ -912,10 +912,11 @@ void show_regs(struct pt_regs *fp)
        /* if no interrupts are going off, don't print this out */
        if (fp->ipend & ~0x3F) {
                for (i = 0; i < (NR_IRQS - 1); i++) {
+                       struct irq_desc *desc = irq_to_desc(i);
                        if (!in_atomic)
-                               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
+                               raw_spin_lock_irqsave(&desc->lock, flags);
 
-                       action = irq_desc[i].action;
+                       action = desc->action;
                        if (!action)
                                goto unlock;
 
@@ -928,7 +929,7 @@ void show_regs(struct pt_regs *fp)
                        pr_cont("\n");
 unlock:
                        if (!in_atomic)
-                               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+                               raw_spin_unlock_irqrestore(&desc->lock, flags);
                }
        }
 
index 5d68bf613b0b9dbe0fde9e2e3055fe23c0375f63..7b07740cf68cdf828c101cced2e99bfe68e59613 100644 (file)
@@ -154,13 +154,13 @@ void platform_clear_ipi(unsigned int cpu, int irq)
 void __cpuinit bfin_local_timer_setup(void)
 {
 #if defined(CONFIG_TICKSOURCE_CORETMR)
-       struct irq_chip *chip = get_irq_chip(IRQ_CORETMR);
-       struct irq_desc *desc = irq_to_desc(IRQ_CORETMR);
+       struct irq_data *data = irq_get_irq_data(IRQ_CORETMR);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
 
        bfin_coretmr_init();
        bfin_coretmr_clockevent_init();
 
-       chip->irq_unmask(&desc->irq_data);
+       chip->irq_unmask(data);
 #else
        /* Power down the core timer, just to play safe. */
        bfin_write_TCNTL(0);
index 6cd52395a999866f778d6d89e8b879ee7ab8386e..43d9fb195c1ee7a82a548e34e08fba4802e128bc 100644 (file)
@@ -559,7 +559,7 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 #ifdef CONFIG_IPIPE
        handle = handle_level_irq;
 #endif
-       __set_irq_handler_unlocked(irq, handle);
+       __irq_set_handler_locked(irq, handle);
 }
 
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
@@ -578,10 +578,9 @@ static void bfin_gpio_ack_irq(struct irq_data *d)
 static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
        unsigned int irq = d->irq;
-       struct irq_desc *desc = irq_to_desc(irq);
        u32 gpionr = irq_to_gpio(irq);
 
-       if (desc->handle_irq == handle_edge_irq)
+       if (!irqd_is_level_type(d))
                set_gpio_data(gpionr, 0);
 
        set_gpio_maska(gpionr, 0);
@@ -837,12 +836,11 @@ void init_pint_lut(void)
 
 static void bfin_gpio_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
        u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
        u32 pintbit = PINT_BIT(pint_val);
        u32 bank = PINT_2_BANK(pint_val);
 
-       if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+       if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
                if (pint[bank]->invert_set & pintbit)
                        pint[bank]->invert_clear = pintbit;
                else
@@ -854,12 +852,11 @@ static void bfin_gpio_ack_irq(struct irq_data *d)
 
 static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
        u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
        u32 pintbit = PINT_BIT(pint_val);
        u32 bank = PINT_2_BANK(pint_val);
 
-       if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+       if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
                if (pint[bank]->invert_set & pintbit)
                        pint[bank]->invert_clear = pintbit;
                else
@@ -1166,9 +1163,9 @@ int __init init_arch_irq(void)
 
        for (irq = 0; irq <= SYS_IRQS; irq++) {
                if (irq <= IRQ_CORETMR)
-                       set_irq_chip(irq, &bfin_core_irqchip);
+                       irq_set_chip(irq, &bfin_core_irqchip);
                else
-                       set_irq_chip(irq, &bfin_internal_irqchip);
+                       irq_set_chip(irq, &bfin_internal_irqchip);
 
                switch (irq) {
 #if defined(CONFIG_BF53x)
@@ -1192,50 +1189,50 @@ int __init init_arch_irq(void)
 #elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
                case IRQ_PORTF_INTA:
 #endif
-                       set_irq_chained_handler(irq,
-                                               bfin_demux_gpio_irq);
+                       irq_set_chained_handler(irq, bfin_demux_gpio_irq);
                        break;
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
                case IRQ_GENERIC_ERROR:
-                       set_irq_chained_handler(irq, bfin_demux_error_irq);
+                       irq_set_chained_handler(irq, bfin_demux_error_irq);
                        break;
 #endif
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
                case IRQ_MAC_ERROR:
-                       set_irq_chained_handler(irq, bfin_demux_mac_status_irq);
+                       irq_set_chained_handler(irq,
+                                               bfin_demux_mac_status_irq);
                        break;
 #endif
 #ifdef CONFIG_SMP
                case IRQ_SUPPLE_0:
                case IRQ_SUPPLE_1:
-                       set_irq_handler(irq, handle_percpu_irq);
+                       irq_set_handler(irq, handle_percpu_irq);
                        break;
 #endif
 
 #ifdef CONFIG_TICKSOURCE_CORETMR
                case IRQ_CORETMR:
 # ifdef CONFIG_SMP
-                       set_irq_handler(irq, handle_percpu_irq);
+                       irq_set_handler(irq, handle_percpu_irq);
                        break;
 # else
-                       set_irq_handler(irq, handle_simple_irq);
+                       irq_set_handler(irq, handle_simple_irq);
                        break;
 # endif
 #endif
 
 #ifdef CONFIG_TICKSOURCE_GPTMR0
                case IRQ_TIMER0:
-                       set_irq_handler(irq, handle_simple_irq);
+                       irq_set_handler(irq, handle_simple_irq);
                        break;
 #endif
 
 #ifdef CONFIG_IPIPE
                default:
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_handler(irq, handle_level_irq);
                        break;
 #else /* !CONFIG_IPIPE */
                default:
-                       set_irq_handler(irq, handle_simple_irq);
+                       irq_set_handler(irq, handle_simple_irq);
                        break;
 #endif /* !CONFIG_IPIPE */
                }
@@ -1243,22 +1240,22 @@ int __init init_arch_irq(void)
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
        for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++)
-               set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip,
+               irq_set_chip_and_handler(irq, &bfin_generic_error_irqchip,
                                         handle_level_irq);
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-       set_irq_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
+       irq_set_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
 #endif
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
        for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
-               set_irq_chip_and_handler(irq, &bfin_mac_status_irqchip,
+               irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,
                                         handle_level_irq);
 #endif
        /* if configured as edge, then will be changed to do_edge_IRQ */
        for (irq = GPIO_IRQ_BASE;
                irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
-               set_irq_chip_and_handler(irq, &bfin_gpio_irqchip,
+               irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
                                         handle_level_irq);
 
        bfin_write_IMASK(0);
index 4db5b46e1effdeb4c4f85fd8692cb0fd37089c03..617925ddd142cd57712daa560be131138680e44f 100644 (file)
@@ -276,7 +276,6 @@ config ETRAX_AXISFLASHMAP
        select MTD_CHAR
        select MTD_BLOCK
        select MTD_PARTITIONS
-       select MTD_CONCAT
        select MTD_COMPLEX_MAPPINGS
        help
          This option enables MTD mapping of flash devices.  Needed to use
@@ -297,8 +296,7 @@ config ETRAX_RTC
 choice
        prompt "RTC chip"
        depends on ETRAX_RTC
-       default ETRAX_PCF8563 if ETRAX_ARCH_V32
-       default ETRAX_DS1302 if ETRAX_ARCH_V10
+       default ETRAX_DS1302
 
 config ETRAX_DS1302
        depends on ETRAX_ARCH_V10
index b2079703af7e381e508d6915d563ab89d8c5ee60..ed708e19d09eb3575c50c05f4c6cf06ee55c854d 100644 (file)
@@ -234,7 +234,6 @@ static struct mtd_info *flash_probe(void)
        }
 
        if (mtd_cse0 && mtd_cse1) {
-#ifdef CONFIG_MTD_CONCAT
                struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 };
 
                /* Since the concatenation layer adds a small overhead we
@@ -246,11 +245,6 @@ static struct mtd_info *flash_probe(void)
                 */
                mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
                                            "cse0+cse1");
-#else
-               printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
-                      "(mis)configuration!\n", map_cse0.name, map_cse1.name);
-               mtd_cse = NULL;
-#endif
                if (!mtd_cse) {
                        printk(KERN_ERR "%s and %s: Concatenation failed!\n",
                               map_cse0.name, map_cse1.name);
index ea69faba9b6212f00a731652e96966ed1116186c..1391b731ad1c5579b5317098bfc0c381270f34bb 100644 (file)
@@ -345,7 +345,7 @@ static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned
        int ret;
 
        mutex_lock(&pcf8563_mutex);
-       return pcf8563_ioctl(filp, cmd, arg);
+       ret = pcf8563_ioctl(filp, cmd, arg);
        mutex_unlock(&pcf8563_mutex);
 
        return ret;
index b6be705c2a3e6fb7ec2994600e47deaebfcadbfa..e78fe49a98490723c16d7d3e9684e536dae4ec2a 100644 (file)
@@ -537,7 +537,7 @@ void do_signal(int canrestart, struct pt_regs *regs)
                        RESTART_CRIS_SYS(regs);
                }
                if (regs->r10 == -ERESTART_RESTARTBLOCK) {
-                       regs->r10 = __NR_restart_syscall;
+                       regs->r9 = __NR_restart_syscall;
                        regs->irp -= 2;
                }
        }
index a2dd740c5907868f54985a1176ea73df3d752c63..1633b120aa81a413b00422629cdbc61a4310ce4a 100644 (file)
@@ -406,7 +406,6 @@ config ETRAX_AXISFLASHMAP
        select MTD_CHAR
        select MTD_BLOCK
        select MTD_PARTITIONS
-       select MTD_CONCAT
        select MTD_COMPLEX_MAPPINGS
        help
          This option enables MTD mapping of flash devices.  Needed to use
index e8c02437edaf609e07b94b82ab5fb752701b7337..39aa3c117a86fd83a7bc4d4059e16e57edd06b16 100644 (file)
@@ -7,7 +7,6 @@ obj-$(CONFIG_ETRAX_AXISFLASHMAP)        += axisflashmap.o
 obj-$(CONFIG_ETRAXFS)                   += mach-fs/
 obj-$(CONFIG_CRIS_MACH_ARTPEC3)         += mach-a3/
 obj-$(CONFIG_ETRAX_IOP_FW_LOAD)         += iop_fw_load.o
-obj-$(CONFIG_ETRAX_PCF8563)            += pcf8563.o
 obj-$(CONFIG_ETRAX_I2C)                        += i2c.o
 obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
 obj-$(CONFIG_PCI)                      += pci/
index 51e1e85df96d5407940c0376e28158724f9c5cb1..3d751250271bee38334a41c4b63073ea4beb453d 100644 (file)
@@ -275,7 +275,6 @@ static struct mtd_info *flash_probe(void)
        }
 
        if (count > 1) {
-#ifdef CONFIG_MTD_CONCAT
                /* Since the concatenation layer adds a small overhead we
                 * could try to figure out if the chips in cse0 and cse1 are
                 * identical and reprobe the whole cse0+cse1 window. But since
@@ -284,11 +283,6 @@ static struct mtd_info *flash_probe(void)
                 * complicating the probing procedure.
                 */
                mtd_total = mtd_concat_create(mtds, count, "cse0+cse1");
-#else
-               printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
-                      "(mis)configuration!\n", map_cse0.name, map_cse1.name);
-               mtd_toal = NULL;
-#endif
                if (!mtd_total) {
                        printk(KERN_ERR "%s and %s: Concatenation failed!\n",
                                map_cse0.name, map_cse1.name);
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
deleted file mode 100644 (file)
index b6e4fc0..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * PCF8563 RTC
- *
- * From Phillips' datasheet:
- *
- * The PCF8563 is a CMOS real-time clock/calendar optimized for low power
- * consumption. A programmable clock output, interrupt output and voltage
- * low detector are also provided. All address and data are transferred
- * serially via two-line bidirectional I2C-bus. Maximum bus speed is
- * 400 kbits/s. The built-in word address register is incremented
- * automatically after each written or read byte.
- *
- * Copyright (c) 2002-2007, Axis Communications AB
- * All rights reserved.
- *
- * Author: Tobias Anderberg <tobiasa@axis.com>.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/delay.h>
-#include <linux/bcd.h>
-#include <linux/mutex.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/rtc.h>
-
-#include "i2c.h"
-
-#define PCF8563_MAJOR  121     /* Local major number. */
-#define DEVICE_NAME    "rtc"   /* Name which is registered in /proc/devices. */
-#define PCF8563_NAME   "PCF8563"
-#define DRIVER_VERSION "$Revision: 1.17 $"
-
-/* Two simple wrapper macros, saves a few keystrokes. */
-#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[] =
-       { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-
-/* Cache VL bit value read at driver init since writing the RTC_SECOND
- * register clears the VL status.
- */
-static int voltage_low;
-
-static const struct file_operations pcf8563_fops = {
-       .owner          = THIS_MODULE,
-       .unlocked_ioctl = pcf8563_unlocked_ioctl,
-       .llseek         = noop_llseek,
-};
-
-unsigned char
-pcf8563_readreg(int reg)
-{
-       unsigned char res = rtc_read(reg);
-
-       /* The PCF8563 does not return 0 for unimplemented bits. */
-       switch (reg) {
-               case RTC_SECONDS:
-               case RTC_MINUTES:
-                       res &= 0x7F;
-                       break;
-               case RTC_HOURS:
-               case RTC_DAY_OF_MONTH:
-                       res &= 0x3F;
-                       break;
-               case RTC_WEEKDAY:
-                       res &= 0x07;
-                       break;
-               case RTC_MONTH:
-                       res &= 0x1F;
-                       break;
-               case RTC_CONTROL1:
-                       res &= 0xA8;
-                       break;
-               case RTC_CONTROL2:
-                       res &= 0x1F;
-                       break;
-               case RTC_CLOCKOUT_FREQ:
-               case RTC_TIMER_CONTROL:
-                       res &= 0x83;
-                       break;
-       }
-       return res;
-}
-
-void
-pcf8563_writereg(int reg, unsigned char val)
-{
-       rtc_write(reg, val);
-}
-
-void
-get_rtc_time(struct rtc_time *tm)
-{
-       tm->tm_sec  = rtc_read(RTC_SECONDS);
-       tm->tm_min  = rtc_read(RTC_MINUTES);
-       tm->tm_hour = rtc_read(RTC_HOURS);
-       tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
-       tm->tm_wday = rtc_read(RTC_WEEKDAY);
-       tm->tm_mon  = rtc_read(RTC_MONTH);
-       tm->tm_year = rtc_read(RTC_YEAR);
-
-       if (tm->tm_sec & 0x80) {
-               printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "
-                      "information is no longer guaranteed!\n", PCF8563_NAME);
-       }
-
-       tm->tm_year  = bcd2bin(tm->tm_year) +
-                      ((tm->tm_mon & 0x80) ? 100 : 0);
-       tm->tm_sec  &= 0x7F;
-       tm->tm_min  &= 0x7F;
-       tm->tm_hour &= 0x3F;
-       tm->tm_mday &= 0x3F;
-       tm->tm_wday &= 0x07; /* Not coded in BCD. */
-       tm->tm_mon  &= 0x1F;
-
-       tm->tm_sec = bcd2bin(tm->tm_sec);
-       tm->tm_min = bcd2bin(tm->tm_min);
-       tm->tm_hour = bcd2bin(tm->tm_hour);
-       tm->tm_mday = bcd2bin(tm->tm_mday);
-       tm->tm_mon = bcd2bin(tm->tm_mon);
-       tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
-}
-
-int __init
-pcf8563_init(void)
-{
-       static int res;
-       static int first = 1;
-
-       if (!first)
-               return res;
-       first = 0;
-
-       /* Initiate the i2c protocol. */
-       res = i2c_init();
-       if (res < 0) {
-               printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
-               return res;
-       }
-
-       /*
-        * First of all we need to reset the chip. This is done by
-        * clearing control1, control2 and clk freq and resetting
-        * all alarms.
-        */
-       if (rtc_write(RTC_CONTROL1, 0x00) < 0)
-               goto err;
-
-       if (rtc_write(RTC_CONTROL2, 0x00) < 0)
-               goto err;
-
-       if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
-               goto err;
-
-       if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
-               goto err;
-
-       /* Reset the alarms. */
-       if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
-               goto err;
-
-       if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
-               goto err;
-
-       if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
-               goto err;
-
-       if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
-               goto err;
-
-       /* Check for low voltage, and warn about it. */
-       if (rtc_read(RTC_SECONDS) & 0x80) {
-               voltage_low = 1;
-               printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
-                      "date/time information is no longer guaranteed!\n",
-                      PCF8563_NAME);
-       }
-
-       return res;
-
-err:
-       printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
-       res = -1;
-       return res;
-}
-
-void __exit
-pcf8563_exit(void)
-{
-       unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME);
-}
-
-/*
- * ioctl calls for this driver. Why return -ENOTTY upon error? Because
- * POSIX says so!
- */
-static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       /* Some sanity checks. */
-       if (_IOC_TYPE(cmd) != RTC_MAGIC)
-               return -ENOTTY;
-
-       if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
-               return -ENOTTY;
-
-       switch (cmd) {
-       case RTC_RD_TIME:
-       {
-               struct rtc_time tm;
-
-               mutex_lock(&rtc_lock);
-               memset(&tm, 0, sizeof tm);
-               get_rtc_time(&tm);
-
-               if (copy_to_user((struct rtc_time *) arg, &tm,
-                                sizeof tm)) {
-                       mutex_unlock(&rtc_lock);
-                       return -EFAULT;
-               }
-
-               mutex_unlock(&rtc_lock);
-
-               return 0;
-       }
-       case RTC_SET_TIME:
-       {
-               int leap;
-               int year;
-               int century;
-               struct rtc_time tm;
-
-               memset(&tm, 0, sizeof tm);
-               if (!capable(CAP_SYS_TIME))
-                       return -EPERM;
-
-               if (copy_from_user(&tm, (struct rtc_time *) arg,
-                                  sizeof tm))
-                       return -EFAULT;
-
-               /* Convert from struct tm to struct rtc_time. */
-               tm.tm_year += 1900;
-               tm.tm_mon += 1;
-
-               /*
-                * Check if tm.tm_year is a leap year. A year is a leap
-                * year if it is divisible by 4 but not 100, except
-                * that years divisible by 400 _are_ leap years.
-                */
-               year = tm.tm_year;
-               leap = (tm.tm_mon == 2) &&
-                       ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
-
-               /* Perform some sanity checks. */
-               if ((tm.tm_year < 1970) ||
-                   (tm.tm_mon > 12) ||
-                   (tm.tm_mday == 0) ||
-                   (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
-                   (tm.tm_wday >= 7) ||
-                   (tm.tm_hour >= 24) ||
-                   (tm.tm_min >= 60) ||
-                   (tm.tm_sec >= 60))
-                       return -EINVAL;
-
-               century = (tm.tm_year >= 2000) ? 0x80 : 0;
-               tm.tm_year = tm.tm_year % 100;
-
-               tm.tm_year = bin2bcd(tm.tm_year);
-               tm.tm_mon = bin2bcd(tm.tm_mon);
-               tm.tm_mday = bin2bcd(tm.tm_mday);
-               tm.tm_hour = bin2bcd(tm.tm_hour);
-               tm.tm_min = bin2bcd(tm.tm_min);
-               tm.tm_sec = bin2bcd(tm.tm_sec);
-               tm.tm_mon |= century;
-
-               mutex_lock(&rtc_lock);
-
-               rtc_write(RTC_YEAR, tm.tm_year);
-               rtc_write(RTC_MONTH, tm.tm_mon);
-               rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
-               rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
-               rtc_write(RTC_HOURS, tm.tm_hour);
-               rtc_write(RTC_MINUTES, tm.tm_min);
-               rtc_write(RTC_SECONDS, tm.tm_sec);
-
-               mutex_unlock(&rtc_lock);
-
-               return 0;
-       }
-       case RTC_VL_READ:
-               if (voltage_low)
-                       printk(KERN_ERR "%s: RTC Voltage Low - "
-                              "reliable date/time information is no "
-                              "longer guaranteed!\n", PCF8563_NAME);
-
-               if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
-                       return -EFAULT;
-               return 0;
-
-       case RTC_VL_CLR:
-       {
-               /* Clear the VL bit in the seconds register in case
-                * the time has not been set already (which would
-                * have cleared it). This does not really matter
-                * because of the cached voltage_low value but do it
-                * anyway for consistency. */
-
-               int ret = rtc_read(RTC_SECONDS);
-
-               rtc_write(RTC_SECONDS, (ret & 0x7F));
-
-               /* Clear the cached value. */
-               voltage_low = 0;
-
-               return 0;
-       }
-       default:
-               return -ENOTTY;
-       }
-
-       return 0;
-}
-
-static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       int ret;
-
-       mutex_lock(&pcf8563_mutex);
-       return pcf8563_ioctl(filp, cmd, arg);
-       mutex_unlock(&pcf8563_mutex);
-
-       return ret;
-}
-
-static int __init pcf8563_register(void)
-{
-       if (pcf8563_init() < 0) {
-               printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "
-                      "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
-               return -1;
-       }
-
-       if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-               printk(KERN_INFO "%s: Unable to get major numer %d for RTC "
-                      "device.\n", PCF8563_NAME, PCF8563_MAJOR);
-               return -1;
-       }
-
-       printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,
-              DRIVER_VERSION);
-
-       /* Check for low voltage, and warn about it. */
-       if (voltage_low) {
-               printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
-                      "information is no longer guaranteed!\n", PCF8563_NAME);
-       }
-
-       return 0;
-}
-
-module_init(pcf8563_register);
-module_exit(pcf8563_exit);
index f6037b2da25ef6f9af5ed31187afac45058c7256..6db8aea5667fae5cda6c2dae62e7f6b0e4b123dd 100644 (file)
@@ -6,6 +6,8 @@ config FRV
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_SHOW
+       select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config ZONE_DMA
        bool
@@ -361,7 +363,6 @@ menu "Power management options"
 
 config ARCH_SUSPEND_POSSIBLE
        def_bool y
-       depends on !SMP
 
 source kernel/power/Kconfig
 endmenu
index 0a6d8d9ca45bdbb6398b2ff2882203743963ea8b..6c10fd2c626ddde848763573e7caf769f479e42f 100644 (file)
@@ -45,21 +45,12 @@ do {                                                                        \
 #define wmb()                  asm volatile ("membar" : : :"memory")
 #define read_barrier_depends() do { } while (0)
 
-#ifdef CONFIG_SMP
-#define smp_mb()                       mb()
-#define smp_rmb()                      rmb()
-#define smp_wmb()                      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) \
-       do { xchg(&var, (value)); } while (0)
-#else
 #define smp_mb()                       barrier()
 #define smp_rmb()                      barrier()
 #define smp_wmb()                      barrier()
 #define smp_read_barrier_depends()     do {} while(0)
 #define set_mb(var, value) \
        do { var = (value); barrier(); } while (0)
-#endif
 
 extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
 extern void free_initmem(void);
index 8582e9c7531c8f3433f0749fec1861cf92847919..cefbe73dc119c5b265e59c83d3da7d230278560e 100644 (file)
@@ -21,6 +21,8 @@
 
 #define THREAD_SIZE            8192
 
+#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+
 /*
  * low level task data that entry.S needs immediate access to
  * - this struct should fit entirely inside of one cache line
@@ -87,7 +89,7 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define alloc_thread_info_node(tsk, node)                      \
                kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info_node(tsk)                            \
+#define alloc_thread_info_node(tsk, node)                      \
                kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
index 4dd9adaf115a4de8083ce7bfde075e5f3ac82123..9afc2ea400dc4b79931c624d7013251706ae1a0e 100644 (file)
 /*
  * on-motherboard FPGA PIC operations
  */
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr |= 1 << (irq - IRQ_BASE_FPGA);
+       imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 
        __set_IMR(imr);
 }
 
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
 {
-       __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+       __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr |= 1 << (irq - IRQ_BASE_FPGA);
+       imr |= 1 << (d->irq - IRQ_BASE_FPGA);
        __set_IMR(imr);
 
-       __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+       __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+       imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 
        __set_IMR(imr);
 }
 
 static struct irq_chip frv_fpga_pic = {
        .name           = "mb93091",
-       .ack            = frv_fpga_ack,
-       .mask           = frv_fpga_mask,
-       .mask_ack       = frv_fpga_mask_ack,
-       .unmask         = frv_fpga_unmask,
+       .irq_ack        = frv_fpga_ack,
+       .irq_mask       = frv_fpga_mask,
+       .irq_mask_ack   = frv_fpga_mask_ack,
+       .irq_unmask     = frv_fpga_unmask,
 };
 
 /*
@@ -146,9 +146,9 @@ void __init fpga_init(void)
        __clr_IFR(0x0000);
 
        for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
-               set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
+               irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
 
-       set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
+       irq_set_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
 
        /* the FPGA drives the first four external IRQ inputs on the CPU PIC */
        setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
index e45209031873e63de6e0202bbd3e831a29ff27bb..4d4ad09d3c919e7ff8cdcf38f79aecff42ecf210 100644 (file)
 /*
  * off-CPU FPGA PIC operations
  */
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr |= 1 << (irq - IRQ_BASE_FPGA);
+       imr |= 1 << (d->irq - IRQ_BASE_FPGA);
        __set_IMR(imr);
 }
 
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
 {
-       __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+       __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr |= 1 << (irq - IRQ_BASE_FPGA);
+       imr |= 1 << (d->irq - IRQ_BASE_FPGA);
        __set_IMR(imr);
 
-       __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+       __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
 {
        uint16_t imr = __get_IMR();
 
-       imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+       imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 
        __set_IMR(imr);
 }
 
 static struct irq_chip frv_fpga_pic = {
        .name           = "mb93093",
-       .ack            = frv_fpga_ack,
-       .mask           = frv_fpga_mask,
-       .mask_ack       = frv_fpga_mask_ack,
-       .unmask         = frv_fpga_unmask,
-       .end            = frv_fpga_end,
+       .irq_ack        = frv_fpga_ack,
+       .irq_mask       = frv_fpga_mask,
+       .irq_mask_ack   = frv_fpga_mask_ack,
+       .irq_unmask     = frv_fpga_unmask,
 };
 
 /*
@@ -94,7 +93,7 @@ static irqreturn_t fpga_interrupt(int irq, void *_mask)
                irq = 31 - irq;
                mask &= ~(1 << irq);
 
-               generic_irq_handle(IRQ_BASE_FPGA + irq);
+               generic_handle_irq(IRQ_BASE_FPGA + irq);
        }
 
        return IRQ_HANDLED;
@@ -125,7 +124,7 @@ void __init fpga_init(void)
        __clr_IFR(0x0000);
 
        for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
-               set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
 
        /* the FPGA drives external IRQ input #2 on the CPU PIC */
        setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
index ba55ecdfb245a5c201bf34583bcad836677ea26e..4d034c7840c9270f26359cb32378cab20e321b18 100644 (file)
  * daughter board PIC operations
  * - there is no way to ACK interrupts in the MB93493 chip
  */
-static void frv_mb93493_mask(unsigned int irq)
+static void frv_mb93493_mask(struct irq_data *d)
 {
        uint32_t iqsr;
        volatile void *piqsr;
 
-       if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+       if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
                piqsr = __addr_MB93493_IQSR(1);
        else
                piqsr = __addr_MB93493_IQSR(0);
 
        iqsr = readl(piqsr);
-       iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
+       iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16));
        writel(iqsr, piqsr);
 }
 
-static void frv_mb93493_ack(unsigned int irq)
+static void frv_mb93493_ack(struct irq_data *d)
 {
 }
 
-static void frv_mb93493_unmask(unsigned int irq)
+static void frv_mb93493_unmask(struct irq_data *d)
 {
        uint32_t iqsr;
        volatile void *piqsr;
 
-       if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+       if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
                piqsr = __addr_MB93493_IQSR(1);
        else
                piqsr = __addr_MB93493_IQSR(0);
 
        iqsr = readl(piqsr);
-       iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
+       iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16);
        writel(iqsr, piqsr);
 }
 
 static struct irq_chip frv_mb93493_pic = {
        .name           = "mb93093",
-       .ack            = frv_mb93493_ack,
-       .mask           = frv_mb93493_mask,
-       .mask_ack       = frv_mb93493_mask,
-       .unmask         = frv_mb93493_unmask,
+       .irq_ack        = frv_mb93493_ack,
+       .irq_mask       = frv_mb93493_mask,
+       .irq_mask_ack   = frv_mb93493_mask,
+       .irq_unmask     = frv_mb93493_unmask,
 };
 
 /*
@@ -139,7 +139,8 @@ void __init mb93493_init(void)
        int irq;
 
        for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
-               set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &frv_mb93493_pic,
+                                        handle_edge_irq);
 
        /* the MB93493 drives external IRQ inputs on the CPU PIC */
        setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
index 625136625a7fef7a0aea779e8d34d15f9c2e345c..a5f624a9f5593de4221f8d038077fb56bce9e5f9 100644 (file)
@@ -47,89 +47,45 @@ extern void __init mb93493_init(void);
 
 atomic_t irq_err_count;
 
-/*
- * Generic, controller-independent functions:
- */
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int i = *(loff_t *) v, cpu;
-       struct irqaction * action;
-       unsigned long flags;
-
-       if (i == 0) {
-               char cpuname[12];
-
-               seq_printf(p, "    ");
-               for_each_present_cpu(cpu) {
-                       sprintf(cpuname, "CPU%d", cpu);
-                       seq_printf(p, " %10s", cpuname);
-               }
-               seq_putc(p, '\n');
-       }
-
-       if (i < NR_IRQS) {
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
-               if (action) {
-                       seq_printf(p, "%3d: ", i);
-                       for_each_present_cpu(cpu)
-                               seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-                       seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
-                       seq_printf(p, "  %s", action->name);
-                       for (action = action->next;
-                            action;
-                            action = action->next)
-                               seq_printf(p, ", %s", action->name);
-
-                       seq_putc(p, '\n');
-               }
-
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS) {
-               seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
-       }
-
+       seq_printf(p, "%*s: ", prec, "ERR");
+       seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
        return 0;
 }
 
 /*
  * on-CPU PIC operations
  */
-static void frv_cpupic_ack(unsigned int irqlevel)
+static void frv_cpupic_ack(struct irq_data *d)
 {
-       __clr_RC(irqlevel);
+       __clr_RC(d->irq);
        __clr_IRL();
 }
 
-static void frv_cpupic_mask(unsigned int irqlevel)
+static void frv_cpupic_mask(struct irq_data *d)
 {
-       __set_MASK(irqlevel);
+       __set_MASK(d->irq);
 }
 
-static void frv_cpupic_mask_ack(unsigned int irqlevel)
+static void frv_cpupic_mask_ack(struct irq_data *d)
 {
-       __set_MASK(irqlevel);
-       __clr_RC(irqlevel);
+       __set_MASK(d->irq);
+       __clr_RC(d->irq);
        __clr_IRL();
 }
 
-static void frv_cpupic_unmask(unsigned int irqlevel)
-{
-       __clr_MASK(irqlevel);
-}
-
-static void frv_cpupic_end(unsigned int irqlevel)
+static void frv_cpupic_unmask(struct irq_data *d)
 {
-       __clr_MASK(irqlevel);
+       __clr_MASK(d->irq);
 }
 
 static struct irq_chip frv_cpu_pic = {
        .name           = "cpu",
-       .ack            = frv_cpupic_ack,
-       .mask           = frv_cpupic_mask,
-       .mask_ack       = frv_cpupic_mask_ack,
-       .unmask         = frv_cpupic_unmask,
-       .end            = frv_cpupic_end,
+       .irq_ack        = frv_cpupic_ack,
+       .irq_mask       = frv_cpupic_mask,
+       .irq_mask_ack   = frv_cpupic_mask_ack,
+       .irq_unmask     = frv_cpupic_unmask,
 };
 
 /*
@@ -161,10 +117,10 @@ void __init init_IRQ(void)
        int level;
 
        for (level = 1; level <= 14; level++)
-               set_irq_chip_and_handler(level, &frv_cpu_pic,
+               irq_set_chip_and_handler(level, &frv_cpu_pic,
                                         handle_level_irq);
 
-       set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
+       irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq);
 
        /* set the trigger levels for internal interrupt sources
         * - timers all falling-edge
index fcf3b437a2d9a859365310bf35e0dae769db6005..c4ea0925cdbd081c89b56d2620af906514f4c01c 100644 (file)
@@ -26,6 +26,7 @@ config IA64
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
        select IRQ_PER_CPU
+       select GENERIC_IRQ_SHOW
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index b272261d77cc7b3a2e05ef7c306c6d52ebee38fc..4bd9a63260eeda8c98c4f1cca66c4a9ccdf29a4c 100644 (file)
 #include <linux/irq.h>
 
 static unsigned int
-hpsim_irq_startup (unsigned int irq)
+hpsim_irq_startup(struct irq_data *data)
 {
        return 0;
 }
 
 static void
-hpsim_irq_noop (unsigned int irq)
+hpsim_irq_noop(struct irq_data *data)
 {
 }
 
 static int
-hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
+hpsim_set_affinity_noop(struct irq_data *d, const struct cpumask *b, bool f)
 {
        return 0;
 }
 
 static struct irq_chip irq_type_hp_sim = {
-       .name =         "hpsim",
-       .startup =      hpsim_irq_startup,
-       .shutdown =     hpsim_irq_noop,
-       .enable =       hpsim_irq_noop,
-       .disable =      hpsim_irq_noop,
-       .ack =          hpsim_irq_noop,
-       .end =          hpsim_irq_noop,
-       .set_affinity = hpsim_set_affinity_noop,
+       .name =                 "hpsim",
+       .irq_startup =          hpsim_irq_startup,
+       .irq_shutdown =         hpsim_irq_noop,
+       .irq_enable =           hpsim_irq_noop,
+       .irq_disable =          hpsim_irq_noop,
+       .irq_ack =              hpsim_irq_noop,
+       .irq_set_affinity =     hpsim_set_affinity_noop,
 };
 
 void __init
 hpsim_irq_init (void)
 {
-       struct irq_desc *idesc;
        int i;
 
-       for (i = 0; i < NR_IRQS; ++i) {
-               idesc = irq_desc + i;
-               if (idesc->chip == &no_irq_chip)
-                       idesc->chip = &irq_type_hp_sim;
+       for_each_active_irq(i) {
+               struct irq_chip *chip = irq_get_chip(i);
+
+               if (chip == &no_irq_chip)
+                       irq_set_chip(i, &irq_type_hp_sim);
        }
 }
index bf2e37493e04c6b28544779377cc72d8ce21a2e2..a681d02cb324c02a4d1f39cf0d5b1b301901d271 100644 (file)
@@ -151,9 +151,6 @@ static inline void ia64_native_resend_irq(unsigned int vector)
 /*
  * Default implementations for the irq-descriptor API:
  */
-
-extern struct irq_desc irq_desc[NR_IRQS];
-
 #ifndef CONFIG_IA64_GENERIC
 static inline ia64_vector __ia64_irq_to_vector(int irq)
 {
index 22c38404f539eeb9ab268ca226db94d1e243e860..b0f9afebb1467d4e2eccf6c16601c7257f378620 100644 (file)
@@ -257,7 +257,7 @@ set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
 }
 
 static void
-nop (unsigned int irq)
+nop (struct irq_data *data)
 {
        /* do nothing... */
 }
@@ -287,8 +287,9 @@ kexec_disable_iosapic(void)
 #endif
 
 static void
-mask_irq (unsigned int irq)
+mask_irq (struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        u32 low32;
        int rte_index;
        struct iosapic_rte_info *rte;
@@ -305,8 +306,9 @@ mask_irq (unsigned int irq)
 }
 
 static void
-unmask_irq (unsigned int irq)
+unmask_irq (struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        u32 low32;
        int rte_index;
        struct iosapic_rte_info *rte;
@@ -323,9 +325,11 @@ unmask_irq (unsigned int irq)
 
 
 static int
-iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
+iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                    bool force)
 {
 #ifdef CONFIG_SMP
+       unsigned int irq = data->irq;
        u32 high32, low32;
        int cpu, dest, rte_index;
        int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
@@ -379,32 +383,33 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
  */
 
 static unsigned int
-iosapic_startup_level_irq (unsigned int irq)
+iosapic_startup_level_irq (struct irq_data *data)
 {
-       unmask_irq(irq);
+       unmask_irq(data);
        return 0;
 }
 
 static void
-iosapic_unmask_level_irq (unsigned int irq)
+iosapic_unmask_level_irq (struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        ia64_vector vec = irq_to_vector(irq);
        struct iosapic_rte_info *rte;
        int do_unmask_irq = 0;
 
        irq_complete_move(irq);
-       if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+       if (unlikely(irqd_is_setaffinity_pending(data))) {
                do_unmask_irq = 1;
-               mask_irq(irq);
+               mask_irq(data);
        } else
-               unmask_irq(irq);
+               unmask_irq(data);
 
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
                iosapic_eoi(rte->iosapic->addr, vec);
 
        if (unlikely(do_unmask_irq)) {
-               move_masked_irq(irq);
-               unmask_irq(irq);
+               irq_move_masked_irq(data);
+               unmask_irq(data);
        }
 }
 
@@ -414,15 +419,15 @@ iosapic_unmask_level_irq (unsigned int irq)
 #define iosapic_ack_level_irq          nop
 
 static struct irq_chip irq_type_iosapic_level = {
-       .name =         "IO-SAPIC-level",
-       .startup =      iosapic_startup_level_irq,
-       .shutdown =     iosapic_shutdown_level_irq,
-       .enable =       iosapic_enable_level_irq,
-       .disable =      iosapic_disable_level_irq,
-       .ack =          iosapic_ack_level_irq,
-       .mask =         mask_irq,
-       .unmask =       iosapic_unmask_level_irq,
-       .set_affinity = iosapic_set_affinity
+       .name =                 "IO-SAPIC-level",
+       .irq_startup =          iosapic_startup_level_irq,
+       .irq_shutdown =         iosapic_shutdown_level_irq,
+       .irq_enable =           iosapic_enable_level_irq,
+       .irq_disable =          iosapic_disable_level_irq,
+       .irq_ack =              iosapic_ack_level_irq,
+       .irq_mask =             mask_irq,
+       .irq_unmask =           iosapic_unmask_level_irq,
+       .irq_set_affinity =     iosapic_set_affinity
 };
 
 /*
@@ -430,9 +435,9 @@ static struct irq_chip irq_type_iosapic_level = {
  */
 
 static unsigned int
-iosapic_startup_edge_irq (unsigned int irq)
+iosapic_startup_edge_irq (struct irq_data *data)
 {
-       unmask_irq(irq);
+       unmask_irq(data);
        /*
         * IOSAPIC simply drops interrupts pended while the
         * corresponding pin was masked, so we can't know if an
@@ -442,37 +447,25 @@ iosapic_startup_edge_irq (unsigned int irq)
 }
 
 static void
-iosapic_ack_edge_irq (unsigned int irq)
+iosapic_ack_edge_irq (struct irq_data *data)
 {
-       struct irq_desc *idesc = irq_desc + irq;
-
-       irq_complete_move(irq);
-       move_native_irq(irq);
-       /*
-        * Once we have recorded IRQ_PENDING already, we can mask the
-        * interrupt for real. This prevents IRQ storms from unhandled
-        * devices.
-        */
-       if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) ==
-           (IRQ_PENDING|IRQ_DISABLED))
-               mask_irq(irq);
+       irq_complete_move(data->irq);
+       irq_move_irq(data);
 }
 
 #define iosapic_enable_edge_irq                unmask_irq
 #define iosapic_disable_edge_irq       nop
-#define iosapic_end_edge_irq           nop
 
 static struct irq_chip irq_type_iosapic_edge = {
-       .name =         "IO-SAPIC-edge",
-       .startup =      iosapic_startup_edge_irq,
-       .shutdown =     iosapic_disable_edge_irq,
-       .enable =       iosapic_enable_edge_irq,
-       .disable =      iosapic_disable_edge_irq,
-       .ack =          iosapic_ack_edge_irq,
-       .end =          iosapic_end_edge_irq,
-       .mask =         mask_irq,
-       .unmask =       unmask_irq,
-       .set_affinity = iosapic_set_affinity
+       .name =                 "IO-SAPIC-edge",
+       .irq_startup =          iosapic_startup_edge_irq,
+       .irq_shutdown =         iosapic_disable_edge_irq,
+       .irq_enable =           iosapic_enable_edge_irq,
+       .irq_disable =          iosapic_disable_edge_irq,
+       .irq_ack =              iosapic_ack_edge_irq,
+       .irq_mask =             mask_irq,
+       .irq_unmask =           unmask_irq,
+       .irq_set_affinity =     iosapic_set_affinity
 };
 
 static unsigned int
@@ -562,8 +555,7 @@ static int
 register_intr (unsigned int gsi, int irq, unsigned char delivery,
               unsigned long polarity, unsigned long trigger)
 {
-       struct irq_desc *idesc;
-       struct irq_chip *irq_type;
+       struct irq_chip *chip, *irq_type;
        int index;
        struct iosapic_rte_info *rte;
 
@@ -610,19 +602,18 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
 
        irq_type = iosapic_get_irq_chip(trigger);
 
-       idesc = irq_desc + irq;
-       if (irq_type != NULL && idesc->chip != irq_type) {
-               if (idesc->chip != &no_irq_chip)
+       chip = irq_get_chip(irq);
+       if (irq_type != NULL && chip != irq_type) {
+               if (chip != &no_irq_chip)
                        printk(KERN_WARNING
                               "%s: changing vector %d from %s to %s\n",
                               __func__, irq_to_vector(irq),
-                              idesc->chip->name, irq_type->name);
-               idesc->chip = irq_type;
+                              chip->name, irq_type->name);
+               chip = irq_type;
        }
-       if (trigger == IOSAPIC_EDGE)
-               __set_irq_handler_unlocked(irq, handle_edge_irq);
-       else
-               __set_irq_handler_unlocked(irq, handle_level_irq);
+       __irq_set_chip_handler_name_locked(irq, chip, trigger == IOSAPIC_EDGE ?
+                                          handle_edge_irq : handle_level_irq,
+                                          NULL);
        return 0;
 }
 
@@ -732,6 +723,7 @@ iosapic_register_intr (unsigned int gsi,
        struct iosapic_rte_info *rte;
        u32 low32;
        unsigned char dmode;
+       struct irq_desc *desc;
 
        /*
         * If this GSI has already been registered (i.e., it's a
@@ -759,12 +751,13 @@ iosapic_register_intr (unsigned int gsi,
                        goto unlock_iosapic_lock;
        }
 
-       raw_spin_lock(&irq_desc[irq].lock);
+       desc = irq_to_desc(irq);
+       raw_spin_lock(&desc->lock);
        dest = get_target_cpu(gsi, irq);
        dmode = choose_dmode();
        err = register_intr(gsi, irq, dmode, polarity, trigger);
        if (err < 0) {
-               raw_spin_unlock(&irq_desc[irq].lock);
+               raw_spin_unlock(&desc->lock);
                irq = err;
                goto unlock_iosapic_lock;
        }
@@ -783,7 +776,7 @@ iosapic_register_intr (unsigned int gsi,
               (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
               cpu_logical_id(dest), dest, irq_to_vector(irq));
 
-       raw_spin_unlock(&irq_desc[irq].lock);
+       raw_spin_unlock(&desc->lock);
  unlock_iosapic_lock:
        spin_unlock_irqrestore(&iosapic_lock, flags);
        return irq;
@@ -794,7 +787,6 @@ iosapic_unregister_intr (unsigned int gsi)
 {
        unsigned long flags;
        int irq, index;
-       struct irq_desc *idesc;
        u32 low32;
        unsigned long trigger, polarity;
        unsigned int dest;
@@ -824,7 +816,6 @@ iosapic_unregister_intr (unsigned int gsi)
        if (--rte->refcnt > 0)
                goto out;
 
-       idesc = irq_desc + irq;
        rte->refcnt = NO_REF_RTE;
 
        /* Mask the interrupt */
@@ -848,7 +839,7 @@ iosapic_unregister_intr (unsigned int gsi)
        if (iosapic_intr_info[irq].count == 0) {
 #ifdef CONFIG_SMP
                /* Clear affinity */
-               cpumask_setall(idesc->affinity);
+               cpumask_setall(irq_get_irq_data(irq)->affinity);
 #endif
                /* Clear the interrupt information */
                iosapic_intr_info[irq].dest = 0;
index 94ee9d067cbd31671ccc86a239a4dc653bad5c9a..ad69606613eb6d336a6f73af5f6c45eb2c936eb1 100644 (file)
@@ -53,47 +53,9 @@ atomic_t irq_err_count;
 /*
  * /proc/interrupts printing:
  */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int i = *(loff_t *) v, j;
-       struct irqaction * action;
-       unsigned long flags;
-
-       if (i == 0) {
-               char cpuname[16];
-               seq_printf(p, "     ");
-               for_each_online_cpu(j) {
-                       snprintf(cpuname, 10, "CPU%d", j);
-                       seq_printf(p, "%10s ", cpuname);
-               }
-               seq_putc(p, '\n');
-       }
-
-       if (i < NR_IRQS) {
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
-               if (!action)
-                       goto skip;
-               seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-               for_each_online_cpu(j) {
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-               }
-#endif
-               seq_printf(p, " %14s", irq_desc[i].chip->name);
-               seq_printf(p, "  %s", action->name);
-
-               for (action=action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-skip:
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS)
-               seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+       seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
        return 0;
 }
 
@@ -103,7 +65,7 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
        if (irq < NR_IRQS) {
-               cpumask_copy(irq_desc[irq].affinity,
+               cpumask_copy(irq_get_irq_data(irq)->affinity,
                             cpumask_of(cpu_logical_id(hwid)));
                irq_redir[irq] = (char) (redir & 0xff);
        }
@@ -130,13 +92,14 @@ unsigned int vectors_in_migration[NR_IRQS];
  */
 static void migrate_irqs(void)
 {
-       struct irq_desc *desc;
        int             irq, new_cpu;
 
        for (irq=0; irq < NR_IRQS; irq++) {
-               desc = irq_desc + irq;
+               struct irq_desc *desc = irq_to_desc(irq);
+               struct irq_data *data = irq_desc_get_irq_data(desc);
+               struct irq_chip *chip = irq_data_get_irq_chip(data);
 
-               if (desc->status == IRQ_DISABLED)
+               if (irqd_irq_disabled(data))
                        continue;
 
                /*
@@ -145,10 +108,10 @@ static void migrate_irqs(void)
                 * tell CPU not to respond to these local intr sources.
                 * such as ITV,CPEI,MCA etc.
                 */
-               if (desc->status == IRQ_PER_CPU)
+               if (irqd_is_per_cpu(data))
                        continue;
 
-               if (cpumask_any_and(irq_desc[irq].affinity, cpu_online_mask)
+               if (cpumask_any_and(data->affinity, cpu_online_mask)
                    >= nr_cpu_ids) {
                        /*
                         * Save it for phase 2 processing
@@ -160,16 +123,16 @@ static void migrate_irqs(void)
                        /*
                         * Al three are essential, currently WARN_ON.. maybe panic?
                         */
-                       if (desc->chip && desc->chip->disable &&
-                               desc->chip->enable && desc->chip->set_affinity) {
-                               desc->chip->disable(irq);
-                               desc->chip->set_affinity(irq,
-                                                        cpumask_of(new_cpu));
-                               desc->chip->enable(irq);
+                       if (chip && chip->irq_disable &&
+                               chip->irq_enable && chip->irq_set_affinity) {
+                               chip->irq_disable(data);
+                               chip->irq_set_affinity(data,
+                                                      cpumask_of(new_cpu), false);
+                               chip->irq_enable(data);
                        } else {
-                               WARN_ON((!(desc->chip) || !(desc->chip->disable) ||
-                                               !(desc->chip->enable) ||
-                                               !(desc->chip->set_affinity)));
+                               WARN_ON((!chip || !chip->irq_disable ||
+                                        !chip->irq_enable ||
+                                        !chip->irq_set_affinity));
                        }
                }
        }
index 38c07b8669011dad6e5637c4049d9d959e61bf5c..5b704740f1608b531b2fafa75ceba40b82b774f8 100644 (file)
@@ -343,7 +343,7 @@ static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id)
                if (irq < 0)
                        continue;
 
-               desc = irq_desc + irq;
+               desc = irq_to_desc(irq);
                cfg = irq_cfg + irq;
                raw_spin_lock(&desc->lock);
                if (!cfg->move_cleanup_count)
@@ -626,17 +626,15 @@ static struct irqaction tlb_irqaction = {
 void
 ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
 {
-       struct irq_desc *desc;
        unsigned int irq;
 
        irq = vec;
        BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
-       desc = irq_desc + irq;
-       desc->status |= IRQ_PER_CPU;
-       set_irq_chip(irq, &irq_type_ia64_lsapic);
+       irq_set_status_flags(irq, IRQ_PER_CPU);
+       irq_set_chip(irq, &irq_type_ia64_lsapic);
        if (action)
                setup_irq(irq, action);
-       set_irq_handler(irq, handle_percpu_irq);
+       irq_set_handler(irq, handle_percpu_irq);
 }
 
 void __init
index fc1549d4564da16ff067e5bf76c8536480137648..1b3a776e5161363ea82efcba50a1ecc7657b43f0 100644 (file)
 #include <linux/irq.h>
 
 static unsigned int
-lsapic_noop_startup (unsigned int irq)
+lsapic_noop_startup (struct irq_data *data)
 {
        return 0;
 }
 
 static void
-lsapic_noop (unsigned int irq)
+lsapic_noop (struct irq_data *data)
 {
        /* nothing to do... */
 }
 
-static int lsapic_retrigger(unsigned int irq)
+static int lsapic_retrigger(struct irq_data *data)
 {
-       ia64_resend_irq(irq);
+       ia64_resend_irq(data->irq);
 
        return 1;
 }
 
 struct irq_chip irq_type_ia64_lsapic = {
-       .name =         "LSAPIC",
-       .startup =      lsapic_noop_startup,
-       .shutdown =     lsapic_noop,
-       .enable =       lsapic_noop,
-       .disable =      lsapic_noop,
-       .ack =          lsapic_noop,
-       .end =          lsapic_noop,
-       .retrigger =    lsapic_retrigger,
+       .name =                 "LSAPIC",
+       .irq_startup =          lsapic_noop_startup,
+       .irq_shutdown =         lsapic_noop,
+       .irq_enable =           lsapic_noop,
+       .irq_disable =          lsapic_noop,
+       .irq_ack =              lsapic_noop,
+       .irq_retrigger =        lsapic_retrigger,
 };
index 80d50b83d4192b434ff1e7216f7c1dc3864ec1e7..84fb405eee87cfc4be613dd20c5636af157e2f9a 100644 (file)
@@ -2125,7 +2125,6 @@ ia64_mca_late_init(void)
        cpe_poll_timer.function = ia64_mca_cpe_poll;
 
        {
-               struct irq_desc *desc;
                unsigned int irq;
 
                if (cpe_vector >= 0) {
@@ -2133,8 +2132,7 @@ ia64_mca_late_init(void)
                        irq = local_vector_to_irq(cpe_vector);
                        if (irq > 0) {
                                cpe_poll_enabled = 0;
-                               desc = irq_desc + irq;
-                               desc->status |= IRQ_PER_CPU;
+                               irq_set_status_flags(irq, IRQ_PER_CPU);
                                setup_irq(irq, &mca_cpe_irqaction);
                                ia64_cpe_irq = irq;
                                ia64_mca_register_cpev(cpe_vector);
index 00b19a416eab5b1fc6db10bb366c37c048f8c7c2..009df5434a7a9a40132f172238ba810f3b2dc1af 100644 (file)
 static struct irq_chip ia64_msi_chip;
 
 #ifdef CONFIG_SMP
-static int ia64_set_msi_irq_affinity(unsigned int irq,
-                                     const cpumask_t *cpu_mask)
+static int ia64_set_msi_irq_affinity(struct irq_data *idata,
+                                    const cpumask_t *cpu_mask, bool force)
 {
        struct msi_msg msg;
        u32 addr, data;
        int cpu = first_cpu(*cpu_mask);
+       unsigned int irq = idata->irq;
 
        if (!cpu_online(cpu))
                return -1;
@@ -38,7 +39,7 @@ static int ia64_set_msi_irq_affinity(unsigned int irq,
        msg.data = data;
 
        write_msi_msg(irq, &msg);
-       cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+       cpumask_copy(idata->affinity, cpumask_of(cpu));
 
        return 0;
 }
@@ -55,7 +56,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
+       irq_set_msi_desc(irq, desc);
        cpus_and(mask, irq_to_domain(irq), cpu_online_map);
        dest_phys_id = cpu_physical_id(first_cpu(mask));
        vector = irq_to_vector(irq);
@@ -74,7 +75,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
                MSI_DATA_VECTOR(vector);
 
        write_msi_msg(irq, &msg);
-       set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
+       irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
 
        return 0;
 }
@@ -84,16 +85,16 @@ void ia64_teardown_msi_irq(unsigned int irq)
        destroy_irq(irq);
 }
 
-static void ia64_ack_msi_irq(unsigned int irq)
+static void ia64_ack_msi_irq(struct irq_data *data)
 {
-       irq_complete_move(irq);
-       move_native_irq(irq);
+       irq_complete_move(data->irq);
+       irq_move_irq(data);
        ia64_eoi();
 }
 
-static int ia64_msi_retrigger_irq(unsigned int irq)
+static int ia64_msi_retrigger_irq(struct irq_data *data)
 {
-       unsigned int vector = irq_to_vector(irq);
+       unsigned int vector = irq_to_vector(data->irq);
        ia64_resend_irq(vector);
 
        return 1;
@@ -103,14 +104,14 @@ static int ia64_msi_retrigger_irq(unsigned int irq)
  * Generic ops used on most IA64 platforms.
  */
 static struct irq_chip ia64_msi_chip = {
-       .name           = "PCI-MSI",
-       .irq_mask       = mask_msi_irq,
-       .irq_unmask     = unmask_msi_irq,
-       .ack            = ia64_ack_msi_irq,
+       .name                   = "PCI-MSI",
+       .irq_mask               = mask_msi_irq,
+       .irq_unmask             = unmask_msi_irq,
+       .irq_ack                = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
-       .set_affinity   = ia64_set_msi_irq_affinity,
+       .irq_set_affinity       = ia64_set_msi_irq_affinity,
 #endif
-       .retrigger      = ia64_msi_retrigger_irq,
+       .irq_retrigger          = ia64_msi_retrigger_irq,
 };
 
 
@@ -132,8 +133,10 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 #ifdef CONFIG_DMAR
 #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)
 {
+       unsigned int irq = data->irq;
        struct irq_cfg *cfg = irq_cfg + irq;
        struct msi_msg msg;
        int cpu = cpumask_first(mask);
@@ -152,7 +155,7 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
        msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
 
        dmar_msi_write(irq, &msg);
-       cpumask_copy(irq_desc[irq].affinity, mask);
+       cpumask_copy(data->affinity, mask);
 
        return 0;
 }
@@ -162,11 +165,11 @@ static struct irq_chip dmar_msi_type = {
        .name = "DMAR_MSI",
        .irq_unmask = dmar_msi_unmask,
        .irq_mask = dmar_msi_mask,
-       .ack = ia64_ack_msi_irq,
+       .irq_ack = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
-       .set_affinity = dmar_msi_set_affinity,
+       .irq_set_affinity = dmar_msi_set_affinity,
 #endif
-       .retrigger = ia64_msi_retrigger_irq,
+       .irq_retrigger = ia64_msi_retrigger_irq,
 };
 
 static int
@@ -203,8 +206,8 @@ int arch_setup_dmar_msi(unsigned int irq)
        if (ret < 0)
                return ret;
        dmar_msi_write(irq, &msg);
-       set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-               "edge");
+       irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+                                     "edge");
        return 0;
 }
 #endif /* CONFIG_DMAR */
index d003b502a432dfdefe22b16a1f8998e7ddea22cc..44f11ee411c001104db6b7dfa34eebd1f0c62e9a 100644 (file)
@@ -677,7 +677,7 @@ extern void fixup_irqs(void);
 int migrate_platform_irqs(unsigned int cpu)
 {
        int new_cpei_cpu;
-       struct irq_desc *desc = NULL;
+       struct irq_data *data = NULL;
        const struct cpumask *mask;
        int             retval = 0;
 
@@ -693,20 +693,20 @@ int migrate_platform_irqs(unsigned int cpu)
                        new_cpei_cpu = any_online_cpu(cpu_online_map);
                        mask = cpumask_of(new_cpei_cpu);
                        set_cpei_target_cpu(new_cpei_cpu);
-                       desc = irq_desc + ia64_cpe_irq;
+                       data = irq_get_irq_data(ia64_cpe_irq);
                        /*
                         * Switch for now, immediately, we need to do fake intr
                         * as other interrupts, but need to study CPEI behaviour with
                         * polling before making changes.
                         */
-                       if (desc) {
-                               desc->chip->disable(ia64_cpe_irq);
-                               desc->chip->set_affinity(ia64_cpe_irq, mask);
-                               desc->chip->enable(ia64_cpe_irq);
+                       if (data && data->chip) {
+                               data->chip->irq_disable(data);
+                               data->chip->irq_set_affinity(data, mask, false);
+                               data->chip->irq_enable(data);
                                printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu);
                        }
                }
-               if (!desc) {
+               if (!data) {
                        printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
                        retval = -EBUSY;
                }
index 13c15d968098d90b91beedb38855e331c73e616d..7f399f9d99c7960edf0b703c3c9d351d79a6f66a 100644 (file)
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_feature_sets.h>
 
-static void force_interrupt(int irq);
 static void register_intr_pda(struct sn_irq_info *sn_irq_info);
 static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
 
-int sn_force_interrupt_flag = 1;
 extern int sn_ioif_inited;
 struct list_head **sn_irq_lh;
 static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
@@ -78,62 +76,40 @@ u64 sn_intr_redirect(nasid_t local_nasid, int local_widget,
        return ret_stuff.status;
 }
 
-static unsigned int sn_startup_irq(unsigned int irq)
+static unsigned int sn_startup_irq(struct irq_data *data)
 {
        return 0;
 }
 
-static void sn_shutdown_irq(unsigned int irq)
+static void sn_shutdown_irq(struct irq_data *data)
 {
 }
 
 extern void ia64_mca_register_cpev(int);
 
-static void sn_disable_irq(unsigned int irq)
+static void sn_disable_irq(struct irq_data *data)
 {
-       if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
+       if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
                ia64_mca_register_cpev(0);
 }
 
-static void sn_enable_irq(unsigned int irq)
+static void sn_enable_irq(struct irq_data *data)
 {
-       if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
-               ia64_mca_register_cpev(irq);
+       if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
+               ia64_mca_register_cpev(data->irq);
 }
 
-static void sn_ack_irq(unsigned int irq)
+static void sn_ack_irq(struct irq_data *data)
 {
        u64 event_occurred, mask;
+       unsigned int irq = data->irq & 0xff;
 
-       irq = irq & 0xff;
        event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
        mask = event_occurred & SH_ALL_INT_MASK;
        HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
        __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-       move_native_irq(irq);
-}
-
-static void sn_end_irq(unsigned int irq)
-{
-       int ivec;
-       u64 event_occurred;
-
-       ivec = irq & 0xff;
-       if (ivec == SGI_UART_VECTOR) {
-               event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
-               /* If the UART bit is set here, we may have received an
-                * interrupt from the UART that the driver missed.  To
-                * make sure, we IPI ourselves to force us to look again.
-                */
-               if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
-                       platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR,
-                                         IA64_IPI_DM_INT, 0);
-               }
-       }
-       __clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
-       if (sn_force_interrupt_flag)
-               force_interrupt(irq);
+       irq_move_irq(data);
 }
 
 static void sn_irq_info_free(struct rcu_head *head);
@@ -228,9 +204,11 @@ finish_up:
        return new_irq_info;
 }
 
-static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
+static int sn_set_affinity_irq(struct irq_data *data,
+                              const struct cpumask *mask, bool force)
 {
        struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
+       unsigned int irq = data->irq;
        nasid_t nasid;
        int slice;
 
@@ -259,26 +237,25 @@ void sn_set_err_irq_affinity(unsigned int irq) { }
 #endif
 
 static void
-sn_mask_irq(unsigned int irq)
+sn_mask_irq(struct irq_data *data)
 {
 }
 
 static void
-sn_unmask_irq(unsigned int irq)
+sn_unmask_irq(struct irq_data *data)
 {
 }
 
 struct irq_chip irq_type_sn = {
-       .name           = "SN hub",
-       .startup        = sn_startup_irq,
-       .shutdown       = sn_shutdown_irq,
-       .enable         = sn_enable_irq,
-       .disable        = sn_disable_irq,
-       .ack            = sn_ack_irq,
-       .end            = sn_end_irq,
-       .mask           = sn_mask_irq,
-       .unmask         = sn_unmask_irq,
-       .set_affinity   = sn_set_affinity_irq
+       .name                   = "SN hub",
+       .irq_startup            = sn_startup_irq,
+       .irq_shutdown           = sn_shutdown_irq,
+       .irq_enable             = sn_enable_irq,
+       .irq_disable            = sn_disable_irq,
+       .irq_ack                = sn_ack_irq,
+       .irq_mask               = sn_mask_irq,
+       .irq_unmask             = sn_unmask_irq,
+       .irq_set_affinity       = sn_set_affinity_irq
 };
 
 ia64_vector sn_irq_to_vector(int irq)
@@ -296,15 +273,13 @@ unsigned int sn_local_vector_to_irq(u8 vector)
 void sn_irq_init(void)
 {
        int i;
-       struct irq_desc *base_desc = irq_desc;
 
        ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
        ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
 
        for (i = 0; i < NR_IRQS; i++) {
-               if (base_desc[i].chip == &no_irq_chip) {
-                       base_desc[i].chip = &irq_type_sn;
-               }
+               if (irq_get_chip(i) == &no_irq_chip)
+                       irq_set_chip(i, &irq_type_sn);
        }
 }
 
@@ -378,7 +353,6 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
        int cpu = nasid_slice_to_cpuid(nasid, slice);
 #ifdef CONFIG_SMP
        int cpuphys;
-       struct irq_desc *desc;
 #endif
 
        pci_dev_get(pci_dev);
@@ -395,12 +369,11 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
 #ifdef CONFIG_SMP
        cpuphys = cpu_physical_id(cpu);
        set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
-       desc = irq_to_desc(sn_irq_info->irq_irq);
        /*
         * Affinity was set by the PROM, prevent it from
         * being reset by the request_irq() path.
         */
-       desc->status |= IRQ_AFFINITY_SET;
+       irqd_mark_affinity_was_set(irq_get_irq_data(sn_irq_info->irq_irq));
 #endif
 }
 
@@ -439,25 +412,11 @@ sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
        pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
 
        /* Don't force an interrupt if the irq has been disabled */
-       if (!(irq_desc[sn_irq_info->irq_irq].status & IRQ_DISABLED) &&
+       if (!irqd_irq_disabled(sn_irq_info->irq_irq) &&
            pci_provider && pci_provider->force_interrupt)
                (*pci_provider->force_interrupt)(sn_irq_info);
 }
 
-static void force_interrupt(int irq)
-{
-       struct sn_irq_info *sn_irq_info;
-
-       if (!sn_ioif_inited)
-               return;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
-               sn_call_force_intr_provider(sn_irq_info);
-
-       rcu_read_unlock();
-}
-
 /*
  * Check for lost interrupts.  If the PIC int_status reg. says that
  * an interrupt has been sent, but not handled, and the interrupt
index a5e500f02853003604979a9b1c8c7fe1f25e0b4c..2b98b9e088def963ac47033c4717fa5ea4f24075 100644 (file)
@@ -144,16 +144,16 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
         */
        msg.data = 0x100 + irq;
 
-       set_irq_msi(irq, entry);
+       irq_set_msi_desc(irq, entry);
        write_msi_msg(irq, &msg);
-       set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
+       irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
        return 0;
 }
 
 #ifdef CONFIG_SMP
-static int sn_set_msi_irq_affinity(unsigned int irq,
-                                   const struct cpumask *cpu_mask)
+static int sn_set_msi_irq_affinity(struct irq_data *data,
+                                  const struct cpumask *cpu_mask, bool force)
 {
        struct msi_msg msg;
        int slice;
@@ -164,7 +164,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq,
        struct sn_irq_info *sn_irq_info;
        struct sn_irq_info *new_irq_info;
        struct sn_pcibus_provider *provider;
-       unsigned int cpu;
+       unsigned int cpu, irq = data->irq;
 
        cpu = cpumask_first(cpu_mask);
        sn_irq_info = sn_msi_info[irq].sn_irq_info;
@@ -206,33 +206,33 @@ static int sn_set_msi_irq_affinity(unsigned int irq,
        msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
        write_msi_msg(irq, &msg);
-       cpumask_copy(irq_desc[irq].affinity, cpu_mask);
+       cpumask_copy(data->affinity, cpu_mask);
 
        return 0;
 }
 #endif /* CONFIG_SMP */
 
-static void sn_ack_msi_irq(unsigned int irq)
+static void sn_ack_msi_irq(struct irq_data *data)
 {
-       move_native_irq(irq);
+       irq_move_irq(data);
        ia64_eoi();
 }
 
-static int sn_msi_retrigger_irq(unsigned int irq)
+static int sn_msi_retrigger_irq(struct irq_data *data)
 {
-       unsigned int vector = irq;
+       unsigned int vector = data->irq;
        ia64_resend_irq(vector);
 
        return 1;
 }
 
 static struct irq_chip sn_msi_chip = {
-       .name           = "PCI-MSI",
-       .irq_mask       = mask_msi_irq,
-       .irq_unmask     = unmask_msi_irq,
-       .ack            = sn_ack_msi_irq,
+       .name                   = "PCI-MSI",
+       .irq_mask               = mask_msi_irq,
+       .irq_unmask             = unmask_msi_irq,
+       .irq_ack                = sn_ack_msi_irq,
 #ifdef CONFIG_SMP
-       .set_affinity   = sn_set_msi_irq_affinity,
+       .irq_set_affinity       = sn_set_msi_irq_affinity,
 #endif
-       .retrigger      = sn_msi_retrigger_irq,
+       .irq_retrigger          = sn_msi_retrigger_irq,
 };
index a3fb7cf9ae1db1664217a7f7bd915b597ebeb483..108bb858acf2cee32801a99f137ea970bdb73487 100644 (file)
@@ -138,7 +138,6 @@ static void
 __xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
                        struct irqaction *action, int save)
 {
-       struct irq_desc *desc;
        int irq = 0;
 
        if (xen_slab_ready) {
@@ -223,8 +222,7 @@ __xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
                         * mark the interrupt for migrations and trigger it
                         * on cpu hotplug.
                         */
-                       desc = irq_desc + irq;
-                       desc->status |= IRQ_PER_CPU;
+                       irq_set_status_flags(irq, IRQ_PER_CPU);
                }
        }
 
index c7dd48f37beeb818b53c58ce053e60bc86dd015c..15dbc3e9d20c5594cdf96d9655898ef7ad378285 100644 (file)
@@ -44,7 +44,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (ap) {
                        seq_printf(p, "%3d: ", irq);
                        seq_printf(p, "%10u ", kstat_irqs(irq));
-                       seq_printf(p, "%14s  ", get_irq_desc_chip(desc)->name);
+                       seq_printf(p, "%14s  ", irq_desc_get_chip(desc)->name);
 
                        seq_printf(p, "%s", ap->name);
                        for (ap = ap->next; ap; ap = ap->next)
index 8f4b63e17366f5f0d3ca26fbe25f9c8c5a5fe0ac..f343bf7bf5b0a090d7423a07d6ec7c367aa156a7 100644 (file)
@@ -51,8 +51,8 @@ static int __init mcf_intc2_init(void)
 
        /* GPIO interrupt sources */
        for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
-               set_irq_chip(irq, &intc2_irq_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip(irq, &intc2_irq_gpio_chip);
+               irq_set_handler(irq, handle_edge_irq);
        }
 
        return 0;
index 969ff0a467c666f4796d7255b936be363eecf077..43e6e96f087f618005d60161be489c589dc956a2 100644 (file)
@@ -145,7 +145,7 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
  */
 static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
 {
-       get_irq_desc_chip(desc)->irq_ack(&desc->irq_data);
+       irq_desc_get_chip(desc)->irq_ack(&desc->irq_data);
        handle_simple_irq(irq, desc);
 }
 
@@ -171,16 +171,16 @@ void __init init_IRQ(void)
        writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               set_irq_chip(irq, &intc_irq_chip);
+               irq_set_chip(irq, &intc_irq_chip);
                edge = 0;
                if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX))
                        edge = intc_irqmap[irq - MCFINT_VECBASE].ack;
                if (edge) {
-                       set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
-                       set_irq_handler(irq, intc_external_irq);
+                       irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+                       irq_set_handler(irq, intc_external_irq);
                } else {
-                       set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-                       set_irq_handler(irq, handle_level_irq);
+                       irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+                       irq_set_handler(irq, handle_level_irq);
                }
        }
 }
index e5631831a200a795d6bf7867348b00a619cbe027..a90288cf7446c3ae562e6be4da70215a31745b26 100644 (file)
@@ -179,8 +179,8 @@ void __init init_IRQ(void)
        IMR = ~0;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               set_irq_chip(i, &intc_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip(i, &intc_irq_chip);
+               irq_set_handler(i, handle_level_irq);
        }
 }
 
index 8de3feb568c605dff2eeed7506b36411a7608af7..4af0f4e30f74e86a01eba693a957414147524ba4 100644 (file)
@@ -132,8 +132,8 @@ void init_IRQ(void)
        pquicc->intr_cimr = 0x00000000;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               set_irq_chip(i, &intc_irq_chip);
-               set_irq_handler(i, handle_level_irq);
+               irq_set_chip(i, &intc_irq_chip);
+               irq_set_handler(i, handle_level_irq);
        }
 }
 
index 2cbfbf035db9b47b70fd06b1df17057855765a00..74b55cfbc3cb2cde7a12f8a51572bf6f7b37b2bf 100644 (file)
@@ -164,7 +164,7 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
        }
 
        if (tb)
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_handler(irq, handle_edge_irq);
 
        irq -= EINT0;
        pa = __raw_readw(MCFEPORT_EPPAR);
@@ -204,11 +204,11 @@ void __init init_IRQ(void)
 
        for (irq = MCFINT_VECBASE; (irq < MCFINT_VECBASE + NR_VECS); irq++) {
                if ((irq >= EINT1) && (irq <=EINT7))
-                       set_irq_chip(irq, &intc_irq_chip_edge_port);
+                       irq_set_chip(irq, &intc_irq_chip_edge_port);
                else
-                       set_irq_chip(irq, &intc_irq_chip);
-               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-               set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip(irq, &intc_irq_chip);
+               irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_handler(irq, handle_level_irq);
        }
 }
 
index e642b24ab729f598f0c85470420509a6a4fcac33..d6a4d9d53e42df8ebc13866d6b27049176e2c8b4 100644 (file)
@@ -141,7 +141,7 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
        }
 
        if (tb)
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_handler(irq, handle_edge_irq);
 
        ebit = irq2ebit(irq) * 2;
        pa = __raw_readw(MCFEPORT_EPPAR);
@@ -181,11 +181,11 @@ void __init init_IRQ(void)
        eirq = MCFINT_VECBASE + 64 + (MCFINTC1_ICR0 ? 64 : 0);
        for (irq = MCFINT_VECBASE; (irq < eirq); irq++) {
                if ((irq >= EINT1) && (irq <= EINT7))
-                       set_irq_chip(irq, &intc_irq_chip_edge_port);
+                       irq_set_chip(irq, &intc_irq_chip_edge_port);
                else
-                       set_irq_chip(irq, &intc_irq_chip);
-               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-               set_irq_handler(irq, handle_level_irq);
+                       irq_set_chip(irq, &intc_irq_chip);
+               irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_handler(irq, handle_level_irq);
        }
 }
 
index d648081a63f691e5e77385dda29f2cc19c053870..c28a6ed6cb234b4e3d3f20e419d915e5920817f8 100644 (file)
@@ -143,9 +143,9 @@ void __init init_IRQ(void)
        mcf_maskimr(0xffffffff);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               set_irq_chip(irq, &intc_irq_chip);
-               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip(irq, &intc_irq_chip);
+               irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_handler(irq, handle_level_irq);
        }
 }
 
index 5f0cf0e32653e30931b5039134ca339287f5c586..c49c326e7af1a43815bf1df36d36616ddbbf0c44 100644 (file)
@@ -18,6 +18,7 @@ config MICROBLAZE
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
 
 config SWAP
        def_bool n
index e4661285118e5e96cd52df9ec669e0338e63a5f9..5ba7e162833b61f653671c9d7b2861ea524c69f6 100644 (file)
@@ -50,7 +50,7 @@ static void intc_enable_or_unmask(struct irq_data *d)
         * ack function since the handle_level_irq function
         * acks the irq before calling the interrupt handler
         */
-       if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
+       if (irqd_is_level_type(d))
                out_be32(INTC_BASE + IAR, mask);
 }
 
@@ -157,11 +157,11 @@ void __init init_IRQ(void)
 
        for (i = 0; i < nr_irq; ++i) {
                if (intr_type & (0x00000001 << i)) {
-                       set_irq_chip_and_handler_name(i, &intc_dev,
+                       irq_set_chip_and_handler_name(i, &intc_dev,
                                handle_edge_irq, intc_dev.name);
                        irq_clear_status_flags(i, IRQ_LEVEL);
                } else {
-                       set_irq_chip_and_handler_name(i, &intc_dev,
+                       irq_set_chip_and_handler_name(i, &intc_dev,
                                handle_level_irq, intc_dev.name);
                        irq_set_status_flags(i, IRQ_LEVEL);
                }
index 09882241372964493cf68ac8df664bb7d824277c..ce7ac8435d5c947adf9920c7a28f78efe0cfa3e3 100644 (file)
@@ -47,48 +47,6 @@ next_irq:
        trace_hardirqs_on();
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-       int i = *(loff_t *) v, j;
-       struct irq_desc *desc;
-       struct irqaction *action;
-       unsigned long flags;
-
-       if (i == 0) {
-               seq_printf(p, "         ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "CPU%-8d", j);
-               seq_putc(p, '\n');
-       }
-
-       if (i < nr_irq) {
-               desc = irq_to_desc(i);
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               action = desc->action;
-               if (!action)
-                       goto skip;
-               seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-               seq_printf(p, " %8s", desc->status &
-                                       IRQ_LEVEL ? "level" : "edge");
-               seq_printf(p, " %8s", desc->irq_data.chip->name);
-               seq_printf(p, "  %s", action->name);
-
-               for (action = action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-skip:
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       }
-       return 0;
-}
-
 /* MS: There is no any advance mapping mechanism. We are using simple 32bit
   intc without any cascades or any connection that's why mapping is 1:1 */
 unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
index 1e01a1253631f11a548ddd817a5a99f8f19b130f..53599067d2f94f37dfbec3d0dc02d5e4950a5aca 100644 (file)
@@ -237,7 +237,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
 
                virq = irq_create_mapping(NULL, line);
                if (virq != NO_IRQ)
-                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
        } else {
                pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
                         oirq.size, oirq.specifier[0], oirq.specifier[1],
index f91c43a7d5dc1ecf6d9a220704c9c0852d8c43b2..596ad00e7f05f7bd0c6dc41b663ed2694fdc263d 100644 (file)
@@ -142,8 +142,8 @@ void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq)
        bcsr_csc_base = csc_start;
 
        for (irq = csc_start; irq <= csc_end; irq++)
-               set_irq_chip_and_handler_name(irq, &bcsr_irq_type,
-                       handle_level_irq, "level");
+               irq_set_chip_and_handler_name(irq, &bcsr_irq_type,
+                                             handle_level_irq, "level");
 
-       set_irq_chained_handler(hook_irq, bcsr_csc_handler);
+       irq_set_chained_handler(hook_irq, bcsr_csc_handler);
 }
index 8876195475539e0ea881c2b80b8bf6a21ff2d2d9..4a8980027ecf83538229e71ea67fe3c27c2a4517 100644 (file)
@@ -63,20 +63,19 @@ void __init board_setup(void)
 static int __init db1200_arch_init(void)
 {
        /* GPIO7 is low-level triggered CPLD cascade */
-       set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
        bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
 
        /* insert/eject pairs: one of both is always screaming.  To avoid
         * issues they must not be automatically enabled when initially
         * requested.
         */
-       irq_to_desc(DB1200_SD0_INSERT_INT)->status |= IRQ_NOAUTOEN;
-       irq_to_desc(DB1200_SD0_EJECT_INT)->status |= IRQ_NOAUTOEN;
-       irq_to_desc(DB1200_PC0_INSERT_INT)->status |= IRQ_NOAUTOEN;
-       irq_to_desc(DB1200_PC0_EJECT_INT)->status |= IRQ_NOAUTOEN;
-       irq_to_desc(DB1200_PC1_INSERT_INT)->status |= IRQ_NOAUTOEN;
-       irq_to_desc(DB1200_PC1_EJECT_INT)->status |= IRQ_NOAUTOEN;
-
+       irq_set_status_flags(DB1200_SD0_INSERT_INT, IRQ_NOAUTOEN);
+       irq_set_status_flags(DB1200_SD0_EJECT_INT, IRQ_NOAUTOEN);
+       irq_set_status_flags(DB1200_PC0_INSERT_INT, IRQ_NOAUTOEN);
+       irq_set_status_flags(DB1200_PC0_EJECT_INT, IRQ_NOAUTOEN);
+       irq_set_status_flags(DB1200_PC1_INSERT_INT, IRQ_NOAUTOEN);
+       irq_set_status_flags(DB1200_PC1_EJECT_INT, IRQ_NOAUTOEN);
        return 0;
 }
 arch_initcall(db1200_arch_init);
index 9e45971343edcd3a751f470bbefdce595e1e0adf..05f120ff90f9c244312a57f9a2619a627e9e28ab 100644 (file)
@@ -215,35 +215,35 @@ void __init board_setup(void)
 static int __init db1x00_init_irq(void)
 {
 #if defined(CONFIG_MIPS_MIRAGE)
-       set_irq_type(AU1500_GPIO7_INT, IRQF_TRIGGER_RISING); /* TS pendown */
+       irq_set_irq_type(AU1500_GPIO7_INT, IRQF_TRIGGER_RISING); /* TS pendown */
 #elif defined(CONFIG_MIPS_DB1550)
-       set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);  /* CD0# */
-       set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);  /* CD1# */
-       set_irq_type(AU1550_GPIO3_INT, IRQF_TRIGGER_LOW);  /* CARD0# */
-       set_irq_type(AU1550_GPIO5_INT, IRQF_TRIGGER_LOW);  /* CARD1# */
-       set_irq_type(AU1550_GPIO21_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-       set_irq_type(AU1550_GPIO22_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+       irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);  /* CD0# */
+       irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);  /* CD1# */
+       irq_set_irq_type(AU1550_GPIO3_INT, IRQF_TRIGGER_LOW);  /* CARD0# */
+       irq_set_irq_type(AU1550_GPIO5_INT, IRQF_TRIGGER_LOW);  /* CARD1# */
+       irq_set_irq_type(AU1550_GPIO21_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+       irq_set_irq_type(AU1550_GPIO22_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1500)
-       set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-       set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-       set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-       set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-       set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-       set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+       irq_set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+       irq_set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+       irq_set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+       irq_set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+       irq_set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+       irq_set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1100)
-       set_irq_type(AU1100_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-       set_irq_type(AU1100_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-       set_irq_type(AU1100_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-       set_irq_type(AU1100_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-       set_irq_type(AU1100_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-       set_irq_type(AU1100_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+       irq_set_irq_type(AU1100_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+       irq_set_irq_type(AU1100_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+       irq_set_irq_type(AU1100_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+       irq_set_irq_type(AU1100_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+       irq_set_irq_type(AU1100_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+       irq_set_irq_type(AU1100_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1000)
-       set_irq_type(AU1000_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-       set_irq_type(AU1000_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-       set_irq_type(AU1000_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-       set_irq_type(AU1000_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-       set_irq_type(AU1000_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-       set_irq_type(AU1000_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+       irq_set_irq_type(AU1000_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+       irq_set_irq_type(AU1000_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+       irq_set_irq_type(AU1000_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+       irq_set_irq_type(AU1000_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+       irq_set_irq_type(AU1000_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+       irq_set_irq_type(AU1000_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #endif
        return 0;
 }
index f6540ec47a64412d982aee01f9e92acd161d363c..2d85c4b5be096f530266f6cfc620886aa1c8b4c6 100644 (file)
@@ -197,7 +197,7 @@ void __init board_setup(void)
 
 static int __init pb1000_init_irq(void)
 {
-       set_irq_type(AU1000_GPIO15_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1000_GPIO15_INT, IRQF_TRIGGER_LOW);
        return 0;
 }
 arch_initcall(pb1000_init_irq);
index 90dda5f3ecc50fad0344b3aadfaa00b2473d037e..d108fd573aaf0eb75d7a2d25abb9a62cbb38eba2 100644 (file)
@@ -117,10 +117,10 @@ void __init board_setup(void)
 
 static int __init pb1100_init_irq(void)
 {
-       set_irq_type(AU1100_GPIO9_INT,  IRQF_TRIGGER_LOW); /* PCCD# */
-       set_irq_type(AU1100_GPIO10_INT, IRQF_TRIGGER_LOW); /* PCSTSCHG# */
-       set_irq_type(AU1100_GPIO11_INT, IRQF_TRIGGER_LOW); /* PCCard# */
-       set_irq_type(AU1100_GPIO13_INT, IRQF_TRIGGER_LOW); /* DC_IRQ# */
+       irq_set_irq_type(AU1100_GPIO9_INT, IRQF_TRIGGER_LOW); /* PCCD# */
+       irq_set_irq_type(AU1100_GPIO10_INT, IRQF_TRIGGER_LOW); /* PCSTSCHG# */
+       irq_set_irq_type(AU1100_GPIO11_INT, IRQF_TRIGGER_LOW); /* PCCard# */
+       irq_set_irq_type(AU1100_GPIO13_INT, IRQF_TRIGGER_LOW); /* DC_IRQ# */
 
        return 0;
 }
index 8b4466f2d44a3de00a28e19a87158d3d9b5974f4..6d06b07c238111b774c2a7e2a15a68dfcbbc4b6f 100644 (file)
@@ -142,7 +142,7 @@ static int __init pb1200_init_irq(void)
                panic("Game over.  Your score is 0.");
        }
 
-       set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
        bcsr_init_irq(PB1200_INT_BEGIN, PB1200_INT_END, AU1200_GPIO7_INT);
 
        return 0;
index 9cd9dfa698e75a9d89d36074f466483f1d512ae7..83f46215eb0c3b7b652a2abea4f7a41dda0c7a15 100644 (file)
@@ -134,14 +134,14 @@ void __init board_setup(void)
 
 static int __init pb1500_init_irq(void)
 {
-       set_irq_type(AU1500_GPIO9_INT, IRQF_TRIGGER_LOW);   /* CD0# */
-       set_irq_type(AU1500_GPIO10_INT, IRQF_TRIGGER_LOW);  /* CARD0 */
-       set_irq_type(AU1500_GPIO11_INT, IRQF_TRIGGER_LOW);  /* STSCHG0# */
-       set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-       set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO9_INT, IRQF_TRIGGER_LOW);   /* CD0# */
+       irq_set_irq_type(AU1500_GPIO10_INT, IRQF_TRIGGER_LOW);  /* CARD0 */
+       irq_set_irq_type(AU1500_GPIO11_INT, IRQF_TRIGGER_LOW);  /* STSCHG0# */
+       irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
 
        return 0;
 }
index 9d7d6edafa8dc87cf1877e86a7348790c7312ad0..b790213848bd3f31086fbe940a4d1456b70c1617 100644 (file)
@@ -73,9 +73,9 @@ void __init board_setup(void)
 
 static int __init pb1550_init_irq(void)
 {
-       set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1550_GPIO201_205_INT, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1550_GPIO201_205_INT, IRQF_TRIGGER_HIGH);
 
        /* enable both PCMCIA card irqs in the shared line */
        alchemy_gpio2_enable_int(201);
index 40b84b99119133e2bce153532c9db5fcca2d1700..cf436ab679ae81f6abdb2ba422bc75617c3d5fed 100644 (file)
@@ -123,11 +123,11 @@ mtx1_pci_idsel(unsigned int devsel, int assert)
 
 static int __init mtx1_init_irq(void)
 {
-       set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-       set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
 
        return 0;
 }
index 80c521e5290d630b0c0ec69023aaa6c9d4a00bff..febfb0fb0896dcd979ca52bc40ecf0fcb3bfcbe2 100644 (file)
@@ -85,19 +85,19 @@ void __init board_setup(void)
 
 static int __init xxs1500_init_irq(void)
 {
-       set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-       set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO207_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO207_INT, IRQF_TRIGGER_LOW);
 
-       set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW);
-       set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* CF irq */
-       set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* CF irq */
+       irq_set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW);
 
        return 0;
 }
index a6484b60642fc071465a0fe614220bc1808c654c..03db3daadbd8f95524783ae7c802e9524e9fb346 100644 (file)
@@ -119,11 +119,11 @@ static void __init ar7_irq_init(int base)
        for (i = 0; i < 40; i++) {
                writel(i, REG(CHNL_OFFSET(i)));
                /* Primary IRQ's */
-               set_irq_chip_and_handler(base + i, &ar7_irq_type,
+               irq_set_chip_and_handler(base + i, &ar7_irq_type,
                                         handle_level_irq);
                /* Secondary IRQ's */
                if (i < 32)
-                       set_irq_chip_and_handler(base + i + 40,
+                       irq_set_chip_and_handler(base + i + 40,
                                                 &ar7_sec_irq_type,
                                                 handle_level_irq);
        }
index 7c02bc948a313077aac8fd354a0b2302c8f57169..ac610d5fe3bab415ef649872072bacce58718c19 100644 (file)
@@ -124,11 +124,11 @@ static void __init ath79_misc_irq_init(void)
 
        for (i = ATH79_MISC_IRQ_BASE;
             i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
-               set_irq_chip_and_handler(i, &ath79_misc_irq_chip,
+               irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
                                         handle_level_irq);
        }
 
-       set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
+       irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
 }
 
 asmlinkage void plat_irq_dispatch(void)
index 1691531aa34d405d166b946a8739637cf312ec7d..cea6021cb8d7a3172976bd1a8c7b378b41331c93 100644 (file)
@@ -230,11 +230,11 @@ void __init arch_init_irq(void)
 
        mips_cpu_irq_init();
        for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
-               set_irq_chip_and_handler(i, &bcm63xx_internal_irq_chip,
+               irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
                                         handle_level_irq);
 
        for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i)
-               set_irq_chip_and_handler(i, &bcm63xx_external_irq_chip,
+               irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
                                         handle_edge_irq);
 
        setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action);
index ce7500cdf5b709de9755d94f6b07b41eeca17359..ffd4ae660f792461015be0f1d7ceb2dec7184dea 100644 (file)
@@ -3,10 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks
+ * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
  */
-#include <linux/irq.h>
+
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/percpu.h>
+#include <linux/irq.h>
 #include <linux/smp.h>
 
 #include <asm/octeon/octeon.h>
 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock);
 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock);
 
+static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror);
+static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror);
+
+static __read_mostly u8 octeon_irq_ciu_to_irq[8][64];
+
+union octeon_ciu_chip_data {
+       void *p;
+       unsigned long l;
+       struct {
+               unsigned int line:6;
+               unsigned int bit:6;
+       } s;
+};
+
+struct octeon_core_chip_data {
+       struct mutex core_irq_mutex;
+       bool current_en;
+       bool desired_en;
+       u8 bit;
+};
+
+#define MIPS_CORE_IRQ_LINES 8
+
+static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
+
+static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
+                                             struct irq_chip *chip,
+                                             irq_flow_handler_t handler)
+{
+       union octeon_ciu_chip_data cd;
+
+       irq_set_chip_and_handler(irq, chip, handler);
+
+       cd.l = 0;
+       cd.s.line = line;
+       cd.s.bit = bit;
+
+       irq_set_chip_data(irq, cd.p);
+       octeon_irq_ciu_to_irq[line][bit] = irq;
+}
+
 static int octeon_coreid_for_cpu(int cpu)
 {
 #ifdef CONFIG_SMP
@@ -23,9 +67,20 @@ static int octeon_coreid_for_cpu(int cpu)
 #endif
 }
 
-static void octeon_irq_core_ack(unsigned int irq)
+static int octeon_cpu_for_coreid(int coreid)
+{
+#ifdef CONFIG_SMP
+       return cpu_number_map(coreid);
+#else
+       return smp_processor_id();
+#endif
+}
+
+static void octeon_irq_core_ack(struct irq_data *data)
 {
-       unsigned int bit = irq - OCTEON_IRQ_SW0;
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+       unsigned int bit = cd->bit;
+
        /*
         * We don't need to disable IRQs to make these atomic since
         * they are already disabled earlier in the low level
@@ -37,131 +92,121 @@ static void octeon_irq_core_ack(unsigned int irq)
                clear_c0_cause(0x100 << bit);
 }
 
-static void octeon_irq_core_eoi(unsigned int irq)
+static void octeon_irq_core_eoi(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned int bit = irq - OCTEON_IRQ_SW0;
-       /*
-        * If an IRQ is being processed while we are disabling it the
-        * handler will attempt to unmask the interrupt after it has
-        * been disabled.
-        */
-       if ((unlikely(desc->status & IRQ_DISABLED)))
-               return;
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
        /*
         * We don't need to disable IRQs to make these atomic since
         * they are already disabled earlier in the low level
         * interrupt code.
         */
-       set_c0_status(0x100 << bit);
+       set_c0_status(0x100 << cd->bit);
 }
 
-static void octeon_irq_core_enable(unsigned int irq)
+static void octeon_irq_core_set_enable_local(void *arg)
 {
-       unsigned long flags;
-       unsigned int bit = irq - OCTEON_IRQ_SW0;
+       struct irq_data *data = arg;
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+       unsigned int mask = 0x100 << cd->bit;
 
        /*
-        * We need to disable interrupts to make sure our updates are
-        * atomic.
+        * Interrupts are already disabled, so these are atomic.
         */
-       local_irq_save(flags);
-       set_c0_status(0x100 << bit);
-       local_irq_restore(flags);
+       if (cd->desired_en)
+               set_c0_status(mask);
+       else
+               clear_c0_status(mask);
+
 }
 
-static void octeon_irq_core_disable_local(unsigned int irq)
+static void octeon_irq_core_disable(struct irq_data *data)
 {
-       unsigned long flags;
-       unsigned int bit = irq - OCTEON_IRQ_SW0;
-       /*
-        * We need to disable interrupts to make sure our updates are
-        * atomic.
-        */
-       local_irq_save(flags);
-       clear_c0_status(0x100 << bit);
-       local_irq_restore(flags);
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+       cd->desired_en = false;
 }
 
-static void octeon_irq_core_disable(unsigned int irq)
+static void octeon_irq_core_enable(struct irq_data *data)
 {
-#ifdef CONFIG_SMP
-       on_each_cpu((void (*)(void *)) octeon_irq_core_disable_local,
-                   (void *) (long) irq, 1);
-#else
-       octeon_irq_core_disable_local(irq);
-#endif
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+       cd->desired_en = true;
 }
 
-static struct irq_chip octeon_irq_chip_core = {
-       .name = "Core",
-       .enable = octeon_irq_core_enable,
-       .disable = octeon_irq_core_disable,
-       .ack = octeon_irq_core_ack,
-       .eoi = octeon_irq_core_eoi,
-};
+static void octeon_irq_core_bus_lock(struct irq_data *data)
+{
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
 
+       mutex_lock(&cd->core_irq_mutex);
+}
 
-static void octeon_irq_ciu0_ack(unsigned int irq)
+static void octeon_irq_core_bus_sync_unlock(struct irq_data *data)
 {
-       switch (irq) {
-       case OCTEON_IRQ_GMX_DRP0:
-       case OCTEON_IRQ_GMX_DRP1:
-       case OCTEON_IRQ_IPD_DRP:
-       case OCTEON_IRQ_KEY_ZERO:
-       case OCTEON_IRQ_TIMER0:
-       case OCTEON_IRQ_TIMER1:
-       case OCTEON_IRQ_TIMER2:
-       case OCTEON_IRQ_TIMER3:
-       {
-               int index = cvmx_get_core_num() * 2;
-               u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-               /*
-                * CIU timer type interrupts must be acknoleged by
-                * writing a '1' bit to their sum0 bit.
-                */
-               cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
-               break;
-       }
-       default:
-               break;
+       struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+       if (cd->desired_en != cd->current_en) {
+               on_each_cpu(octeon_irq_core_set_enable_local, data, 1);
+
+               cd->current_en = cd->desired_en;
        }
 
-       /*
-        * In order to avoid any locking accessing the CIU, we
-        * acknowledge CIU interrupts by disabling all of them.  This
-        * way we can use a per core register and avoid any out of
-        * core locking requirements.  This has the side affect that
-        * CIU interrupts can't be processed recursively.
-        *
-        * We don't need to disable IRQs to make these atomic since
-        * they are already disabled earlier in the low level
-        * interrupt code.
-        */
-       clear_c0_status(0x100 << 2);
+       mutex_unlock(&cd->core_irq_mutex);
 }
 
-static void octeon_irq_ciu0_eoi(unsigned int irq)
+static struct irq_chip octeon_irq_chip_core = {
+       .name = "Core",
+       .irq_enable = octeon_irq_core_enable,
+       .irq_disable = octeon_irq_core_disable,
+       .irq_ack = octeon_irq_core_ack,
+       .irq_eoi = octeon_irq_core_eoi,
+       .irq_bus_lock = octeon_irq_core_bus_lock,
+       .irq_bus_sync_unlock = octeon_irq_core_bus_sync_unlock,
+
+       .irq_cpu_online = octeon_irq_core_eoi,
+       .irq_cpu_offline = octeon_irq_core_ack,
+       .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static void __init octeon_irq_init_core(void)
 {
-       /*
-        * Enable all CIU interrupts again.  We don't need to disable
-        * IRQs to make these atomic since they are already disabled
-        * earlier in the low level interrupt code.
-        */
-       set_c0_status(0x100 << 2);
+       int i;
+       int irq;
+       struct octeon_core_chip_data *cd;
+
+       for (i = 0; i < MIPS_CORE_IRQ_LINES; i++) {
+               cd = &octeon_irq_core_chip_data[i];
+               cd->current_en = false;
+               cd->desired_en = false;
+               cd->bit = i;
+               mutex_init(&cd->core_irq_mutex);
+
+               irq = OCTEON_IRQ_SW0 + i;
+               switch (irq) {
+               case OCTEON_IRQ_TIMER:
+               case OCTEON_IRQ_SW0:
+               case OCTEON_IRQ_SW1:
+               case OCTEON_IRQ_5:
+               case OCTEON_IRQ_PERF:
+                       irq_set_chip_data(irq, cd);
+                       irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
+                                                handle_percpu_irq);
+                       break;
+               default:
+                       break;
+               }
+       }
 }
 
-static int next_coreid_for_irq(struct irq_desc *desc)
+static int next_cpu_for_irq(struct irq_data *data)
 {
 
 #ifdef CONFIG_SMP
-       int coreid;
-       int weight = cpumask_weight(desc->affinity);
+       int cpu;
+       int weight = cpumask_weight(data->affinity);
 
        if (weight > 1) {
-               int cpu = smp_processor_id();
+               cpu = smp_processor_id();
                for (;;) {
-                       cpu = cpumask_next(cpu, desc->affinity);
+                       cpu = cpumask_next(cpu, data->affinity);
                        if (cpu >= nr_cpu_ids) {
                                cpu = -1;
                                continue;
@@ -169,83 +214,175 @@ static int next_coreid_for_irq(struct irq_desc *desc)
                                break;
                        }
                }
-               coreid = octeon_coreid_for_cpu(cpu);
        } else if (weight == 1) {
-               coreid = octeon_coreid_for_cpu(cpumask_first(desc->affinity));
+               cpu = cpumask_first(data->affinity);
        } else {
-               coreid = cvmx_get_core_num();
+               cpu = smp_processor_id();
        }
-       return coreid;
+       return cpu;
 #else
-       return cvmx_get_core_num();
+       return smp_processor_id();
 #endif
 }
 
-static void octeon_irq_ciu0_enable(unsigned int irq)
+static void octeon_irq_ciu_enable(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       int coreid = next_coreid_for_irq(desc);
+       int cpu = next_cpu_for_irq(data);
+       int coreid = octeon_coreid_for_cpu(cpu);
+       unsigned long *pen;
        unsigned long flags;
-       uint64_t en0;
-       int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
 
-       raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-       en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       en0 |= 1ull << bit;
-       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-       cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+               set_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+               set_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       }
 }
 
-static void octeon_irq_ciu0_enable_mbox(unsigned int irq)
+static void octeon_irq_ciu_enable_local(struct irq_data *data)
 {
-       int coreid = cvmx_get_core_num();
+       unsigned long *pen;
+       unsigned long flags;
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
+
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
+               set_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
+               set_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       }
+}
+
+static void octeon_irq_ciu_disable_local(struct irq_data *data)
+{
+       unsigned long *pen;
        unsigned long flags;
-       uint64_t en0;
-       int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
 
-       raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-       en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       en0 |= 1ull << bit;
-       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-       cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
+               clear_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
+               clear_bit(cd.s.bit, pen);
+               cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       }
 }
 
-static void octeon_irq_ciu0_disable(unsigned int irq)
+static void octeon_irq_ciu_disable_all(struct irq_data *data)
 {
-       int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
        unsigned long flags;
-       uint64_t en0;
+       unsigned long *pen;
        int cpu;
-       raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-       for_each_online_cpu(cpu) {
-               int coreid = octeon_coreid_for_cpu(cpu);
-               en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-               en0 &= ~(1ull << bit);
-               cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+       union octeon_ciu_chip_data cd;
+
+       wmb(); /* Make sure flag changes arrive before register updates. */
+
+       cd.p = irq_data_get_irq_chip_data(data);
+
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+                       clear_bit(cd.s.bit, pen);
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+               }
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+                       clear_bit(cd.s.bit, pen);
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+               }
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       }
+}
+
+static void octeon_irq_ciu_enable_all(struct irq_data *data)
+{
+       unsigned long flags;
+       unsigned long *pen;
+       int cpu;
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
+
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+                       set_bit(cd.s.bit, pen);
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+               }
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+                       set_bit(cd.s.bit, pen);
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+               }
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
        }
-       /*
-        * We need to do a read after the last update to make sure all
-        * of them are done.
-        */
-       cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
 }
 
 /*
  * Enable the irq on the next core in the affinity set for chips that
  * have the EN*_W1{S,C} registers.
  */
-static void octeon_irq_ciu0_enable_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_v2(struct irq_data *data)
 {
-       int index;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-       struct irq_desc *desc = irq_to_desc(irq);
+       u64 mask;
+       int cpu = next_cpu_for_irq(data);
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
+       mask = 1ull << (cd.s.bit);
 
-       if ((desc->status & IRQ_DISABLED) == 0) {
-               index = next_coreid_for_irq(desc) * 2;
+       /*
+        * Called under the desc lock, so these should never get out
+        * of sync.
+        */
+       if (cd.s.line == 0) {
+               int index = octeon_coreid_for_cpu(cpu) * 2;
+               set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
                cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+       } else {
+               int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+               set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
        }
 }
 
@@ -253,83 +390,155 @@ static void octeon_irq_ciu0_enable_v2(unsigned int irq)
  * Enable the irq on the current CPU for chips that
  * have the EN*_W1{S,C} registers.
  */
-static void octeon_irq_ciu0_enable_mbox_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_local_v2(struct irq_data *data)
+{
+       u64 mask;
+       union octeon_ciu_chip_data cd;
+
+       cd.p = irq_data_get_irq_chip_data(data);
+       mask = 1ull << (cd.s.bit);
+
+       if (cd.s.line == 0) {
+               int index = cvmx_get_core_num() * 2;
+               set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
+               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+       } else {
+               int index = cvmx_get_core_num() * 2 + 1;
+               set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
+               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+       }
+}
+
+static void octeon_irq_ciu_disable_local_v2(struct irq_data *data)
 {
-       int index;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+       u64 mask;
+       union octeon_ciu_chip_data cd;
 
-       index = cvmx_get_core_num() * 2;
-       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+       cd.p = irq_data_get_irq_chip_data(data);
+       mask = 1ull << (cd.s.bit);
+
+       if (cd.s.line == 0) {
+               int index = cvmx_get_core_num() * 2;
+               clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
+               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+       } else {
+               int index = cvmx_get_core_num() * 2 + 1;
+               clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
+               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+       }
 }
 
 /*
- * Disable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
+ * Write to the W1C bit in CVMX_CIU_INTX_SUM0 to clear the irq.
  */
-static void octeon_irq_ciu0_ack_v2(unsigned int irq)
-{
-       int index = cvmx_get_core_num() * 2;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-
-       switch (irq) {
-       case OCTEON_IRQ_GMX_DRP0:
-       case OCTEON_IRQ_GMX_DRP1:
-       case OCTEON_IRQ_IPD_DRP:
-       case OCTEON_IRQ_KEY_ZERO:
-       case OCTEON_IRQ_TIMER0:
-       case OCTEON_IRQ_TIMER1:
-       case OCTEON_IRQ_TIMER2:
-       case OCTEON_IRQ_TIMER3:
-               /*
-                * CIU timer type interrupts must be acknoleged by
-                * writing a '1' bit to their sum0 bit.
-                */
+static void octeon_irq_ciu_ack(struct irq_data *data)
+{
+       u64 mask;
+       union octeon_ciu_chip_data cd;
+
+       cd.p = data->chip_data;
+       mask = 1ull << (cd.s.bit);
+
+       if (cd.s.line == 0) {
+               int index = cvmx_get_core_num() * 2;
                cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
-               break;
-       default:
-               break;
+       } else {
+               cvmx_write_csr(CVMX_CIU_INT_SUM1, mask);
        }
-
-       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
 }
 
 /*
- * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
  * registers.
  */
-static void octeon_irq_ciu0_eoi_mbox_v2(unsigned int irq)
+static void octeon_irq_ciu_disable_all_v2(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       int index = cvmx_get_core_num() * 2;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+       int cpu;
+       u64 mask;
+       union octeon_ciu_chip_data cd;
 
-       if (likely((desc->status & IRQ_DISABLED) == 0))
-               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+       wmb(); /* Make sure flag changes arrive before register updates. */
+
+       cd.p = data->chip_data;
+       mask = 1ull << (cd.s.bit);
+
+       if (cd.s.line == 0) {
+               for_each_online_cpu(cpu) {
+                       int index = octeon_coreid_for_cpu(cpu) * 2;
+                       clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+               }
+       } else {
+               for_each_online_cpu(cpu) {
+                       int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+                       clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+               }
+       }
 }
 
 /*
- * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * Enable the irq on the all cores for chips that have the EN*_W1{S,C}
  * registers.
  */
-static void octeon_irq_ciu0_disable_all_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
 {
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-       int index;
        int cpu;
-       for_each_online_cpu(cpu) {
-               index = octeon_coreid_for_cpu(cpu) * 2;
-               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+       u64 mask;
+       union octeon_ciu_chip_data cd;
+
+       cd.p = data->chip_data;
+       mask = 1ull << (cd.s.bit);
+
+       if (cd.s.line == 0) {
+               for_each_online_cpu(cpu) {
+                       int index = octeon_coreid_for_cpu(cpu) * 2;
+                       set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+               }
+       } else {
+               for_each_online_cpu(cpu) {
+                       int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+                       set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+               }
        }
 }
 
 #ifdef CONFIG_SMP
-static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+
+static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
+{
+       int cpu = smp_processor_id();
+       cpumask_t new_affinity;
+
+       if (!cpumask_test_cpu(cpu, data->affinity))
+               return;
+
+       if (cpumask_weight(data->affinity) > 1) {
+               /*
+                * It has multi CPU affinity, just remove this CPU
+                * from the affinity set.
+                */
+               cpumask_copy(&new_affinity, data->affinity);
+               cpumask_clear_cpu(cpu, &new_affinity);
+       } else {
+               /* Otherwise, put it on lowest numbered online CPU. */
+               cpumask_clear(&new_affinity);
+               cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
+       }
+       __irq_set_affinity_locked(data, &new_affinity);
+}
+
+static int octeon_irq_ciu_set_affinity(struct irq_data *data,
+                                      const struct cpumask *dest, bool force)
 {
        int cpu;
-       struct irq_desc *desc = irq_to_desc(irq);
-       int enable_one = (desc->status & IRQ_DISABLED) == 0;
+       bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
        unsigned long flags;
-       int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
+       union octeon_ciu_chip_data cd;
+
+       cd.p = data->chip_data;
 
        /*
         * For non-v2 CIU, we will allow only single CPU affinity.
@@ -339,26 +548,40 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *
        if (cpumask_weight(dest) != 1)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-       for_each_online_cpu(cpu) {
-               int coreid = octeon_coreid_for_cpu(cpu);
-               uint64_t en0 =
-                       cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-               if (cpumask_test_cpu(cpu, dest) && enable_one) {
-                       enable_one = 0;
-                       en0 |= 1ull << bit;
-               } else {
-                       en0 &= ~(1ull << bit);
+       if (!enable_one)
+               return 0;
+
+       if (cd.s.line == 0) {
+               raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+
+                       if (cpumask_test_cpu(cpu, dest) && enable_one) {
+                               enable_one = false;
+                               set_bit(cd.s.bit, pen);
+                       } else {
+                               clear_bit(cd.s.bit, pen);
+                       }
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
                }
-               cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+       } else {
+               raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+               for_each_online_cpu(cpu) {
+                       int coreid = octeon_coreid_for_cpu(cpu);
+                       unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+
+                       if (cpumask_test_cpu(cpu, dest) && enable_one) {
+                               enable_one = false;
+                               set_bit(cd.s.bit, pen);
+                       } else {
+                               clear_bit(cd.s.bit, pen);
+                       }
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+               }
+               raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
        }
-       /*
-        * We need to do a read after the last update to make sure all
-        * of them are done.
-        */
-       cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
-
        return 0;
 }
 
@@ -366,103 +589,149 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *
  * Set affinity for the irq for chips that have the EN*_W1{S,C}
  * registers.
  */
-static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq,
-                                          const struct cpumask *dest)
+static int octeon_irq_ciu_set_affinity_v2(struct irq_data *data,
+                                         const struct cpumask *dest,
+                                         bool force)
 {
        int cpu;
-       int index;
-       struct irq_desc *desc = irq_to_desc(irq);
-       int enable_one = (desc->status & IRQ_DISABLED) == 0;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-
-       for_each_online_cpu(cpu) {
-               index = octeon_coreid_for_cpu(cpu) * 2;
-               if (cpumask_test_cpu(cpu, dest) && enable_one) {
-                       enable_one = 0;
-                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
-               } else {
-                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+       bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
+       u64 mask;
+       union octeon_ciu_chip_data cd;
+
+       if (!enable_one)
+               return 0;
+
+       cd.p = data->chip_data;
+       mask = 1ull << cd.s.bit;
+
+       if (cd.s.line == 0) {
+               for_each_online_cpu(cpu) {
+                       unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+                       int index = octeon_coreid_for_cpu(cpu) * 2;
+                       if (cpumask_test_cpu(cpu, dest) && enable_one) {
+                               enable_one = false;
+                               set_bit(cd.s.bit, pen);
+                               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+                       } else {
+                               clear_bit(cd.s.bit, pen);
+                               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+                       }
+               }
+       } else {
+               for_each_online_cpu(cpu) {
+                       unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+                       int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+                       if (cpumask_test_cpu(cpu, dest) && enable_one) {
+                               enable_one = false;
+                               set_bit(cd.s.bit, pen);
+                               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+                       } else {
+                               clear_bit(cd.s.bit, pen);
+                               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+                       }
                }
        }
        return 0;
 }
 #endif
 
+/*
+ * The v1 CIU code already masks things, so supply a dummy version to
+ * the core chip code.
+ */
+static void octeon_irq_dummy_mask(struct irq_data *data)
+{
+}
+
 /*
  * Newer octeon chips have support for lockless CIU operation.
  */
-static struct irq_chip octeon_irq_chip_ciu0_v2 = {
-       .name = "CIU0",
-       .enable = octeon_irq_ciu0_enable_v2,
-       .disable = octeon_irq_ciu0_disable_all_v2,
-       .eoi = octeon_irq_ciu0_enable_v2,
+static struct irq_chip octeon_irq_chip_ciu_v2 = {
+       .name = "CIU",
+       .irq_enable = octeon_irq_ciu_enable_v2,
+       .irq_disable = octeon_irq_ciu_disable_all_v2,
+       .irq_mask = octeon_irq_ciu_disable_local_v2,
+       .irq_unmask = octeon_irq_ciu_enable_v2,
 #ifdef CONFIG_SMP
-       .set_affinity = octeon_irq_ciu0_set_affinity_v2,
+       .irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
 };
 
-static struct irq_chip octeon_irq_chip_ciu0 = {
-       .name = "CIU0",
-       .enable = octeon_irq_ciu0_enable,
-       .disable = octeon_irq_ciu0_disable,
-       .eoi = octeon_irq_ciu0_eoi,
+static struct irq_chip octeon_irq_chip_ciu_edge_v2 = {
+       .name = "CIU-E",
+       .irq_enable = octeon_irq_ciu_enable_v2,
+       .irq_disable = octeon_irq_ciu_disable_all_v2,
+       .irq_ack = octeon_irq_ciu_ack,
+       .irq_mask = octeon_irq_ciu_disable_local_v2,
+       .irq_unmask = octeon_irq_ciu_enable_v2,
 #ifdef CONFIG_SMP
-       .set_affinity = octeon_irq_ciu0_set_affinity,
+       .irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
 };
 
-/* The mbox versions don't do any affinity or round-robin. */
-static struct irq_chip octeon_irq_chip_ciu0_mbox_v2 = {
-       .name = "CIU0-M",
-       .enable = octeon_irq_ciu0_enable_mbox_v2,
-       .disable = octeon_irq_ciu0_disable,
-       .eoi = octeon_irq_ciu0_eoi_mbox_v2,
+static struct irq_chip octeon_irq_chip_ciu = {
+       .name = "CIU",
+       .irq_enable = octeon_irq_ciu_enable,
+       .irq_disable = octeon_irq_ciu_disable_all,
+       .irq_mask = octeon_irq_dummy_mask,
+#ifdef CONFIG_SMP
+       .irq_set_affinity = octeon_irq_ciu_set_affinity,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
 };
 
-static struct irq_chip octeon_irq_chip_ciu0_mbox = {
-       .name = "CIU0-M",
-       .enable = octeon_irq_ciu0_enable_mbox,
-       .disable = octeon_irq_ciu0_disable,
-       .eoi = octeon_irq_ciu0_eoi,
+static struct irq_chip octeon_irq_chip_ciu_edge = {
+       .name = "CIU-E",
+       .irq_enable = octeon_irq_ciu_enable,
+       .irq_disable = octeon_irq_ciu_disable_all,
+       .irq_mask = octeon_irq_dummy_mask,
+       .irq_ack = octeon_irq_ciu_ack,
+#ifdef CONFIG_SMP
+       .irq_set_affinity = octeon_irq_ciu_set_affinity,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
 };
 
-static void octeon_irq_ciu1_ack(unsigned int irq)
-{
-       /*
-        * In order to avoid any locking accessing the CIU, we
-        * acknowledge CIU interrupts by disabling all of them.  This
-        * way we can use a per core register and avoid any out of
-        * core locking requirements.  This has the side affect that
-        * CIU interrupts can't be processed recursively.  We don't
-        * need to disable IRQs to make these atomic since they are
-        * already disabled earlier in the low level interrupt code.
-        */
-       clear_c0_status(0x100 << 3);
-}
+/* The mbox versions don't do any affinity or round-robin. */
+static struct irq_chip octeon_irq_chip_ciu_mbox_v2 = {
+       .name = "CIU-M",
+       .irq_enable = octeon_irq_ciu_enable_all_v2,
+       .irq_disable = octeon_irq_ciu_disable_all_v2,
+       .irq_ack = octeon_irq_ciu_disable_local_v2,
+       .irq_eoi = octeon_irq_ciu_enable_local_v2,
+
+       .irq_cpu_online = octeon_irq_ciu_enable_local_v2,
+       .irq_cpu_offline = octeon_irq_ciu_disable_local_v2,
+       .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
 
-static void octeon_irq_ciu1_eoi(unsigned int irq)
-{
-       /*
-        * Enable all CIU interrupts again.  We don't need to disable
-        * IRQs to make these atomic since they are already disabled
-        * earlier in the low level interrupt code.
-        */
-       set_c0_status(0x100 << 3);
-}
+static struct irq_chip octeon_irq_chip_ciu_mbox = {
+       .name = "CIU-M",
+       .irq_enable = octeon_irq_ciu_enable_all,
+       .irq_disable = octeon_irq_ciu_disable_all,
+
+       .irq_cpu_online = octeon_irq_ciu_enable_local,
+       .irq_cpu_offline = octeon_irq_ciu_disable_local,
+       .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
 
-static void octeon_irq_ciu1_enable(unsigned int irq)
+/*
+ * Watchdog interrupts are special.  They are associated with a single
+ * core, so we hardwire the affinity to that core.
+ */
+static void octeon_irq_ciu_wd_enable(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       int coreid = next_coreid_for_irq(desc);
        unsigned long flags;
-       uint64_t en1;
-       int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
+       unsigned long *pen;
+       int coreid = data->irq - OCTEON_IRQ_WDOG0;      /* Bit 0-63 of EN1 */
+       int cpu = octeon_cpu_for_coreid(coreid);
 
        raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-       en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-       en1 |= 1ull << bit;
-       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-       cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+       pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+       set_bit(coreid, pen);
+       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
        raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
 }
 
@@ -470,286 +739,281 @@ static void octeon_irq_ciu1_enable(unsigned int irq)
  * Watchdog interrupts are special.  They are associated with a single
  * core, so we hardwire the affinity to that core.
  */
-static void octeon_irq_ciu1_wd_enable(unsigned int irq)
+static void octeon_irq_ciu1_wd_enable_v2(struct irq_data *data)
 {
-       unsigned long flags;
-       uint64_t en1;
-       int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
-       int coreid = bit;
+       int coreid = data->irq - OCTEON_IRQ_WDOG0;
+       int cpu = octeon_cpu_for_coreid(coreid);
 
-       raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-       en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-       en1 |= 1ull << bit;
-       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-       cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       set_bit(coreid, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(coreid * 2 + 1), 1ull << coreid);
 }
 
-static void octeon_irq_ciu1_disable(unsigned int irq)
+
+static struct irq_chip octeon_irq_chip_ciu_wd_v2 = {
+       .name = "CIU-W",
+       .irq_enable = octeon_irq_ciu1_wd_enable_v2,
+       .irq_disable = octeon_irq_ciu_disable_all_v2,
+       .irq_mask = octeon_irq_ciu_disable_local_v2,
+       .irq_unmask = octeon_irq_ciu_enable_local_v2,
+};
+
+static struct irq_chip octeon_irq_chip_ciu_wd = {
+       .name = "CIU-W",
+       .irq_enable = octeon_irq_ciu_wd_enable,
+       .irq_disable = octeon_irq_ciu_disable_all,
+       .irq_mask = octeon_irq_dummy_mask,
+};
+
+static void octeon_irq_ip2_v1(void)
 {
-       int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
-       unsigned long flags;
-       uint64_t en1;
-       int cpu;
-       raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-       for_each_online_cpu(cpu) {
-               int coreid = octeon_coreid_for_cpu(cpu);
-               en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-               en1 &= ~(1ull << bit);
-               cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+       const unsigned long core_id = cvmx_get_core_num();
+       u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
+
+       ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
+       clear_c0_status(STATUSF_IP2);
+       if (likely(ciu_sum)) {
+               int bit = fls64(ciu_sum) - 1;
+               int irq = octeon_irq_ciu_to_irq[0][bit];
+               if (likely(irq))
+                       do_IRQ(irq);
+               else
+                       spurious_interrupt();
+       } else {
+               spurious_interrupt();
        }
-       /*
-        * We need to do a read after the last update to make sure all
-        * of them are done.
-        */
-       cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+       set_c0_status(STATUSF_IP2);
 }
 
-/*
- * Enable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_enable_v2(unsigned int irq)
+static void octeon_irq_ip2_v2(void)
 {
-       int index;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       if ((desc->status & IRQ_DISABLED) == 0) {
-               index = next_coreid_for_irq(desc) * 2 + 1;
-               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+       const unsigned long core_id = cvmx_get_core_num();
+       u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
+
+       ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
+       if (likely(ciu_sum)) {
+               int bit = fls64(ciu_sum) - 1;
+               int irq = octeon_irq_ciu_to_irq[0][bit];
+               if (likely(irq))
+                       do_IRQ(irq);
+               else
+                       spurious_interrupt();
+       } else {
+               spurious_interrupt();
        }
 }
-
-/*
- * Watchdog interrupts are special.  They are associated with a single
- * core, so we hardwire the affinity to that core.
- */
-static void octeon_irq_ciu1_wd_enable_v2(unsigned int irq)
+static void octeon_irq_ip3_v1(void)
 {
-       int index;
-       int coreid = irq - OCTEON_IRQ_WDOG0;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       if ((desc->status & IRQ_DISABLED) == 0) {
-               index = coreid * 2 + 1;
-               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+       u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
+
+       ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
+       clear_c0_status(STATUSF_IP3);
+       if (likely(ciu_sum)) {
+               int bit = fls64(ciu_sum) - 1;
+               int irq = octeon_irq_ciu_to_irq[1][bit];
+               if (likely(irq))
+                       do_IRQ(irq);
+               else
+                       spurious_interrupt();
+       } else {
+               spurious_interrupt();
        }
+       set_c0_status(STATUSF_IP3);
 }
 
-/*
- * Disable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_ack_v2(unsigned int irq)
+static void octeon_irq_ip3_v2(void)
 {
-       int index = cvmx_get_core_num() * 2 + 1;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-
-       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+       u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
+
+       ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
+       if (likely(ciu_sum)) {
+               int bit = fls64(ciu_sum) - 1;
+               int irq = octeon_irq_ciu_to_irq[1][bit];
+               if (likely(irq))
+                       do_IRQ(irq);
+               else
+                       spurious_interrupt();
+       } else {
+               spurious_interrupt();
+       }
 }
 
-/*
- * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_disable_all_v2(unsigned int irq)
+static void octeon_irq_ip4_mask(void)
 {
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-       int index;
-       int cpu;
-       for_each_online_cpu(cpu) {
-               index = octeon_coreid_for_cpu(cpu) * 2 + 1;
-               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
-       }
+       clear_c0_status(STATUSF_IP4);
+       spurious_interrupt();
 }
 
-#ifdef CONFIG_SMP
-static int octeon_irq_ciu1_set_affinity(unsigned int irq,
-                                       const struct cpumask *dest)
-{
-       int cpu;
-       struct irq_desc *desc = irq_to_desc(irq);
-       int enable_one = (desc->status & IRQ_DISABLED) == 0;
-       unsigned long flags;
-       int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
+static void (*octeon_irq_ip2)(void);
+static void (*octeon_irq_ip3)(void);
+static void (*octeon_irq_ip4)(void);
 
-       /*
-        * For non-v2 CIU, we will allow only single CPU affinity.
-        * This removes the need to do locking in the .ack/.eoi
-        * functions.
-        */
-       if (cpumask_weight(dest) != 1)
-               return -EINVAL;
+void __cpuinitdata (*octeon_irq_setup_secondary)(void);
 
-       raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-       for_each_online_cpu(cpu) {
-               int coreid = octeon_coreid_for_cpu(cpu);
-               uint64_t en1 =
-                       cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-               if (cpumask_test_cpu(cpu, dest) && enable_one) {
-                       enable_one = 0;
-                       en1 |= 1ull << bit;
-               } else {
-                       en1 &= ~(1ull << bit);
-               }
-               cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-       }
+static void __cpuinit octeon_irq_percpu_enable(void)
+{
+       irq_cpu_online();
+}
+
+static void __cpuinit octeon_irq_init_ciu_percpu(void)
+{
+       int coreid = cvmx_get_core_num();
        /*
-        * We need to do a read after the last update to make sure all
-        * of them are done.
+        * Disable All CIU Interrupts. The ones we need will be
+        * enabled later.  Read the SUM register so we know the write
+        * completed.
         */
-       cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
-       raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
-
-       return 0;
+       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
+       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
+       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
+       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
+       cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
 }
 
-/*
- * Set affinity for the irq for chips that have the EN*_W1{S,C}
- * registers.
- */
-static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq,
-                                          const struct cpumask *dest)
+static void __cpuinit octeon_irq_setup_secondary_ciu(void)
 {
-       int cpu;
-       int index;
-       struct irq_desc *desc = irq_to_desc(irq);
-       int enable_one = (desc->status & IRQ_DISABLED) == 0;
-       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-       for_each_online_cpu(cpu) {
-               index = octeon_coreid_for_cpu(cpu) * 2 + 1;
-               if (cpumask_test_cpu(cpu, dest) && enable_one) {
-                       enable_one = 0;
-                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
-               } else {
-                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
-               }
-       }
-       return 0;
-}
-#endif
 
-/*
- * Newer octeon chips have support for lockless CIU operation.
- */
-static struct irq_chip octeon_irq_chip_ciu1_v2 = {
-       .name = "CIU1",
-       .enable = octeon_irq_ciu1_enable_v2,
-       .disable = octeon_irq_ciu1_disable_all_v2,
-       .eoi = octeon_irq_ciu1_enable_v2,
-#ifdef CONFIG_SMP
-       .set_affinity = octeon_irq_ciu1_set_affinity_v2,
-#endif
-};
+       __get_cpu_var(octeon_irq_ciu0_en_mirror) = 0;
+       __get_cpu_var(octeon_irq_ciu1_en_mirror) = 0;
 
-static struct irq_chip octeon_irq_chip_ciu1 = {
-       .name = "CIU1",
-       .enable = octeon_irq_ciu1_enable,
-       .disable = octeon_irq_ciu1_disable,
-       .eoi = octeon_irq_ciu1_eoi,
-#ifdef CONFIG_SMP
-       .set_affinity = octeon_irq_ciu1_set_affinity,
-#endif
-};
+       octeon_irq_init_ciu_percpu();
+       octeon_irq_percpu_enable();
 
-static struct irq_chip octeon_irq_chip_ciu1_wd_v2 = {
-       .name = "CIU1-W",
-       .enable = octeon_irq_ciu1_wd_enable_v2,
-       .disable = octeon_irq_ciu1_disable_all_v2,
-       .eoi = octeon_irq_ciu1_wd_enable_v2,
-};
+       /* Enable the CIU lines */
+       set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+       clear_c0_status(STATUSF_IP4);
+}
 
-static struct irq_chip octeon_irq_chip_ciu1_wd = {
-       .name = "CIU1-W",
-       .enable = octeon_irq_ciu1_wd_enable,
-       .disable = octeon_irq_ciu1_disable,
-       .eoi = octeon_irq_ciu1_eoi,
-};
+static void __init octeon_irq_init_ciu(void)
+{
+       unsigned int i;
+       struct irq_chip *chip;
+       struct irq_chip *chip_edge;
+       struct irq_chip *chip_mbox;
+       struct irq_chip *chip_wd;
+
+       octeon_irq_init_ciu_percpu();
+       octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
 
-static void (*octeon_ciu0_ack)(unsigned int);
-static void (*octeon_ciu1_ack)(unsigned int);
+       if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
+           OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
+           OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) ||
+           OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+               octeon_irq_ip2 = octeon_irq_ip2_v2;
+               octeon_irq_ip3 = octeon_irq_ip3_v2;
+               chip = &octeon_irq_chip_ciu_v2;
+               chip_edge = &octeon_irq_chip_ciu_edge_v2;
+               chip_mbox = &octeon_irq_chip_ciu_mbox_v2;
+               chip_wd = &octeon_irq_chip_ciu_wd_v2;
+       } else {
+               octeon_irq_ip2 = octeon_irq_ip2_v1;
+               octeon_irq_ip3 = octeon_irq_ip3_v1;
+               chip = &octeon_irq_chip_ciu;
+               chip_edge = &octeon_irq_chip_ciu_edge;
+               chip_mbox = &octeon_irq_chip_ciu_mbox;
+               chip_wd = &octeon_irq_chip_ciu_wd;
+       }
+       octeon_irq_ip4 = octeon_irq_ip4_mask;
+
+       /* Mips internal */
+       octeon_irq_init_core();
+
+       /* CIU_0 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
+       for (i = 0; i < 16; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
+
+       for (i = 0; i < 4; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
+       for (i = 0; i < 4; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
+
+       for (i = 0; i < 2; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
+
+       for (i = 0; i < 4; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
+
+       /* CIU_1 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
+
+       /* Enable the CIU lines */
+       set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+       clear_c0_status(STATUSF_IP4);
+}
 
 void __init arch_init_irq(void)
 {
-       unsigned int irq;
-       struct irq_chip *chip0;
-       struct irq_chip *chip0_mbox;
-       struct irq_chip *chip1;
-       struct irq_chip *chip1_wd;
-
 #ifdef CONFIG_SMP
        /* Set the default affinity to the boot cpu. */
        cpumask_clear(irq_default_affinity);
        cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
 #endif
-
-       if (NR_IRQS < OCTEON_IRQ_LAST)
-               pr_err("octeon_irq_init: NR_IRQS is set too low\n");
-
-       if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
-           OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
-           OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
-               octeon_ciu0_ack = octeon_irq_ciu0_ack_v2;
-               octeon_ciu1_ack = octeon_irq_ciu1_ack_v2;
-               chip0 = &octeon_irq_chip_ciu0_v2;
-               chip0_mbox = &octeon_irq_chip_ciu0_mbox_v2;
-               chip1 = &octeon_irq_chip_ciu1_v2;
-               chip1_wd = &octeon_irq_chip_ciu1_wd_v2;
-       } else {
-               octeon_ciu0_ack = octeon_irq_ciu0_ack;
-               octeon_ciu1_ack = octeon_irq_ciu1_ack;
-               chip0 = &octeon_irq_chip_ciu0;
-               chip0_mbox = &octeon_irq_chip_ciu0_mbox;
-               chip1 = &octeon_irq_chip_ciu1;
-               chip1_wd = &octeon_irq_chip_ciu1_wd;
-       }
-
-       /* 0 - 15 reserved for i8259 master and slave controller. */
-
-       /* 17 - 23 Mips internal */
-       for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) {
-               set_irq_chip_and_handler(irq, &octeon_irq_chip_core,
-                                        handle_percpu_irq);
-       }
-
-       /* 24 - 87 CIU_INT_SUM0 */
-       for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
-               switch (irq) {
-               case OCTEON_IRQ_MBOX0:
-               case OCTEON_IRQ_MBOX1:
-                       set_irq_chip_and_handler(irq, chip0_mbox, handle_percpu_irq);
-                       break;
-               default:
-                       set_irq_chip_and_handler(irq, chip0, handle_fasteoi_irq);
-                       break;
-               }
-       }
-
-       /* 88 - 151 CIU_INT_SUM1 */
-       for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_WDOG15; irq++)
-               set_irq_chip_and_handler(irq, chip1_wd, handle_fasteoi_irq);
-
-       for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED151; irq++)
-               set_irq_chip_and_handler(irq, chip1, handle_fasteoi_irq);
-
-       set_c0_status(0x300 << 2);
+       octeon_irq_init_ciu();
 }
 
 asmlinkage void plat_irq_dispatch(void)
 {
-       const unsigned long core_id = cvmx_get_core_num();
-       const uint64_t ciu_sum0_address = CVMX_CIU_INTX_SUM0(core_id * 2);
-       const uint64_t ciu_en0_address = CVMX_CIU_INTX_EN0(core_id * 2);
-       const uint64_t ciu_sum1_address = CVMX_CIU_INT_SUM1;
-       const uint64_t ciu_en1_address = CVMX_CIU_INTX_EN1(core_id * 2 + 1);
        unsigned long cop0_cause;
        unsigned long cop0_status;
-       uint64_t ciu_en;
-       uint64_t ciu_sum;
-       unsigned int irq;
 
        while (1) {
                cop0_cause = read_c0_cause();
@@ -757,33 +1021,16 @@ asmlinkage void plat_irq_dispatch(void)
                cop0_cause &= cop0_status;
                cop0_cause &= ST0_IM;
 
-               if (unlikely(cop0_cause & STATUSF_IP2)) {
-                       ciu_sum = cvmx_read_csr(ciu_sum0_address);
-                       ciu_en = cvmx_read_csr(ciu_en0_address);
-                       ciu_sum &= ciu_en;
-                       if (likely(ciu_sum)) {
-                               irq = fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1;
-                               octeon_ciu0_ack(irq);
-                               do_IRQ(irq);
-                       } else {
-                               spurious_interrupt();
-                       }
-               } else if (unlikely(cop0_cause & STATUSF_IP3)) {
-                       ciu_sum = cvmx_read_csr(ciu_sum1_address);
-                       ciu_en = cvmx_read_csr(ciu_en1_address);
-                       ciu_sum &= ciu_en;
-                       if (likely(ciu_sum)) {
-                               irq = fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1;
-                               octeon_ciu1_ack(irq);
-                               do_IRQ(irq);
-                       } else {
-                               spurious_interrupt();
-                       }
-               } else if (likely(cop0_cause)) {
+               if (unlikely(cop0_cause & STATUSF_IP2))
+                       octeon_irq_ip2();
+               else if (unlikely(cop0_cause & STATUSF_IP3))
+                       octeon_irq_ip3();
+               else if (unlikely(cop0_cause & STATUSF_IP4))
+                       octeon_irq_ip4();
+               else if (likely(cop0_cause))
                        do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE);
-               } else {
+               else
                        break;
-               }
        }
 }
 
@@ -791,83 +1038,7 @@ asmlinkage void plat_irq_dispatch(void)
 
 void fixup_irqs(void)
 {
-       int irq;
-       struct irq_desc *desc;
-       cpumask_t new_affinity;
-       unsigned long flags;
-       int do_set_affinity;
-       int cpu;
-
-       cpu = smp_processor_id();
-
-       for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++)
-               octeon_irq_core_disable_local(irq);
-
-       for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) {
-               desc = irq_to_desc(irq);
-               switch (irq) {
-               case OCTEON_IRQ_MBOX0:
-               case OCTEON_IRQ_MBOX1:
-                       /* The eoi function will disable them on this CPU. */
-                       desc->chip->eoi(irq);
-                       break;
-               case OCTEON_IRQ_WDOG0:
-               case OCTEON_IRQ_WDOG1:
-               case OCTEON_IRQ_WDOG2:
-               case OCTEON_IRQ_WDOG3:
-               case OCTEON_IRQ_WDOG4:
-               case OCTEON_IRQ_WDOG5:
-               case OCTEON_IRQ_WDOG6:
-               case OCTEON_IRQ_WDOG7:
-               case OCTEON_IRQ_WDOG8:
-               case OCTEON_IRQ_WDOG9:
-               case OCTEON_IRQ_WDOG10:
-               case OCTEON_IRQ_WDOG11:
-               case OCTEON_IRQ_WDOG12:
-               case OCTEON_IRQ_WDOG13:
-               case OCTEON_IRQ_WDOG14:
-               case OCTEON_IRQ_WDOG15:
-                       /*
-                        * These have special per CPU semantics and
-                        * are handled in the watchdog driver.
-                        */
-                       break;
-               default:
-                       raw_spin_lock_irqsave(&desc->lock, flags);
-                       /*
-                        * If this irq has an action, it is in use and
-                        * must be migrated if it has affinity to this
-                        * cpu.
-                        */
-                       if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) {
-                               if (cpumask_weight(desc->affinity) > 1) {
-                                       /*
-                                        * It has multi CPU affinity,
-                                        * just remove this CPU from
-                                        * the affinity set.
-                                        */
-                                       cpumask_copy(&new_affinity, desc->affinity);
-                                       cpumask_clear_cpu(cpu, &new_affinity);
-                               } else {
-                                       /*
-                                        * Otherwise, put it on lowest
-                                        * numbered online CPU.
-                                        */
-                                       cpumask_clear(&new_affinity);
-                                       cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
-                               }
-                               do_set_affinity = 1;
-                       } else {
-                               do_set_affinity = 0;
-                       }
-                       raw_spin_unlock_irqrestore(&desc->lock, flags);
-
-                       if (do_set_affinity)
-                               irq_set_affinity(irq, &new_affinity);
-
-                       break;
-               }
-       }
+       irq_cpu_offline();
 }
 
 #endif /* CONFIG_HOTPLUG_CPU */
index b0c3686c96dd614abe8dac92a3a84a04818c2e7c..8b139bf4a1b5d9aaf24653eb97cc373a31cd4fb9 100644 (file)
@@ -420,7 +420,6 @@ void octeon_user_io_init(void)
 void __init prom_init(void)
 {
        struct cvmx_sysinfo *sysinfo;
-       const int coreid = cvmx_get_core_num();
        int i;
        int argc;
 #ifdef CONFIG_CAVIUM_RESERVE32
@@ -537,17 +536,6 @@ void __init prom_init(void)
 
        octeon_uart = octeon_get_boot_uart();
 
-       /*
-        * Disable All CIU Interrupts. The ones we need will be
-        * enabled later.  Read the SUM register so we know the write
-        * completed.
-        */
-       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
-       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
-       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
-       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
-       cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
-
 #ifdef CONFIG_SMP
        octeon_write_lcd("LinuxSMP");
 #else
index 391cefe556b3d025872b36b1ad38eb1ae850234c..ba78b21cc8d0496b7be966550c9612d3a547ad4e 100644 (file)
@@ -171,41 +171,19 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle)
  * After we've done initial boot, this function is called to allow the
  * board code to clean up state, if needed
  */
-static void octeon_init_secondary(void)
+static void __cpuinit octeon_init_secondary(void)
 {
-       const int coreid = cvmx_get_core_num();
-       union cvmx_ciu_intx_sum0 interrupt_enable;
        unsigned int sr;
 
-#ifdef CONFIG_HOTPLUG_CPU
-       struct linux_app_boot_info *labi;
-
-       labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
-       if (labi->labi_signature != LABI_SIGNATURE)
-               panic("The bootloader version on this board is incorrect.");
-#endif
-
        sr = set_c0_status(ST0_BEV);
        write_c0_ebase((u32)ebase);
        write_c0_status(sr);
 
        octeon_check_cpu_bist();
        octeon_init_cvmcount();
-       /*
-       pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid);
-       */
-       /* Enable Mailbox interrupts to this core. These are the only
-          interrupts allowed on line 3 */
-       cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff);
-       interrupt_enable.u64 = 0;
-       interrupt_enable.s.mbox = 0x3;
-       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64);
-       cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
-       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
-       cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
-       /* Enable core interrupt processing for 2,3 and 7 */
-       set_c0_status(0x8c01);
+
+       octeon_irq_setup_secondary();
+       raw_local_irq_enable();
 }
 
 /**
@@ -214,6 +192,15 @@ static void octeon_init_secondary(void)
  */
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
+#ifdef CONFIG_HOTPLUG_CPU
+       struct linux_app_boot_info *labi;
+
+       labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
+
+       if (labi->labi_signature != LABI_SIGNATURE)
+               panic("The bootloader version on this board is incorrect.");
+#endif
+
        cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
        if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
                        "mailbox0", mailbox_interrupt)) {
index 8d9a5fc607e48573f50efcd3eb9e9f2af0358756..824e08c737981d8d9be039892b49f876b4c54bd0 100644 (file)
@@ -68,10 +68,10 @@ void __init init_ioasic_irqs(int base)
        fast_iob();
 
        for (i = base; i < base + IO_INR_DMA; i++)
-               set_irq_chip_and_handler(i, &ioasic_irq_type,
+               irq_set_chip_and_handler(i, &ioasic_irq_type,
                                         handle_level_irq);
        for (; i < base + IO_IRQ_LINES; i++)
-               set_irq_chip(i, &ioasic_dma_irq_type);
+               irq_set_chip(i, &ioasic_dma_irq_type);
 
        ioasic_irq_base = base;
 }
index ef31d98c4fb8dd01622505345b0fec9ced62b009..37199f742c4590ba6bb302f7fa37766aa3606342 100644 (file)
@@ -73,7 +73,7 @@ void __init init_kn02_irqs(int base)
        iob();
 
        for (i = base; i < base + KN02_IRQ_LINES; i++)
-               set_irq_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
 
        kn02_irq_base = base;
 }
index 9b1207ae22560380a9f1837f02c1069cf8103a64..3dbd7a5a6ad33f5ab8335c0c45d84f235adb9d01 100644 (file)
@@ -69,7 +69,7 @@ void emma2rh_irq_init(void)
        u32 i;
 
        for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
-               set_irq_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
+               irq_set_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
                                              &emma2rh_irq_controller,
                                              handle_level_irq, "level");
 }
@@ -105,7 +105,7 @@ void emma2rh_sw_irq_init(void)
        u32 i;
 
        for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
-               set_irq_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
+               irq_set_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
                                              &emma2rh_sw_irq_controller,
                                              handle_level_irq, "level");
 }
@@ -162,7 +162,7 @@ void emma2rh_gpio_irq_init(void)
        u32 i;
 
        for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
-               set_irq_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
+               irq_set_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
                                              &emma2rh_gpio_irq_controller,
                                              handle_edge_irq, "edge");
 }
index 6ddab8aef64478984164e372d5463bd18b5116c6..5b05f186e3952744bb932508d631932209e9e530 100644 (file)
 #define NR_IRQS OCTEON_IRQ_LAST
 #define MIPS_CPU_IRQ_BASE OCTEON_IRQ_SW0
 
-/* 0 - 7 represent the i8259 master */
-#define OCTEON_IRQ_I8259M0     0
-#define OCTEON_IRQ_I8259M1     1
-#define OCTEON_IRQ_I8259M2     2
-#define OCTEON_IRQ_I8259M3     3
-#define OCTEON_IRQ_I8259M4     4
-#define OCTEON_IRQ_I8259M5     5
-#define OCTEON_IRQ_I8259M6     6
-#define OCTEON_IRQ_I8259M7     7
-/* 8 - 15 represent the i8259 slave */
-#define OCTEON_IRQ_I8259S0     8
-#define OCTEON_IRQ_I8259S1     9
-#define OCTEON_IRQ_I8259S2     10
-#define OCTEON_IRQ_I8259S3     11
-#define OCTEON_IRQ_I8259S4     12
-#define OCTEON_IRQ_I8259S5     13
-#define OCTEON_IRQ_I8259S6     14
-#define OCTEON_IRQ_I8259S7     15
-/* 16 - 23 represent the 8 MIPS standard interrupt sources */
-#define OCTEON_IRQ_SW0         16
-#define OCTEON_IRQ_SW1         17
-#define OCTEON_IRQ_CIU0                18
-#define OCTEON_IRQ_CIU1                19
-#define OCTEON_IRQ_CIU4                20
-#define OCTEON_IRQ_5           21
-#define OCTEON_IRQ_PERF                22
-#define OCTEON_IRQ_TIMER       23
-/* 24 - 87 represent the sources in CIU_INTX_EN0 */
-#define OCTEON_IRQ_WORKQ0      24
-#define OCTEON_IRQ_WORKQ1      25
-#define OCTEON_IRQ_WORKQ2      26
-#define OCTEON_IRQ_WORKQ3      27
-#define OCTEON_IRQ_WORKQ4      28
-#define OCTEON_IRQ_WORKQ5      29
-#define OCTEON_IRQ_WORKQ6      30
-#define OCTEON_IRQ_WORKQ7      31
-#define OCTEON_IRQ_WORKQ8      32
-#define OCTEON_IRQ_WORKQ9      33
-#define OCTEON_IRQ_WORKQ10     34
-#define OCTEON_IRQ_WORKQ11     35
-#define OCTEON_IRQ_WORKQ12     36
-#define OCTEON_IRQ_WORKQ13     37
-#define OCTEON_IRQ_WORKQ14     38
-#define OCTEON_IRQ_WORKQ15     39
-#define OCTEON_IRQ_GPIO0       40
-#define OCTEON_IRQ_GPIO1       41
-#define OCTEON_IRQ_GPIO2       42
-#define OCTEON_IRQ_GPIO3       43
-#define OCTEON_IRQ_GPIO4       44
-#define OCTEON_IRQ_GPIO5       45
-#define OCTEON_IRQ_GPIO6       46
-#define OCTEON_IRQ_GPIO7       47
-#define OCTEON_IRQ_GPIO8       48
-#define OCTEON_IRQ_GPIO9       49
-#define OCTEON_IRQ_GPIO10      50
-#define OCTEON_IRQ_GPIO11      51
-#define OCTEON_IRQ_GPIO12      52
-#define OCTEON_IRQ_GPIO13      53
-#define OCTEON_IRQ_GPIO14      54
-#define OCTEON_IRQ_GPIO15      55
-#define OCTEON_IRQ_MBOX0       56
-#define OCTEON_IRQ_MBOX1       57
-#define OCTEON_IRQ_UART0       58
-#define OCTEON_IRQ_UART1       59
-#define OCTEON_IRQ_PCI_INT0    60
-#define OCTEON_IRQ_PCI_INT1    61
-#define OCTEON_IRQ_PCI_INT2    62
-#define OCTEON_IRQ_PCI_INT3    63
-#define OCTEON_IRQ_PCI_MSI0    64
-#define OCTEON_IRQ_PCI_MSI1    65
-#define OCTEON_IRQ_PCI_MSI2    66
-#define OCTEON_IRQ_PCI_MSI3    67
-#define OCTEON_IRQ_RESERVED68  68      /* Summary of CIU_INT_SUM1 */
-#define OCTEON_IRQ_TWSI                69
-#define OCTEON_IRQ_RML         70
-#define OCTEON_IRQ_TRACE       71
-#define OCTEON_IRQ_GMX_DRP0    72
-#define OCTEON_IRQ_GMX_DRP1    73
-#define OCTEON_IRQ_IPD_DRP     74
-#define OCTEON_IRQ_KEY_ZERO    75
-#define OCTEON_IRQ_TIMER0      76
-#define OCTEON_IRQ_TIMER1      77
-#define OCTEON_IRQ_TIMER2      78
-#define OCTEON_IRQ_TIMER3      79
-#define OCTEON_IRQ_USB0                80
-#define OCTEON_IRQ_PCM         81
-#define OCTEON_IRQ_MPI         82
-#define OCTEON_IRQ_TWSI2       83
-#define OCTEON_IRQ_POWIQ       84
-#define OCTEON_IRQ_IPDPPTHR    85
-#define OCTEON_IRQ_MII0                86
-#define OCTEON_IRQ_BOOTDMA     87
-/* 88 - 151 represent the sources in CIU_INTX_EN1 */
-#define OCTEON_IRQ_WDOG0       88
-#define OCTEON_IRQ_WDOG1       89
-#define OCTEON_IRQ_WDOG2       90
-#define OCTEON_IRQ_WDOG3       91
-#define OCTEON_IRQ_WDOG4       92
-#define OCTEON_IRQ_WDOG5       93
-#define OCTEON_IRQ_WDOG6       94
-#define OCTEON_IRQ_WDOG7       95
-#define OCTEON_IRQ_WDOG8       96
-#define OCTEON_IRQ_WDOG9       97
-#define OCTEON_IRQ_WDOG10      98
-#define OCTEON_IRQ_WDOG11      99
-#define OCTEON_IRQ_WDOG12      100
-#define OCTEON_IRQ_WDOG13      101
-#define OCTEON_IRQ_WDOG14      102
-#define OCTEON_IRQ_WDOG15      103
-#define OCTEON_IRQ_UART2       104
-#define OCTEON_IRQ_USB1                105
-#define OCTEON_IRQ_MII1                106
-#define OCTEON_IRQ_RESERVED107 107
-#define OCTEON_IRQ_RESERVED108 108
-#define OCTEON_IRQ_RESERVED109 109
-#define OCTEON_IRQ_RESERVED110 110
-#define OCTEON_IRQ_RESERVED111 111
-#define OCTEON_IRQ_RESERVED112 112
-#define OCTEON_IRQ_RESERVED113 113
-#define OCTEON_IRQ_RESERVED114 114
-#define OCTEON_IRQ_RESERVED115 115
-#define OCTEON_IRQ_RESERVED116 116
-#define OCTEON_IRQ_RESERVED117 117
-#define OCTEON_IRQ_RESERVED118 118
-#define OCTEON_IRQ_RESERVED119 119
-#define OCTEON_IRQ_RESERVED120 120
-#define OCTEON_IRQ_RESERVED121 121
-#define OCTEON_IRQ_RESERVED122 122
-#define OCTEON_IRQ_RESERVED123 123
-#define OCTEON_IRQ_RESERVED124 124
-#define OCTEON_IRQ_RESERVED125 125
-#define OCTEON_IRQ_RESERVED126 126
-#define OCTEON_IRQ_RESERVED127 127
-#define OCTEON_IRQ_RESERVED128 128
-#define OCTEON_IRQ_RESERVED129 129
-#define OCTEON_IRQ_RESERVED130 130
-#define OCTEON_IRQ_RESERVED131 131
-#define OCTEON_IRQ_RESERVED132 132
-#define OCTEON_IRQ_RESERVED133 133
-#define OCTEON_IRQ_RESERVED134 134
-#define OCTEON_IRQ_RESERVED135 135
-#define OCTEON_IRQ_RESERVED136 136
-#define OCTEON_IRQ_RESERVED137 137
-#define OCTEON_IRQ_RESERVED138 138
-#define OCTEON_IRQ_RESERVED139 139
-#define OCTEON_IRQ_RESERVED140 140
-#define OCTEON_IRQ_RESERVED141 141
-#define OCTEON_IRQ_RESERVED142 142
-#define OCTEON_IRQ_RESERVED143 143
-#define OCTEON_IRQ_RESERVED144 144
-#define OCTEON_IRQ_RESERVED145 145
-#define OCTEON_IRQ_RESERVED146 146
-#define OCTEON_IRQ_RESERVED147 147
-#define OCTEON_IRQ_RESERVED148 148
-#define OCTEON_IRQ_RESERVED149 149
-#define OCTEON_IRQ_RESERVED150 150
-#define OCTEON_IRQ_RESERVED151 151
+enum octeon_irq {
+/* 1 - 8 represent the 8 MIPS standard interrupt sources */
+       OCTEON_IRQ_SW0 = 1,
+       OCTEON_IRQ_SW1,
+/* CIU0, CUI2, CIU4 are 3, 4, 5 */
+       OCTEON_IRQ_5 = 6,
+       OCTEON_IRQ_PERF,
+       OCTEON_IRQ_TIMER,
+/* sources in CIU_INTX_EN0 */
+       OCTEON_IRQ_WORKQ0,
+       OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16,
+       OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
+       OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
+       OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
+       OCTEON_IRQ_MBOX1,
+       OCTEON_IRQ_UART0,
+       OCTEON_IRQ_UART1,
+       OCTEON_IRQ_UART2,
+       OCTEON_IRQ_PCI_INT0,
+       OCTEON_IRQ_PCI_INT1,
+       OCTEON_IRQ_PCI_INT2,
+       OCTEON_IRQ_PCI_INT3,
+       OCTEON_IRQ_PCI_MSI0,
+       OCTEON_IRQ_PCI_MSI1,
+       OCTEON_IRQ_PCI_MSI2,
+       OCTEON_IRQ_PCI_MSI3,
+
+       OCTEON_IRQ_TWSI,
+       OCTEON_IRQ_TWSI2,
+       OCTEON_IRQ_RML,
+       OCTEON_IRQ_TRACE0,
+       OCTEON_IRQ_GMX_DRP0 = OCTEON_IRQ_TRACE0 + 4,
+       OCTEON_IRQ_IPD_DRP = OCTEON_IRQ_GMX_DRP0 + 5,
+       OCTEON_IRQ_KEY_ZERO,
+       OCTEON_IRQ_TIMER0,
+       OCTEON_IRQ_TIMER1,
+       OCTEON_IRQ_TIMER2,
+       OCTEON_IRQ_TIMER3,
+       OCTEON_IRQ_USB0,
+       OCTEON_IRQ_USB1,
+       OCTEON_IRQ_PCM,
+       OCTEON_IRQ_MPI,
+       OCTEON_IRQ_POWIQ,
+       OCTEON_IRQ_IPDPPTHR,
+       OCTEON_IRQ_MII0,
+       OCTEON_IRQ_MII1,
+       OCTEON_IRQ_BOOTDMA,
+
+       OCTEON_IRQ_NAND,
+       OCTEON_IRQ_MIO,         /* Summary of MIO_BOOT_ERR */
+       OCTEON_IRQ_IOB,         /* Summary of IOB_INT_SUM */
+       OCTEON_IRQ_FPA,         /* Summary of FPA_INT_SUM */
+       OCTEON_IRQ_POW,         /* Summary of POW_ECC_ERR */
+       OCTEON_IRQ_L2C,         /* Summary of L2C_INT_STAT */
+       OCTEON_IRQ_IPD,         /* Summary of IPD_INT_SUM */
+       OCTEON_IRQ_PIP,         /* Summary of PIP_INT_REG */
+       OCTEON_IRQ_PKO,         /* Summary of PKO_REG_ERROR */
+       OCTEON_IRQ_ZIP,         /* Summary of ZIP_ERROR */
+       OCTEON_IRQ_TIM,         /* Summary of TIM_REG_ERROR */
+       OCTEON_IRQ_RAD,         /* Summary of RAD_REG_ERROR */
+       OCTEON_IRQ_KEY,         /* Summary of KEY_INT_SUM */
+       OCTEON_IRQ_DFA,         /* Summary of DFA */
+       OCTEON_IRQ_USBCTL,      /* Summary of USBN0_INT_SUM */
+       OCTEON_IRQ_SLI,         /* Summary of SLI_INT_SUM */
+       OCTEON_IRQ_DPI,         /* Summary of DPI_INT_SUM */
+       OCTEON_IRQ_AGX0,        /* Summary of GMX0*+PCS0_INT*_REG */
+       OCTEON_IRQ_AGL  = OCTEON_IRQ_AGX0 + 5,
+       OCTEON_IRQ_PTP,
+       OCTEON_IRQ_PEM0,
+       OCTEON_IRQ_PEM1,
+       OCTEON_IRQ_SRIO0,
+       OCTEON_IRQ_SRIO1,
+       OCTEON_IRQ_LMC0,
+       OCTEON_IRQ_DFM = OCTEON_IRQ_LMC0 + 4,           /* Summary of DFM */
+       OCTEON_IRQ_RST,
+};
 
 #ifdef CONFIG_PCI_MSI
-/* 152 - 215 represent the MSI interrupts 0-63 */
-#define OCTEON_IRQ_MSI_BIT0    152
-#define OCTEON_IRQ_MSI_LAST    (OCTEON_IRQ_MSI_BIT0 + 255)
+/* 152 - 407 represent the MSI interrupts 0-255 */
+#define OCTEON_IRQ_MSI_BIT0    (OCTEON_IRQ_RST + 1)
 
-#define OCTEON_IRQ_LAST                (OCTEON_IRQ_MSI_LAST + 1)
+#define OCTEON_IRQ_MSI_LAST      (OCTEON_IRQ_MSI_BIT0 + 255)
+#define OCTEON_IRQ_LAST          (OCTEON_IRQ_MSI_LAST + 1)
 #else
-#define OCTEON_IRQ_LAST         152
+#define OCTEON_IRQ_LAST         (OCTEON_IRQ_RST + 1)
 #endif
 
 #endif
index 6b34afd0d4e7d7ff7ec68f93a15e2d57c07059de..f72f768cd3a47b14b6be4397ba56a6c29103a9ae 100644 (file)
@@ -257,4 +257,6 @@ extern struct cvmx_bootinfo *octeon_bootinfo;
 
 extern uint64_t octeon_bootloader_entry_addr;
 
+extern void (*octeon_irq_setup_secondary)(void);
+
 #endif /* __ASM_OCTEON_OCTEON_H */
index dae22c1d2c8287f2ce2b4ed24f8a0c98eaad0f15..fa2e37ea2be17220a958a7dfaefbd121ee5e6bb8 100644 (file)
 #define __NR_name_to_handle_at         (__NR_Linux + 303)
 #define __NR_open_by_handle_at         (__NR_Linux + 304)
 #define __NR_clock_adjtime             (__NR_Linux + 305)
-#define __NR_clock_adjtime             (__NR_Linux + 306)
+#define __NR_syncfs                    (__NR_Linux + 306)
 
 /*
  * Offset of the last N32 flavoured syscall
index 40f7c6b1e26030d1a1a886f9c763c2b442410e01..260df47509494e06a6747f18891ab0ce75278fa2 100644 (file)
@@ -56,7 +56,7 @@ void __init init_r4030_ints(void)
        int i;
 
        for (i = JAZZ_IRQ_START; i <= JAZZ_IRQ_END; i++)
-               set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
 
        r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
        r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);           /* clear pending IRQs */
index bd2fc29b95e0920ed73e34d1f1de0b1ca09f236f..73031f7fc827e70c42ba99562897874b060605c5 100644 (file)
@@ -306,7 +306,7 @@ static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
        uint32_t flag;
        unsigned int gpio_irq;
        unsigned int gpio_bank;
-       struct jz_gpio_chip *chip = get_irq_desc_data(desc);
+       struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc);
 
        gpio_bank = JZ4740_IRQ_GPIO0 - irq;
 
@@ -416,7 +416,7 @@ static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
                chip->wakeup &= ~IRQ_TO_BIT(data->irq);
        spin_unlock(&chip->lock);
 
-       set_irq_wake(chip->irq, on);
+       irq_set_irq_wake(chip->irq, on);
        return 0;
 }
 
@@ -510,14 +510,14 @@ static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
        gpiochip_add(&chip->gpio_chip);
 
        chip->irq = JZ4740_IRQ_INTC_GPIO(id);
-       set_irq_data(chip->irq, chip);
-       set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+       irq_set_handler_data(chip->irq, chip);
+       irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
 
        for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
                irq_set_lockdep_class(irq, &gpio_lock_class);
-               set_irq_chip_data(irq, chip);
-               set_irq_chip_and_handler(irq, &jz_gpio_irq_chip,
-                       handle_level_irq);
+               irq_set_chip_data(irq, chip);
+               irq_set_chip_and_handler(irq, &jz_gpio_irq_chip,
+                                        handle_level_irq);
        }
 
        return 0;
index dcc5593a9389ba7552c5de926cabf3cd74221145..d82c0c430e03b27370fc12718c0077bd71f3c96a 100644 (file)
@@ -104,8 +104,8 @@ void __init arch_init_irq(void)
        writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
 
        for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
-               set_irq_chip_data(i, (void *)IRQ_BIT(i));
-               set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+               irq_set_chip_data(i, (void *)IRQ_BIT(i));
+               irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
        }
 
        setup_irq(2, &jz4740_cascade_action);
index e221662bb80cc1def1c5f35df77b93d2f2ea8b13..c018696765d4c86d5a474049f5a13023387f437d 100644 (file)
@@ -110,7 +110,7 @@ int i8259A_irq_pending(unsigned int irq)
 void make_8259A_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
-       set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+       irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
        enable_irq(irq);
 }
 
@@ -336,8 +336,8 @@ void __init init_i8259_irqs(void)
        init_8259A(0);
 
        for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) {
-               set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
-               set_irq_probe(i);
+               irq_set_chip_and_handler(i, &i8259A_chip, handle_level_irq);
+               irq_set_probe(i);
        }
 
        setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
index 43cd9628251a5e3c4d74fabb1607dee24f619c8e..0c527f652196f4be60aad9515e731c703620df49 100644 (file)
@@ -229,7 +229,7 @@ static void __init gic_basic_init(int numintrs, int numvpes,
        vpe_local_setup(numvpes);
 
        for (i = _irqbase; i < (_irqbase + numintrs); i++)
-               set_irq_chip(i, &gic_irq_controller);
+               irq_set_chip(i, &gic_irq_controller);
 }
 
 void __init gic_init(unsigned long gic_base_addr,
index 7fd176fa367ac32cee4ead24da2aaffd50689290..883fc6cead360c086b85e35a0cde476db12b22a4 100644 (file)
@@ -126,6 +126,6 @@ void __init gt641xx_irq_init(void)
         * bit31: logical or of bits[25:1].
         */
        for (i = 1; i < 30; i++)
-               set_irq_chip_and_handler(GT641XX_IRQ_BASE + i,
-                                        &gt641xx_irq_chip, handle_level_irq);
+               irq_set_chip_and_handler(GT641XX_IRQ_BASE + i,
+                                        &gt641xx_irq_chip, handle_level_irq);
 }
index fc800cd9947e648e996ec1a93bbbe4424ba2688a..0c6afeed89d2b71d382f7ec826bb5a64d762c90e 100644 (file)
@@ -137,16 +137,20 @@ void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqma
 
                switch (imp->im_type) {
                case MSC01_IRQ_EDGE:
-                       set_irq_chip_and_handler_name(irqbase + n,
-                               &msc_edgeirq_type, handle_edge_irq, "edge");
+                       irq_set_chip_and_handler_name(irqbase + n,
+                                                     &msc_edgeirq_type,
+                                                     handle_edge_irq,
+                                                     "edge");
                        if (cpu_has_veic)
                                MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
                        else
                                MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
                        break;
                case MSC01_IRQ_LEVEL:
-                       set_irq_chip_and_handler_name(irqbase+n,
-                               &msc_levelirq_type, handle_level_irq, "level");
+                       irq_set_chip_and_handler_name(irqbase + n,
+                                                     &msc_levelirq_type,
+                                                     handle_level_irq,
+                                                     "level");
                        if (cpu_has_veic)
                                MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
                        else
index fd24fd98b0410f70a83abe77a766014a4d963b87..a8a8977d58872f5973401adb691f2232937d3a73 100644 (file)
@@ -45,6 +45,6 @@ void __init rm7k_cpu_irq_init(void)
        clear_c0_intcontrol(0x00000f00);                /* Mask all */
 
        for (i = base; i < base + 4; i++)
-               set_irq_chip_and_handler(i, &rm7k_irq_controller,
+               irq_set_chip_and_handler(i, &rm7k_irq_controller,
                                         handle_percpu_irq);
 }
index ca463ec9bad522260b6613626c33dbcab7aaff22..38874a4b9255b918af63b94f289c60a4d41523cc 100644 (file)
@@ -98,10 +98,10 @@ void __init rm9k_cpu_irq_init(void)
        clear_c0_intcontrol(0x0000f000);                /* Mask all */
 
        for (i = base; i < base + 4; i++)
-               set_irq_chip_and_handler(i, &rm9k_irq_controller,
+               irq_set_chip_and_handler(i, &rm9k_irq_controller,
                                         handle_level_irq);
 
        rm9000_perfcount_irq = base + 1;
-       set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
+       irq_set_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
                                 handle_percpu_irq);
 }
index 1b68ebe1b4583f42052d470626cc4250262219b8..9b734d74ae8e0ee43922d34629ed1838d5c0e7c8 100644 (file)
@@ -102,7 +102,7 @@ void __init init_IRQ(void)
 #endif
 
        for (i = 0; i < NR_IRQS; i++)
-               set_irq_noprobe(i);
+               irq_set_noprobe(i);
 
        arch_init_irq();
 
index fd945c56bc33edd5aae2b1e04cb1b2064c1b1d0f..6e71b284f6c925b7b3f73bfd89e78bfd6816b7b6 100644 (file)
@@ -109,10 +109,10 @@ void __init mips_cpu_irq_init(void)
         */
        if (cpu_has_mipsmt)
                for (i = irq_base; i < irq_base + 2; i++)
-                       set_irq_chip_and_handler(i, &mips_mt_cpu_irq_controller,
+                       irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,
                                                 handle_percpu_irq);
 
        for (i = irq_base + 2; i < irq_base + 8; i++)
-               set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
+               irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
                                         handle_percpu_irq);
 }
index 526e1581549a53c2216bca5445e8f3602cb5fb81..b0c55b50218e9e4f1940e3fcd518aa8aecb55fda 100644 (file)
@@ -154,8 +154,8 @@ void __init txx9_irq_init(unsigned long baseaddr)
        for (i = 0; i < TXx9_MAX_IR; i++) {
                txx9irq[i].level = 4; /* middle level */
                txx9irq[i].mode = TXx9_IRCR_LOW;
-               set_irq_chip_and_handler(TXX9_IRQ_BASE + i,
-                                        &txx9_irq_chip, handle_level_irq);
+               irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &txx9_irq_chip,
+                                        handle_level_irq);
        }
 
        /* mask all IRC interrupts */
index f7e2c7807d7ba8932e8ae136e5dce79b83846f51..5a88cc4ccd5a761c468d98f6f710a38dae2013b8 100644 (file)
@@ -1146,7 +1146,7 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe)
 
        setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
 
-       set_irq_handler(cpu_ipi_irq, handle_percpu_irq);
+       irq_set_handler(cpu_ipi_irq, handle_percpu_irq);
 }
 
 /*
index 670e3e70d1983f7bcb11b4b822718f7f3908eb6d..de4c165515d780571712c81e9e641c9a31728c8c 100644 (file)
@@ -128,7 +128,7 @@ void __init arch_init_irq(void)
        mips_cpu_irq_init();
 
        for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++)
-               set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
 
        setup_irq(LASAT_CASCADE_IRQ, &cascade);
 }
index 1549361696ad01bb94c0093bf5bcd8e9b35f6770..f27d7ccca92acd148677b9a340fcb76ffc55991f 100644 (file)
@@ -44,7 +44,8 @@ void bonito_irq_init(void)
        u32 i;
 
        for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
-               set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &bonito_irq_type,
+                                        handle_level_irq);
 
 #ifdef CONFIG_CPU_LOONGSON2E
        setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction);
index b79b24afe3a2fc67ab6687a082e44d45bf219242..9027061f0ead0d8ba259681dacdee9da9330e1ce 100644 (file)
@@ -472,7 +472,7 @@ static void __init fill_ipi_map(void)
 void __init arch_init_ipiirq(int irq, struct irqaction *action)
 {
        setup_irq(irq, action);
-       set_irq_handler(irq, handle_percpu_irq);
+       irq_set_handler(irq, handle_percpu_irq);
 }
 
 void __init arch_init_irq(void)
index 3c6f190aa61ce9fdb2a15c10b96c139ca167a4d0..1620b83cd13eea594b091cc1f19dc655a0eb2e8d 100644 (file)
@@ -119,7 +119,7 @@ static void __init plat_perf_setup(void)
                        set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
                mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
 #ifdef CONFIG_SMP
-               set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq);
+               irq_set_handler(mips_cpu_perf_irq, handle_percpu_irq);
 #endif
        }
 }
index d8080499872a5af2bbf47c1f2431744b94d4ef1b..5d530f89d87223e86965eb0b013923a461263d32 100644 (file)
@@ -172,7 +172,7 @@ msi_irq_allocated:
        pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
                              control);
 
-       set_irq_msi(irq, desc);
+       irq_set_msi_desc(irq, desc);
        write_msi_msg(irq, &msg);
        return 0;
 }
@@ -259,11 +259,11 @@ static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock);
 static u64 msi_rcv_reg[4];
 static u64 mis_ena_reg[4];
 
-static void octeon_irq_msi_enable_pcie(unsigned int irq)
+static void octeon_irq_msi_enable_pcie(struct irq_data *data)
 {
        u64 en;
        unsigned long flags;
-       int msi_number = irq - OCTEON_IRQ_MSI_BIT0;
+       int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
        int irq_index = msi_number >> 6;
        int irq_bit = msi_number & 0x3f;
 
@@ -275,11 +275,11 @@ static void octeon_irq_msi_enable_pcie(unsigned int irq)
        raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
 }
 
-static void octeon_irq_msi_disable_pcie(unsigned int irq)
+static void octeon_irq_msi_disable_pcie(struct irq_data *data)
 {
        u64 en;
        unsigned long flags;
-       int msi_number = irq - OCTEON_IRQ_MSI_BIT0;
+       int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
        int irq_index = msi_number >> 6;
        int irq_bit = msi_number & 0x3f;
 
@@ -293,11 +293,11 @@ static void octeon_irq_msi_disable_pcie(unsigned int irq)
 
 static struct irq_chip octeon_irq_chip_msi_pcie = {
        .name = "MSI",
-       .enable = octeon_irq_msi_enable_pcie,
-       .disable = octeon_irq_msi_disable_pcie,
+       .irq_enable = octeon_irq_msi_enable_pcie,
+       .irq_disable = octeon_irq_msi_disable_pcie,
 };
 
-static void octeon_irq_msi_enable_pci(unsigned int irq)
+static void octeon_irq_msi_enable_pci(struct irq_data *data)
 {
        /*
         * Octeon PCI doesn't have the ability to mask/unmask MSI
@@ -308,15 +308,15 @@ static void octeon_irq_msi_enable_pci(unsigned int irq)
         */
 }
 
-static void octeon_irq_msi_disable_pci(unsigned int irq)
+static void octeon_irq_msi_disable_pci(struct irq_data *data)
 {
        /* See comment in enable */
 }
 
 static struct irq_chip octeon_irq_chip_msi_pci = {
        .name = "MSI",
-       .enable = octeon_irq_msi_enable_pci,
-       .disable = octeon_irq_msi_disable_pci,
+       .irq_enable = octeon_irq_msi_enable_pci,
+       .irq_disable = octeon_irq_msi_disable_pci,
 };
 
 /*
@@ -388,7 +388,7 @@ int __init octeon_msi_initialize(void)
        }
 
        for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++)
-               set_irq_chip_and_handler(irq, msi, handle_simple_irq);
+               irq_set_chip_and_handler(irq, msi, handle_simple_irq);
 
        if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
                if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0,
index 352f29d9226f01b5eff4377233862db55cba6817..c4fa2d775d8b80d7db818e74b50b07e19ea6d32a 100644 (file)
@@ -182,7 +182,7 @@ void __init msp_cic_irq_init(void)
 
        /* initialize all the IRQ descriptors */
        for (i = MSP_CIC_INTBASE ; i < MSP_CIC_INTBASE + 32 ; i++) {
-               set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+               irq_set_chip_and_handler(i, &msp_cic_irq_controller,
                                         handle_level_irq);
 #ifdef CONFIG_MIPS_MT_SMTC
                /* Mask of CIC interrupt */
index 8f51e4adc4380391f34567cd504388a164ca30b4..5bbcc47da6b96954134a514888e99fc0b132ef50 100644 (file)
@@ -77,7 +77,7 @@ void __init msp_slp_irq_init(void)
 
        /* initialize all the IRQ descriptors */
        for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
-               set_irq_chip_and_handler(i, &msp_slp_irq_controller,
+               irq_set_chip_and_handler(i, &msp_slp_irq_controller,
                                         handle_level_irq);
 }
 
index 43a9e26e1c699f70256205b0de722acc287653c7..bec17901ff03aae58814451a16d13487ed1b8ff9 100644 (file)
@@ -64,7 +64,7 @@ static struct irqaction irq_call = {
 void __init arch_init_ipiirq(int irq, struct irqaction *action)
 {
        setup_irq(irq, action);
-       set_irq_handler(irq, handle_percpu_irq);
+       irq_set_handler(irq, handle_percpu_irq);
 }
 
 void __init msp_vsmp_int_init(void)
index b226bcb0a2f4925969534213628bd7fd5238de5e..adc171c8846f29bae0fa55e5a889b7dbc6335086 100644 (file)
@@ -259,11 +259,13 @@ void __init arch_init_irq(void)
        /* Set IRQ information in irq_desc */
        for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) {
                pnx833x_hard_disable_pic_irq(irq);
-               set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq);
+               irq_set_chip_and_handler(irq, &pnx833x_pic_irq_type,
+                                        handle_simple_irq);
        }
 
        for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++)
-               set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq);
+               irq_set_chip_and_handler(irq, &pnx833x_gpio_irq_type,
+                                        handle_simple_irq);
 
        /* Set PIC priority limiter register to 0 */
        PNX833X_PIC_INT_PRIORITY = 0;
index dbdc35c3531db15a8791783d50313479aa2a44b0..6b93c81779c1a6166ca0a5ead00f81b1632badd4 100644 (file)
@@ -183,7 +183,7 @@ void __init arch_init_irq(void)
        int configPR;
 
        for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++)
-               set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
 
        /* init of GIC/IPC interrupts */
        /* should be done before cp0 since cp0 init enables the GIC int */
@@ -206,7 +206,7 @@ void __init arch_init_irq(void)
                /* mask/priority is still 0 so we will not get any
                 * interrupts until it is unmasked */
 
-               set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
        }
 
        /* Priority level 0 */
@@ -215,20 +215,20 @@ void __init arch_init_irq(void)
        /* Set int vector table address */
        PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
 
-       set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
+       irq_set_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
                                 handle_level_irq);
        setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
 
        /* init of Timer interrupts */
        for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++)
-               set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
 
        /* Stop Timer 1-3 */
        configPR = read_c0_config7();
        configPR |= 0x00000038;
        write_c0_config7(configPR);
 
-       set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
+       irq_set_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
                                 handle_level_irq);
        setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
 }
index 6f1c8ef6a719bf3dfee9c9d9866a6ff7015df366..7fb97fb0931e54645c7cc5598450be3b349d11b3 100644 (file)
@@ -112,5 +112,5 @@ void __init asic_irq_init(void)
         * Initialize interrupt handlers.
         */
        for (i = 0; i < NR_IRQS; i++)
-               set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
+               irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
 }
index b32a768da894f53e627bae8a450bc2b1ff8b3f56..7c6db74e3fad096831499fef13744d884d03a21a 100644 (file)
@@ -207,8 +207,8 @@ void __init arch_init_irq(void)
        pr_info("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
 
        for (i = 0; i < RC32434_NR_IRQS; i++)
-               set_irq_chip_and_handler(i,  &rc32434_irq_type,
-                                       handle_level_irq);
+               irq_set_chip_and_handler(i, &rc32434_irq_type,
+                                        handle_level_irq);
 }
 
 /* Main Interrupt dispatcher */
index e6e64750e90a40d2932f4b2f64d6b16a2ea21179..476423a01296504ce56b7825d98b600a0b68c82d 100644 (file)
@@ -312,7 +312,7 @@ void __init arch_init_irq(void)
                else
                        handler         = &ip22_local3_irq_type;
 
-               set_irq_chip_and_handler(i, handler, handle_level_irq);
+               irq_set_chip_and_handler(i, handler, handle_level_irq);
        }
 
        /* vector handler. this register the IRQ as non-sharable */
index f2d09d7700dd75b4f3ae6c00cba9638974376d82..11488719dd9747d491765e262956ff9f770d23b0 100644 (file)
@@ -337,7 +337,7 @@ static struct irq_chip bridge_irq_type = {
 
 void __devinit register_bridge_irq(unsigned int irq)
 {
-       set_irq_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
 }
 
 int __devinit request_bridge_irq(struct bridge_controller *bc)
index c01f558a2a09142fb06c0ed4a64673b1fff461a3..a152538d3c9744cb27f40a0e18d5a69eeb94c91c 100644 (file)
@@ -153,7 +153,7 @@ static void __init hub_rt_clock_event_global_init(void)
                        panic("Allocation of irq number for timer failed");
        } while (xchg(&rt_timer_irq, irq));
 
-       set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
+       irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
        setup_irq(irq, &hub_rt_irqaction);
 }
 
index e0a3ce4a8d48a550b525b79b26b33b7cb81dbb65..c65ea76d56c78a831b24603522b35207088c9a59 100644 (file)
@@ -451,43 +451,51 @@ void __init arch_init_irq(void)
        for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) {
                switch (irq) {
                case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ:
-                       set_irq_chip_and_handler_name(irq,&ip32_mace_interrupt,
-                               handle_level_irq, "level");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &ip32_mace_interrupt,
+                                                     handle_level_irq,
+                                                     "level");
                        break;
 
                case MACEPCI_SCSI0_IRQ ...  MACEPCI_SHARED2_IRQ:
-                       set_irq_chip_and_handler_name(irq,
-                               &ip32_macepci_interrupt, handle_level_irq,
-                               "level");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &ip32_macepci_interrupt,
+                                                     handle_level_irq,
+                                                     "level");
                        break;
 
                case CRIME_CPUERR_IRQ:
                case CRIME_MEMERR_IRQ:
-                       set_irq_chip_and_handler_name(irq,
-                               &crime_level_interrupt, handle_level_irq,
-                               "level");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &crime_level_interrupt,
+                                                     handle_level_irq,
+                                                     "level");
                        break;
 
                case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ:
                case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ:
                case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ:
                case CRIME_VICE_IRQ:
-                       set_irq_chip_and_handler_name(irq,
-                               &crime_edge_interrupt, handle_edge_irq, "edge");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &crime_edge_interrupt,
+                                                     handle_edge_irq,
+                                                     "edge");
                        break;
 
                case MACEISA_PARALLEL_IRQ:
                case MACEISA_SERIAL1_TDMAPR_IRQ:
                case MACEISA_SERIAL2_TDMAPR_IRQ:
-                       set_irq_chip_and_handler_name(irq,
-                               &ip32_maceisa_edge_interrupt, handle_edge_irq,
-                               "edge");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &ip32_maceisa_edge_interrupt,
+                                                     handle_edge_irq,
+                                                     "edge");
                        break;
 
                default:
-                       set_irq_chip_and_handler_name(irq,
-                               &ip32_maceisa_level_interrupt, handle_level_irq,
-                               "level");
+                       irq_set_chip_and_handler_name(irq,
+                                                     &ip32_maceisa_level_interrupt,
+                                                     handle_level_irq,
+                                                     "level");
                        break;
                }
        }
index 89e8188a466522fdd5675fddcfac18ea5088c8d2..09740d60e18722c9e5de6d565a62aa1dfded4ce3 100644 (file)
@@ -216,7 +216,8 @@ void __init init_bcm1480_irqs(void)
        int i;
 
        for (i = 0; i < BCM1480_NR_IRQS; i++) {
-               set_irq_chip_and_handler(i, &bcm1480_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &bcm1480_irq_type,
+                                        handle_level_irq);
                bcm1480_irq_owner[i] = 0;
        }
 }
index fd269ea8d8a85cbe71ca3b1e0c31e40ecf80f2d3..be4460a5f6a89634aeb589513c91059a773af13d 100644 (file)
@@ -190,7 +190,8 @@ void __init init_sb1250_irqs(void)
        int i;
 
        for (i = 0; i < SB1250_NR_IRQS; i++) {
-               set_irq_chip_and_handler(i, &sb1250_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &sb1250_irq_type,
+                                        handle_level_irq);
                sb1250_irq_owner[i] = 0;
        }
 }
index 72b94155778d51772b447c58e870cc00fc06a1a3..c48194c3073b95a2ccdcee6b1b0947913d996587 100644 (file)
@@ -209,7 +209,7 @@ void __init sni_a20r_irq_init(void)
        int i;
 
        for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
-               set_irq_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
        sni_hwint = a20r_hwint;
        change_c0_status(ST0_IM, IE_IRQ0);
        setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
index cfcc68abc5b266dc3f6235f7160b2829cc8289cf..ed3b3d31735815ac1933a289a2673e1b573977ac 100644 (file)
@@ -296,7 +296,7 @@ void __init sni_pcimt_irq_init(void)
        mips_cpu_irq_init();
        /* Actually we've got more interrupts to handle ...  */
        for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
-               set_irq_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
        sni_hwint = sni_pcimt_hwint;
        change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
 }
index 0846e99a6efee0f03e5040a28c430f96722a39db..b5246373d16bde19b832d49f2acb02b395ab2622 100644 (file)
@@ -238,7 +238,7 @@ void __init sni_pcit_irq_init(void)
 
        mips_cpu_irq_init();
        for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-               set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
        *(volatile u32 *)SNI_PCIT_INT_REG = 0;
        sni_hwint = sni_pcit_hwint;
        change_c0_status(ST0_IM, IE_IRQ1);
@@ -251,7 +251,7 @@ void __init sni_pcit_cplus_irq_init(void)
 
        mips_cpu_irq_init();
        for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-               set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
        *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
        sni_hwint = sni_pcit_hwint_cplus;
        change_c0_status(ST0_IM, IE_IRQ0);
index f05d8e593300736afbb096ee4090b775fe6f0a9a..a7e5a6d917b1572c283903729f7f495f3fb334f0 100644 (file)
@@ -413,7 +413,7 @@ void __init sni_rm200_i8259_irqs(void)
        sni_rm200_init_8259A();
 
        for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++)
-               set_irq_chip_and_handler(i, &sni_rm200_i8259A_chip,
+               irq_set_chip_and_handler(i, &sni_rm200_i8259A_chip,
                                         handle_level_irq);
 
        setup_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, &sni_rm200_irq2);
@@ -477,7 +477,7 @@ void __init sni_rm200_irq_init(void)
        mips_cpu_irq_init();
        /* Actually we've got more interrupts to handle ...  */
        for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
-               set_irq_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
        sni_hwint = sni_rm200_hwint;
        change_c0_status(ST0_IM, IE_IRQ0);
        setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq);
index e1828e8bcaefedd4449cb0b96806c50708b343ed..7e3ac5782da433003a3d8d59f0ef4f1d8e43a5fe 100644 (file)
@@ -35,7 +35,7 @@ void __init tx4927_irq_init(void)
 
        mips_cpu_irq_init();
        txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL);
-       set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
+       irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
                                handle_simple_irq);
        /* raise priority for errors, timers, SIO */
        txx9_irq_set_pri(TX4927_IR_ECCERR, 7);
index a6e6e805097a80be53edf7501f2ead464ae8f023..aace856533296e9ceb13330d5b0fa60725c402da 100644 (file)
@@ -23,7 +23,7 @@ void __init tx4938_irq_init(void)
 
        mips_cpu_irq_init();
        txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL);
-       set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
+       irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
                                handle_simple_irq);
        /* raise priority for errors, timers, SIO */
        txx9_irq_set_pri(TX4938_IR_ECCERR, 7);
index 93b6edbedd64bd7645c5ad7c9a390f6d350d434d..6b067dbd2ae1bc5d5e2d1a45cd81c380745b4ff7 100644 (file)
@@ -176,8 +176,8 @@ void __init tx4939_irq_init(void)
        for (i = 1; i < TX4939_NUM_IR; i++) {
                tx4939irq[i].level = 4; /* middle level */
                tx4939irq[i].mode = TXx9_IRCR_LOW;
-               set_irq_chip_and_handler(TXX9_IRQ_BASE + i,
-                                        &tx4939_irq_chip, handle_level_irq);
+               irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &tx4939_irq_chip,
+                                        handle_level_irq);
        }
 
        /* mask all IRC interrupts */
@@ -193,7 +193,7 @@ void __init tx4939_irq_init(void)
        __raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r);
        __raw_writel(irc_elevel, &tx4939_ircptr->msk.r);
 
-       set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
+       irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
                                handle_simple_irq);
 
        /* raise priority for errors, timers, sio */
index 92a5c1b400f061d6dcc4a7917c2cead1ceb494e8..c22c859a2c4987e77e8bafe2b9c64443fc890cce 100644 (file)
@@ -120,8 +120,9 @@ void __init jmr3927_irq_setup(void)
 
        tx3927_irq_init();
        for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++)
-               set_irq_chip_and_handler(i, &jmr3927_irq_ioc, handle_level_irq);
+               irq_set_chip_and_handler(i, &jmr3927_irq_ioc,
+                                        handle_level_irq);
 
        /* setup IOC interrupt 1 (PCI, MODEM) */
-       set_irq_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
+       irq_set_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
 }
index 7c0a048b307ca15f3cabd83207e7d8cf95fcea79..6c22c496090b10ae249e90664dc7d1ad70350cf6 100644 (file)
@@ -164,9 +164,9 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void)
 
        for (i = RBTX4927_IRQ_IOC;
             i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++)
-               set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
+               irq_set_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
                                         handle_level_irq);
-       set_irq_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
+       irq_set_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
 }
 
 static int rbtx4927_irq_dispatch(int pending)
@@ -194,5 +194,5 @@ void __init rbtx4927_irq_setup(void)
        tx4927_irq_init();
        toshiba_rbtx4927_irq_ioc_init();
        /* Onboard 10M Ether: High Active */
-       set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
 }
index 2ec4fe1b167071d3e5c8eca38616ce68b1b66768..58cd7a9272cc14f0a9a1243dc799c7db294198ba 100644 (file)
@@ -132,10 +132,10 @@ static void __init toshiba_rbtx4938_irq_ioc_init(void)
 
        for (i = RBTX4938_IRQ_IOC;
             i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++)
-               set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
+               irq_set_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
                                         handle_level_irq);
 
-       set_irq_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
+       irq_set_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
 }
 
 void __init rbtx4938_irq_setup(void)
@@ -153,5 +153,5 @@ void __init rbtx4938_irq_setup(void)
        tx4938_irq_init();
        toshiba_rbtx4938_irq_ioc_init();
        /* Onboard 10M Ether: High Active */
-       set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
+       irq_set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
 }
index 70074632fb990f6a6a6f7f133afdebdbd04517ef..69a80616f0c993ff982652240a32f2933f487cc1 100644 (file)
@@ -88,8 +88,8 @@ void __init rbtx4939_irq_setup(void)
        tx4939_irq_init();
        for (i = RBTX4939_IRQ_IOC;
             i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++)
-               set_irq_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
+               irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
                                         handle_level_irq);
 
-       set_irq_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
+       irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
 }
index f53156bb9aa8c5815432d779e15fdfe28a9c2225..a39ef3207d7148d96351e7ea23cb385bbdd8f05f 100644 (file)
@@ -710,11 +710,11 @@ static int __init vr41xx_icu_init(void)
        icu2_write(MGIUINTHREG, 0xffff);
 
        for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
-               set_irq_chip_and_handler(i, &sysint1_irq_type,
+               irq_set_chip_and_handler(i, &sysint1_irq_type,
                                         handle_level_irq);
 
        for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
-               set_irq_chip_and_handler(i, &sysint2_irq_type,
+               irq_set_chip_and_handler(i, &sysint2_irq_type,
                                         handle_level_irq);
 
        cascade_irq(INT0_IRQ, icu_get_irq);
index 9ff7f397c0e14ed7520d266e5ad77dbad78bde91..70a3b85f37576dcc8ac6ad8f68155c79c5ae747b 100644 (file)
@@ -87,7 +87,7 @@ static void irq_dispatch(unsigned int irq)
                        atomic_inc(&irq_err_count);
                else
                        irq_dispatch(irq);
-               if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
+               if (!irqd_irq_disabled(idata) && chip->irq_unmask)
                        chip->irq_unmask(idata);
        } else
                do_IRQ(irq);
index d8ab97a73db288db6b601fd13fd2baaa278f6809..a523c94fa6986dbab1858a7276e883711accaec7 100644 (file)
@@ -3,6 +3,7 @@ config MN10300
        select HAVE_OPROFILE
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_KGDB
 
index 5f7fc3eb45e60807c58a4888fce1bc5ca24e83ce..86af0d7d07719aab1c3435b71adb44ded4fee730 100644 (file)
@@ -263,7 +263,7 @@ void set_intr_level(int irq, u16 level)
  */
 void mn10300_set_lateack_irq_type(int irq)
 {
-       set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
+       irq_set_chip_and_handler(irq, &mn10300_cpu_pic_level,
                                 handle_level_irq);
 }
 
@@ -275,12 +275,12 @@ void __init init_IRQ(void)
        int irq;
 
        for (irq = 0; irq < NR_IRQS; irq++)
-               if (get_irq_chip(irq) == &no_irq_chip)
+               if (irq_get_chip(irq) == &no_irq_chip)
                        /* due to the PIC latching interrupt requests, even
                         * when the IRQ is disabled, IRQ_PENDING is superfluous
                         * and we can use handle_level_irq() for edge-triggered
                         * interrupts */
-                       set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
+                       irq_set_chip_and_handler(irq, &mn10300_cpu_pic_edge,
                                                 handle_level_irq);
 
        unit_init_IRQ();
@@ -335,91 +335,42 @@ asmlinkage void do_IRQ(void)
 /*
  * Display interrupt management information through /proc/interrupts
  */
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int i = *(loff_t *) v, j, cpu;
-       struct irqaction *action;
-       unsigned long flags;
-
-       switch (i) {
-               /* display column title bar naming CPUs */
-       case 0:
-               seq_printf(p, "           ");
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "CPU%d       ", j);
-               seq_putc(p, '\n');
-               break;
-
-               /* display information rows, one per active CPU */
-       case 1 ... NR_IRQS - 1:
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-
-               action = irq_desc[i].action;
-               if (action) {
-                       seq_printf(p, "%3d: ", i);
-                       for_each_present_cpu(cpu)
-                               seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-
-                       if (i < NR_CPU_IRQS)
-                               seq_printf(p, " %14s.%u",
-                                          irq_desc[i].irq_data.chip->name,
-                                          (GxICR(i) & GxICR_LEVEL) >>
-                                          GxICR_LEVEL_SHIFT);
-                       else
-                               seq_printf(p, " %14s",
-                                          irq_desc[i].irq_data.chip->name);
-
-                       seq_printf(p, "  %s", action->name);
-
-                       for (action = action->next;
-                            action;
-                            action = action->next)
-                               seq_printf(p, ", %s", action->name);
-
-                       seq_putc(p, '\n');
-               }
-
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-               break;
-
-               /* polish off with NMI and error counters */
-       case NR_IRQS:
 #ifdef CONFIG_MN10300_WD_TIMER
-               seq_printf(p, "NMI: ");
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "%10u ", nmi_count(j));
-               seq_putc(p, '\n');
-#endif
+       int j;
 
-               seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-               break;
-       }
+       seq_printf(p, "%*s: ", prec, "NMI");
+       for (j = 0; j < NR_CPUS; j++)
+               if (cpu_online(j))
+                       seq_printf(p, "%10u ", nmi_count(j));
+       seq_putc(p, '\n');
+#endif
 
+       seq_printf(p, "%*s: ", prec, "ERR");
+       seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
        return 0;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 void migrate_irqs(void)
 {
-       irq_desc_t *desc;
        int irq;
        unsigned int self, new;
        unsigned long flags;
 
        self = smp_processor_id();
        for (irq = 0; irq < NR_IRQS; irq++) {
-               desc = irq_desc + irq;
+               struct irq_data *data = irq_get_irq_data(irq);
 
-               if (desc->status == IRQ_PER_CPU)
+               if (irqd_is_per_cpu(data))
                        continue;
 
-               if (cpu_isset(self, irq_desc[irq].affinity) &&
+               if (cpu_isset(self, data->affinity) &&
                    !cpus_intersects(irq_affinity[irq], cpu_online_map)) {
                        int cpu_id;
                        cpu_id = first_cpu(cpu_online_map);
-                       cpu_set(cpu_id, irq_desc[irq].affinity);
+                       cpu_set(cpu_id, data->affinity);
                }
                /* We need to operate irq_affinity_online atomically. */
                arch_local_cli_save(flags);
@@ -430,7 +381,7 @@ void migrate_irqs(void)
                        GxICR(irq) = x & GxICR_LEVEL;
                        tmp = GxICR(irq);
 
-                       new = any_online_cpu(irq_desc[irq].affinity);
+                       new = any_online_cpu(data->affinity);
                        irq_affinity_online[irq] = new;
 
                        CROSS_GxICR(irq, new) =
index efca426a2ed4e7241e4a8a74d7b29a49c29a2973..94901c56baf189551f3719dadac80c9219070687 100644 (file)
@@ -933,7 +933,7 @@ static int mn10300_serial_startup(struct uart_port *_port)
                NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
        set_intr_level(port->tx_irq,
                NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
-       set_irq_chip(port->tm_irq, &mn10300_serial_pic);
+       irq_set_chip(port->tm_irq, &mn10300_serial_pic);
 
        if (request_irq(port->rx_irq, mn10300_serial_interrupt,
                        IRQF_DISABLED, port->rx_name, port) < 0)
index 51c02f97dceaa924aaba64383efcbb93032ad313..226c826a21940c79a778b6c7284116cdedc647ea 100644 (file)
@@ -156,15 +156,15 @@ static void init_ipi(void)
        u16 tmp16;
 
        /* set up the reschedule IPI */
-       set_irq_chip_and_handler(RESCHEDULE_IPI,
-                                &mn10300_ipi_type, handle_percpu_irq);
+       irq_set_chip_and_handler(RESCHEDULE_IPI, &mn10300_ipi_type,
+                                handle_percpu_irq);
        setup_irq(RESCHEDULE_IPI, &reschedule_ipi);
        set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV);
        mn10300_ipi_enable(RESCHEDULE_IPI);
 
        /* set up the call function IPI */
-       set_irq_chip_and_handler(CALL_FUNC_SINGLE_IPI,
-                                &mn10300_ipi_type, handle_percpu_irq);
+       irq_set_chip_and_handler(CALL_FUNC_SINGLE_IPI, &mn10300_ipi_type,
+                                handle_percpu_irq);
        setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi);
        set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV);
        mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
@@ -172,8 +172,8 @@ static void init_ipi(void)
        /* set up the local timer IPI */
 #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
     defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
-       set_irq_chip_and_handler(LOCAL_TIMER_IPI,
-                                &mn10300_ipi_type, handle_percpu_irq);
+       irq_set_chip_and_handler(LOCAL_TIMER_IPI, &mn10300_ipi_type,
+                                handle_percpu_irq);
        setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi);
        set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV);
        mn10300_ipi_enable(LOCAL_TIMER_IPI);
index ee84e62b16ede6e40d93592e3e6bd9342575cdd4..e16c216f31dcdd3ce0c4279f6e921ce13db1f41e 100644 (file)
@@ -100,7 +100,8 @@ void __init irq_fpga_init(void)
        SyncExBus();
 
        for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
-               set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq);
+               irq_set_chip_and_handler(irq, &asb2364_fpga_pic,
+                                        handle_level_irq);
 
        /* the FPGA drives the XIRQ1 input on the CPU PIC */
        setup_irq(XIRQ1, &fpga_irq[0]);
index cb450e1e79b322e074277aa9d56f8802476bd5c6..c0b1affc06a8fdce9163cf06a384cc958705fa59 100644 (file)
@@ -113,13 +113,8 @@ int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest)
        int cpu_dest;
 
        /* timer and ipi have to always be received on all CPUs */
-       if (CHECK_IRQ_PER_CPU(irq_to_desc(d->irq)->status)) {
-               /* Bad linux design decision.  The mask has already
-                * been set; we must reset it. Will fix - tglx
-                */
-               cpumask_setall(d->affinity);
+       if (irqd_is_per_cpu(d))
                return -EINVAL;
-       }
 
        /* whatever mask they set, we just allow one CPU */
        cpu_dest = first_cpu(*dest);
@@ -174,10 +169,11 @@ int show_interrupts(struct seq_file *p, void *v)
        }
 
        if (i < NR_IRQS) {
+               struct irq_desc *desc = irq_to_desc(i);
                struct irqaction *action;
 
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
+               raw_spin_lock_irqsave(&desc->lock, flags);
+               action = desc->action;
                if (!action)
                        goto skip;
                seq_printf(p, "%3d: ", i);
@@ -188,7 +184,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
 
-               seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
+               seq_printf(p, " %14s", irq_desc_get_chip(desc)->name);
 #ifndef PARISC_IRQ_CR16_COUNTS
                seq_printf(p, "  %s", action->name);
 
@@ -220,7 +216,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
                seq_putc(p, '\n');
  skip:
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
        }
 
        return 0;
@@ -238,15 +234,15 @@ int show_interrupts(struct seq_file *p, void *v)
 
 int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
-       if (irq_desc[irq].action)
+       if (irq_has_action(irq))
                return -EBUSY;
-       if (get_irq_chip(irq) != &cpu_interrupt_type)
+       if (irq_get_chip(irq) != &cpu_interrupt_type)
                return -EBUSY;
 
        /* for iosapic interrupts */
        if (type) {
-               set_irq_chip_and_handler(irq, type, handle_percpu_irq);
-               set_irq_chip_data(irq, data);
+               irq_set_chip_and_handler(irq, type, handle_percpu_irq);
+               irq_set_chip_data(irq, data);
                __cpu_unmask_irq(irq);
        }
        return 0;
@@ -357,7 +353,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
 #ifdef CONFIG_SMP
        desc = irq_to_desc(irq);
        cpumask_copy(&dest, desc->irq_data.affinity);
-       if (CHECK_IRQ_PER_CPU(desc->status) &&
+       if (irqd_is_per_cpu(&desc->irq_data) &&
            !cpu_isset(smp_processor_id(), dest)) {
                int cpu = first_cpu(dest);
 
@@ -398,14 +394,14 @@ static void claim_cpu_irqs(void)
 {
        int i;
        for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
-               set_irq_chip_and_handler(i, &cpu_interrupt_type,
+               irq_set_chip_and_handler(i, &cpu_interrupt_type,
                                         handle_percpu_irq);
        }
 
-       set_irq_handler(TIMER_IRQ, handle_percpu_irq);
+       irq_set_handler(TIMER_IRQ, handle_percpu_irq);
        setup_irq(TIMER_IRQ, &timer_action);
 #ifdef CONFIG_SMP
-       set_irq_handler(IPI_IRQ, handle_percpu_irq);
+       irq_set_handler(IPI_IRQ, handle_percpu_irq);
        setup_irq(IPI_IRQ, &ipi_action);
 #endif
 }
index 3584e4d4a4ad5f0f0409e5fc77e2fa6869b8dc67..d0e8a1dbf8226df7d089448d4cafa92b5aee1d1b 100644 (file)
@@ -139,6 +139,8 @@ config PPC
        select HAVE_SPARSE_IRQ
        select IRQ_PER_CPU
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
+       select GENERIC_IRQ_SHOW_LEVEL
 
 config EARLY_PRINTK
        bool
index 0a5570338b96c6bef5bdda5769e0c5be066b2cda..63625e0650b58d93bd1903708f0b574acc282e3f 100644 (file)
@@ -195,7 +195,7 @@ notrace void arch_local_irq_restore(unsigned long en)
 EXPORT_SYMBOL(arch_local_irq_restore);
 #endif /* CONFIG_PPC64 */
 
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
        int j;
 
@@ -231,65 +231,6 @@ static int show_other_interrupts(struct seq_file *p, int prec)
        return 0;
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-       unsigned long flags, any_count = 0;
-       int i = *(loff_t *) v, j, prec;
-       struct irqaction *action;
-       struct irq_desc *desc;
-       struct irq_chip *chip;
-
-       if (i > nr_irqs)
-               return 0;
-
-       for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
-               j *= 10;
-
-       if (i == nr_irqs)
-               return show_other_interrupts(p, prec);
-
-       /* print header */
-       if (i == 0) {
-               seq_printf(p, "%*s", prec + 8, "");
-               for_each_online_cpu(j)
-                       seq_printf(p, "CPU%-8d", j);
-               seq_putc(p, '\n');
-       }
-
-       desc = irq_to_desc(i);
-       if (!desc)
-               return 0;
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       for_each_online_cpu(j)
-               any_count |= kstat_irqs_cpu(i, j);
-       action = desc->action;
-       if (!action && !any_count)
-               goto out;
-
-       seq_printf(p, "%*d: ", prec, i);
-       for_each_online_cpu(j)
-               seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-
-       chip = get_irq_desc_chip(desc);
-       if (chip)
-               seq_printf(p, "  %-16s", chip->name);
-       else
-               seq_printf(p, "  %-16s", "None");
-       seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge");
-
-       if (action) {
-               seq_printf(p, "     %s", action->name);
-               while ((action = action->next) != NULL)
-                       seq_printf(p, ", %s", action->name);
-       }
-
-       seq_putc(p, '\n');
-out:
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-       return 0;
-}
-
 /*
  * /proc/stat helpers
  */
@@ -315,24 +256,26 @@ void fixup_irqs(const struct cpumask *map)
        alloc_cpumask_var(&mask, GFP_KERNEL);
 
        for_each_irq(irq) {
+               struct irq_data *data;
                struct irq_chip *chip;
 
                desc = irq_to_desc(irq);
                if (!desc)
                        continue;
 
-               if (desc->status & IRQ_PER_CPU)
+               data = irq_desc_get_irq_data(desc);
+               if (irqd_is_per_cpu(data))
                        continue;
 
-               chip = get_irq_desc_chip(desc);
+               chip = irq_data_get_irq_chip(data);
 
-               cpumask_and(mask, desc->irq_data.affinity, map);
+               cpumask_and(mask, data->affinity, map);
                if (cpumask_any(mask) >= nr_cpu_ids) {
                        printk("Breaking affinity for irq %i\n", irq);
                        cpumask_copy(mask, map);
                }
                if (chip->irq_set_affinity)
-                       chip->irq_set_affinity(&desc->irq_data, mask, true);
+                       chip->irq_set_affinity(data, mask, true);
                else if (desc->action && !(warned++))
                        printk("Cannot set affinity for irq %i\n", irq);
        }
@@ -618,7 +561,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
                        smp_wmb();
 
                        /* Clear norequest flags */
-                       irq_to_desc(i)->status &= ~IRQ_NOREQUEST;
+                       irq_clear_status_flags(i, IRQ_NOREQUEST);
 
                        /* Legacy flags are left to default at this point,
                         * one can then use irq_create_mapping() to
@@ -827,8 +770,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
 
        /* Set type if specified and different than the current one */
        if (type != IRQ_TYPE_NONE &&
-           type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
-               set_irq_type(virq, type);
+           type != (irqd_get_trigger_type(irq_get_irq_data(virq))))
+               irq_set_irq_type(virq, type);
        return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
@@ -851,7 +794,7 @@ void irq_dispose_mapping(unsigned int virq)
                return;
 
        /* remove chip and handler */
-       set_irq_chip_and_handler(virq, NULL, NULL);
+       irq_set_chip_and_handler(virq, NULL, NULL);
 
        /* Make sure it's completed */
        synchronize_irq(virq);
@@ -1156,7 +1099,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
                        seq_printf(m, "%5d  ", i);
                        seq_printf(m, "0x%05lx  ", virq_to_hw(i));
 
-                       chip = get_irq_desc_chip(desc);
+                       chip = irq_desc_get_chip(desc);
                        if (chip && chip->name)
                                p = chip->name;
                        else
index bd1e1ff17b2d585ec60a4fcdec0d6b8a08e43a52..7ee50f0547cb73de52be535b8f4b6543536b5405 100644 (file)
@@ -31,17 +31,17 @@ void machine_kexec_mask_interrupts(void) {
                if (!desc)
                        continue;
 
-               chip = get_irq_desc_chip(desc);
+               chip = irq_desc_get_chip(desc);
                if (!chip)
                        continue;
 
-               if (chip->irq_eoi && desc->status & IRQ_INPROGRESS)
+               if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
                        chip->irq_eoi(&desc->irq_data);
 
                if (chip->irq_mask)
                        chip->irq_mask(&desc->irq_data);
 
-               if (chip->irq_disable && !(desc->status & IRQ_DISABLED))
+               if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
                        chip->irq_disable(&desc->irq_data);
        }
 }
index 3cd85faa8ac66e3c251a98805d789060dbffce2d..893af2a9cd03a53bfb6e5b6d2d37cdb1cac63026 100644 (file)
@@ -261,7 +261,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
 
                virq = irq_create_mapping(NULL, line);
                if (virq != NO_IRQ)
-                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
        } else {
                pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
                         oirq.size, oirq.specifier[0], oirq.specifier[1],
index fde0ea50c97d1aca4810b1bd86e8b4a712194dcd..cfc4b200998208b33cf7fd866adbe5a4fab74ee1 100644 (file)
@@ -132,8 +132,8 @@ static int
 cpld_pic_host_map(struct irq_host *h, unsigned int virq,
                             irq_hw_number_t hw)
 {
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &cpld_pic, handle_level_irq);
        return 0;
 }
 
@@ -198,7 +198,7 @@ mpc5121_ads_cpld_pic_init(void)
                goto end;
        }
 
-       set_irq_chained_handler(cascade_irq, cpld_pic_cascade);
+       irq_set_chained_handler(cascade_irq, cpld_pic_cascade);
 end:
        of_node_put(np);
 }
index 2bd1e6cf1f58b4fa3babdc61b50713791bc6346c..57a6a349e932db9c7b51760eaef7c30d6b1951d3 100644 (file)
@@ -82,7 +82,7 @@ static struct irq_chip media5200_irq_chip = {
 
 void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int sub_virq, val;
        u32 status, enable;
 
@@ -107,7 +107,7 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
        /* Processing done; can reenable the cascade now */
        raw_spin_lock(&desc->lock);
        chip->irq_ack(&desc->irq_data);
-       if (!(desc->status & IRQ_DISABLED))
+       if (!irqd_irq_disabled(&desc->irq_data))
                chip->irq_unmask(&desc->irq_data);
        raw_spin_unlock(&desc->lock);
 }
@@ -115,15 +115,10 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
 static int media5200_irq_map(struct irq_host *h, unsigned int virq,
                             irq_hw_number_t hw)
 {
-       struct irq_desc *desc = irq_to_desc(virq);
-
        pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw);
-       set_irq_chip_data(virq, &media5200_irq);
-       set_irq_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
-       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= IRQ_TYPE_LEVEL_LOW | IRQ_LEVEL;
-
+       irq_set_chip_data(virq, &media5200_irq);
+       irq_set_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
        return 0;
 }
 
@@ -187,8 +182,8 @@ static void __init media5200_init_irq(void)
 
        media5200_irq.irqhost->host_data = &media5200_irq;
 
-       set_irq_data(cascade_virq, &media5200_irq);
-       set_irq_chained_handler(cascade_virq, media5200_irq_cascade);
+       irq_set_handler_data(cascade_virq, &media5200_irq);
+       irq_set_chained_handler(cascade_virq, media5200_irq_cascade);
 
        return;
 
index 6da44f0f2934a8f3e4fd252768ba8a0bab8326e8..6c39b9cc2fa3fe0b367d92e086a7f9b046f93700 100644 (file)
@@ -192,7 +192,7 @@ static struct irq_chip mpc52xx_gpt_irq_chip = {
 
 void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
-       struct mpc52xx_gpt_priv *gpt = get_irq_data(virq);
+       struct mpc52xx_gpt_priv *gpt = irq_get_handler_data(virq);
        int sub_virq;
        u32 status;
 
@@ -209,8 +209,8 @@ static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq,
        struct mpc52xx_gpt_priv *gpt = h->host_data;
 
        dev_dbg(gpt->dev, "%s: h=%p, virq=%i\n", __func__, h, virq);
-       set_irq_chip_data(virq, gpt);
-       set_irq_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
+       irq_set_chip_data(virq, gpt);
+       irq_set_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
 
        return 0;
 }
@@ -259,8 +259,8 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
        }
 
        gpt->irqhost->host_data = gpt;
-       set_irq_data(cascade_virq, gpt);
-       set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
+       irq_set_handler_data(cascade_virq, gpt);
+       irq_set_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
 
        /* If the GPT is currently disabled, then change it to be in Input
         * Capture mode.  If the mode is non-zero, then the pin could be
index 9f3ed582d08247bac4d039f6347ed859154023d3..3ddea96273ca5ec6e1ef5ce197fbfc26d664a815 100644 (file)
@@ -214,7 +214,7 @@ static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
        ctrl_reg |= (type << (22 - (l2irq * 2)));
        out_be32(&intr->ctrl, ctrl_reg);
 
-       __set_irq_handler_unlocked(d->irq, handler);
+       __irq_set_handler_locked(d->irq, handler);
 
        return 0;
 }
@@ -414,7 +414,7 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
                else
                        hndlr = handle_level_irq;
 
-               set_irq_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
+               irq_set_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
                pr_debug("%s: External IRQ%i virq=%x, hw=%x. type=%x\n",
                         __func__, l2irq, virq, (int)irq, type);
                return 0;
@@ -431,7 +431,7 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
                return -EINVAL;
        }
 
-       set_irq_chip_and_handler(virq, irqchip, handle_level_irq);
+       irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
        pr_debug("%s: virq=%x, l1=%i, l2=%i\n", __func__, virq, l1irq, l2irq);
 
        return 0;
index 926dfdaaf57aeccdad4bc4e1a508b87353038b14..4a4eb6ffa12f81f2ab8fdb5cd4e780560a38dbf5 100644 (file)
@@ -81,7 +81,7 @@ static struct irq_chip pq2ads_pci_ic = {
 
 static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct pq2ads_pci_pic *priv = get_irq_desc_data(desc);
+       struct pq2ads_pci_pic *priv = irq_desc_get_handler_data(desc);
        u32 stat, mask, pend;
        int bit;
 
@@ -106,17 +106,17 @@ static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
                            irq_hw_number_t hw)
 {
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_data(virq, h->host_data);
-       set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
        return 0;
 }
 
 static void pci_host_unmap(struct irq_host *h, unsigned int virq)
 {
        /* remove chip and handler */
-       set_irq_chip_data(virq, NULL);
-       set_irq_chip(virq, NULL);
+       irq_set_chip_data(virq, NULL);
+       irq_set_chip(virq, NULL);
 }
 
 static struct irq_host_ops pci_pic_host_ops = {
@@ -175,8 +175,8 @@ int __init pq2ads_pci_init_irq(void)
 
        priv->host = host;
        host->host_data = priv;
-       set_irq_data(irq, priv);
-       set_irq_chained_handler(irq, pq2ads_pci_irq_demux);
+       irq_set_handler_data(irq, priv);
+       irq_set_chained_handler(irq, pq2ads_pci_irq_demux);
 
        of_node_put(np);
        return 0;
index 64447e48f3d5c2fb5b27b4d00af9a1d47987bc34..c46f9359be158678d8c28af191088220a50f7848 100644 (file)
@@ -56,7 +56,7 @@ static void machine_restart(char *cmd)
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
 
        while ((cascade_irq = cpm2_get_irq()) >= 0)
@@ -106,7 +106,7 @@ static void __init ksi8560_pic_init(void)
 
        cpm2_pic_init(np);
        of_node_put(np);
-       set_irq_chained_handler(irq, cpm2_cascade);
+       irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
index 1352d1107bfd208e08a420fdbb8e1f609d0a7397..3b2c9bb661998918f3ac1033fc4a19311ca910b2 100644 (file)
@@ -50,7 +50,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
 
        while ((cascade_irq = cpm2_get_irq()) >= 0)
@@ -101,7 +101,7 @@ static void __init mpc85xx_ads_pic_init(void)
 
        cpm2_pic_init(np);
        of_node_put(np);
-       set_irq_chained_handler(irq, cpm2_cascade);
+       irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
index 458d91fba91d5f80ba7296c55752b0960eaca11d..6299a2a51ae8f2dc49444d5ffa66b0912e4688a6 100644 (file)
@@ -255,7 +255,7 @@ static int mpc85xx_cds_8259_attach(void)
        }
 
        /* Success. Connect our low-level cascade handler. */
-       set_irq_handler(cascade_irq, mpc85xx_8259_cascade_handler);
+       irq_set_handler(cascade_irq, mpc85xx_8259_cascade_handler);
 
        return 0;
 }
index 793ead7993abadfa0c87f9df1efe7e9e7e3e659c..c7b97f70312e792d8cd59d761982fd112827ca3b 100644 (file)
@@ -47,7 +47,7 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
 
        if (cascade_irq != NO_IRQ) {
@@ -122,7 +122,7 @@ void __init mpc85xx_ds_pic_init(void)
        i8259_init(cascade_node, 0);
        of_node_put(cascade_node);
 
-       set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade);
+       irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade);
 #endif /* CONFIG_PPC_I8259 */
 }
 
index d7e28ec3e07214c577bedc68e52d6fe9973d64c9..d2dfd465fbf67cf92f79d772284aa7e0bde6f554 100644 (file)
@@ -41,7 +41,7 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
 
        while ((cascade_irq = cpm2_get_irq()) >= 0)
@@ -92,7 +92,7 @@ static void __init sbc8560_pic_init(void)
 
        cpm2_pic_init(np);
        of_node_put(np);
-       set_irq_chained_handler(irq, cpm2_cascade);
+       irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
index 79d85aca476719830e6d440a36fbef30c82a31cf..db864623b4aea66a698291d46f6ac8349fa93e8b 100644 (file)
@@ -93,7 +93,7 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
 
 void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq;
 
        /*
@@ -245,9 +245,9 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
                irq_hw_number_t hwirq)
 {
        /* All interrupts are LEVEL sensitive */
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
-                       handle_fasteoi_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip,
+                                handle_fasteoi_irq);
 
        return 0;
 }
@@ -308,8 +308,8 @@ void socrates_fpga_pic_init(struct device_node *pic)
                        pr_warning("FPGA PIC: can't get irq%d.\n", i);
                        continue;
                }
-               set_irq_chained_handler(socrates_fpga_irqs[i],
-                               socrates_fpga_pic_cascade);
+               irq_set_chained_handler(socrates_fpga_irqs[i],
+                                       socrates_fpga_pic_cascade);
        }
 
        socrates_fpga_pic_iobase = of_iomap(pic, 0);
index 2b62b064eac7a009f0dbf0183412f506a20e34bd..5387e9f06bdba34b772f66cd174bcb17a6b963f7 100644 (file)
@@ -46,7 +46,7 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
 
        while ((cascade_irq = cpm2_get_irq()) >= 0)
@@ -102,7 +102,7 @@ static void __init stx_gp3_pic_init(void)
 
        cpm2_pic_init(np);
        of_node_put(np);
-       set_irq_chained_handler(irq, cpm2_cascade);
+       irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
index 2265b68e3279af883660772ab2bbc965b4da72e4..325de772725a6076a747dfc08ce132f8a34e67c4 100644 (file)
@@ -44,7 +44,7 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
 
        while ((cascade_irq = cpm2_get_irq()) >= 0)
@@ -100,7 +100,7 @@ static void __init tqm85xx_pic_init(void)
 
        cpm2_pic_init(np);
        of_node_put(np);
-       set_irq_chained_handler(irq, cpm2_cascade);
+       irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
index 0adfe3b740cd69bb938c6ab8e1ffd321f05a43d8..0beec7d5566bfc5b25e9a4ce591e9dac97e9fe97 100644 (file)
@@ -95,7 +95,7 @@ static int gef_pic_cascade_irq;
 
 void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq;
 
        /*
@@ -163,8 +163,8 @@ static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
                          irq_hw_number_t hwirq)
 {
        /* All interrupts are LEVEL sensitive */
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
 
        return 0;
 }
@@ -225,7 +225,7 @@ void __init gef_pic_init(struct device_node *np)
                return;
 
        /* Chain with parent controller */
-       set_irq_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
+       irq_set_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
 }
 
 /*
index cbe33639b478177d9e6b86e6cf6eb187d88e9e14..8ef8960abda6d53ccd17193ab5722ab700a2d231 100644 (file)
@@ -19,7 +19,7 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
 
        if (cascade_irq != NO_IRQ)
@@ -77,6 +77,6 @@ void __init mpc86xx_init_irq(void)
        i8259_init(cascade_node, 0);
        of_node_put(cascade_node);
 
-       set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
+       irq_set_chained_handler(cascade_irq, mpc86xx_8259_cascade);
 #endif
 }
index fabb108e874411e7008e18ad51d0db80012bfd29..9ecce995dd4b0dce5cd25f6498e41133850c8837 100644 (file)
@@ -226,11 +226,11 @@ static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
 
                generic_handle_irq(cascade_irq);
 
-               chip = get_irq_desc_chip(cdesc);
+               chip = irq_desc_get_chip(cdesc);
                chip->irq_eoi(&cdesc->irq_data);
        }
 
-       chip = get_irq_desc_chip(desc);
+       chip = irq_desc_get_chip(desc);
        chip->irq_eoi(&desc->irq_data);
 }
 
@@ -251,5 +251,5 @@ void __init mpc8xx_pics_init(void)
 
        irq = cpm_pic_init();
        if (irq != NO_IRQ)
-               set_irq_chained_handler(irq, cpm_cascade);
+               irq_set_chained_handler(irq, cpm_cascade);
 }
index 48cd7d2e1b75a54a451093121d5348fc0edbccaf..81239ebed83fef43d7a726c6d0edcf5e30931c92 100644 (file)
@@ -9,6 +9,7 @@ config PPC_CELL_COMMON
        select PPC_INDIRECT_IO
        select PPC_NATIVE
        select PPC_RTAS
+       select IRQ_EDGE_EOI_HANDLER
 
 config PPC_CELL_NATIVE
        bool
index c48b66a67e42ab7e1144d9f6c2ee90d3b617dbff..bb5ebf8fa80bff7dbe8f77463c1a439064b70624 100644 (file)
@@ -93,8 +93,8 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
 
 static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct axon_msic *msic = get_irq_data(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct axon_msic *msic = irq_get_handler_data(irq);
        u32 write_offset, msi;
        int idx;
        int retry = 0;
@@ -287,7 +287,7 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                }
                dev_dbg(&dev->dev, "axon_msi: allocated virq 0x%x\n", virq);
 
-               set_irq_msi(virq, entry);
+               irq_set_msi_desc(virq, entry);
                msg.data = virq;
                write_msi_msg(virq, &msg);
        }
@@ -305,7 +305,7 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
                if (entry->irq == NO_IRQ)
                        continue;
 
-               set_irq_msi(entry->irq, NULL);
+               irq_set_msi_desc(entry->irq, NULL);
                irq_dispose_mapping(entry->irq);
        }
 }
@@ -320,7 +320,7 @@ static struct irq_chip msic_irq_chip = {
 static int msic_host_map(struct irq_host *h, unsigned int virq,
                         irq_hw_number_t hw)
 {
-       set_irq_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
+       irq_set_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
 
        return 0;
 }
@@ -400,8 +400,8 @@ static int axon_msi_probe(struct platform_device *device)
 
        msic->irq_host->host_data = msic;
 
-       set_irq_data(virq, msic);
-       set_irq_chained_handler(virq, axon_msi_cascade);
+       irq_set_handler_data(virq, msic);
+       irq_set_chained_handler(virq, axon_msi_cascade);
        pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
        /* Enable the MSIC hardware */
index 0b8f7d7135c507c11fd0ccc828014de2b94524dd..4cb9e147c30766c8267156e4167ca1ad6a56b808 100644 (file)
@@ -136,15 +136,14 @@ static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
 static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
                               irq_hw_number_t hw)
 {
-       struct irq_desc *desc = irq_to_desc(virq);
        int64_t err;
 
        err = beat_construct_and_connect_irq_plug(virq, hw);
        if (err < 0)
                return -EIO;
 
-       desc->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
        return 0;
 }
 
index 624d26e72f1d5718e5493b178dd2696340f5f92c..44cfd1bef89b319609ffc32b308f3d6f03ba3dfa 100644 (file)
@@ -101,9 +101,9 @@ static void iic_ioexc_eoi(struct irq_data *d)
 
 static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct cbe_iic_regs __iomem *node_iic =
-               (void __iomem *)get_irq_desc_data(desc);
+               (void __iomem *)irq_desc_get_handler_data(desc);
        unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
        unsigned long bits, ack;
        int cascade;
@@ -235,67 +235,19 @@ static int iic_host_match(struct irq_host *h, struct device_node *node)
                                    "IBM,CBEA-Internal-Interrupt-Controller");
 }
 
-extern int noirqdebug;
-
-static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
-{
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-
-       raw_spin_lock(&desc->lock);
-
-       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-
-       /*
-        * If we're currently running this IRQ, or its disabled,
-        * we shouldn't process the IRQ. Mark it pending, handle
-        * the necessary masking and go out
-        */
-       if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
-                   !desc->action)) {
-               desc->status |= IRQ_PENDING;
-               goto out_eoi;
-       }
-
-       kstat_incr_irqs_this_cpu(irq, desc);
-
-       /* Mark the IRQ currently in progress.*/
-       desc->status |= IRQ_INPROGRESS;
-
-       do {
-               struct irqaction *action = desc->action;
-               irqreturn_t action_ret;
-
-               if (unlikely(!action))
-                       goto out_eoi;
-
-               desc->status &= ~IRQ_PENDING;
-               raw_spin_unlock(&desc->lock);
-               action_ret = handle_IRQ_event(irq, action);
-               if (!noirqdebug)
-                       note_interrupt(irq, desc, action_ret);
-               raw_spin_lock(&desc->lock);
-
-       } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
-
-       desc->status &= ~IRQ_INPROGRESS;
-out_eoi:
-       chip->irq_eoi(&desc->irq_data);
-       raw_spin_unlock(&desc->lock);
-}
-
 static int iic_host_map(struct irq_host *h, unsigned int virq,
                        irq_hw_number_t hw)
 {
        switch (hw & IIC_IRQ_TYPE_MASK) {
        case IIC_IRQ_TYPE_IPI:
-               set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
+               irq_set_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
                break;
        case IIC_IRQ_TYPE_IOEXC:
-               set_irq_chip_and_handler(virq, &iic_ioexc_chip,
-                                        handle_iic_irq);
+               irq_set_chip_and_handler(virq, &iic_ioexc_chip,
+                                        handle_edge_eoi_irq);
                break;
        default:
-               set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq);
+               irq_set_chip_and_handler(virq, &iic_chip, handle_edge_eoi_irq);
        }
        return 0;
 }
@@ -412,8 +364,8 @@ static int __init setup_iic(void)
                 * irq_data is a generic pointer that gets passed back
                 * to us later, so the forced cast is fine.
                 */
-               set_irq_data(cascade, (void __force *)node_iic);
-               set_irq_chained_handler(cascade , iic_ioexc_cascade);
+               irq_set_handler_data(cascade, (void __force *)node_iic);
+               irq_set_chained_handler(cascade, iic_ioexc_cascade);
                out_be64(&node_iic->iic_ir,
                         (1 << 12)              /* priority */ |
                         (node << 4)            /* dest node */ |
index 6a28d027d95940f20c5a13edf1f8d737cbf51eb2..fd57bfe00edf7f73d53019639b253653bbdfb1de 100644 (file)
@@ -187,8 +187,8 @@ machine_subsys_initcall(cell, cell_publish_devices);
 
 static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct mpic *mpic = get_irq_desc_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct mpic *mpic = irq_desc_get_handler_data(desc);
        unsigned int virq;
 
        virq = mpic_get_one_irq(mpic);
@@ -223,8 +223,8 @@ static void __init mpic_init_IRQ(void)
 
                printk(KERN_INFO "%s : hooking up to IRQ %d\n",
                       dn->full_name, virq);
-               set_irq_data(virq, mpic);
-               set_irq_chained_handler(virq, cell_mpic_cascade);
+               irq_set_handler_data(virq, mpic);
+               irq_set_chained_handler(virq, cell_mpic_cascade);
        }
 }
 
index b38cdfc1deb8e1930312f525a992876c7d458da8..c5cf50e6b45a2c45b52cae8c814214f936659486 100644 (file)
@@ -102,7 +102,7 @@ static void spider_ack_irq(struct irq_data *d)
 
        /* Reset edge detection logic if necessary
         */
-       if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
+       if (irqd_is_level_type(d))
                return;
 
        /* Only interrupts 47 to 50 can be set to edge */
@@ -119,7 +119,6 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
        struct spider_pic *pic = spider_virq_to_pic(d->irq);
        unsigned int hw = irq_map[d->irq].hwirq;
        void __iomem *cfg = spider_get_irq_config(pic, hw);
-       struct irq_desc *desc = irq_to_desc(d->irq);
        u32 old_mask;
        u32 ic;
 
@@ -147,12 +146,6 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
                return -EINVAL;
        }
 
-       /* Update irq_desc */
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= type & IRQ_TYPE_SENSE_MASK;
-       if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-               desc->status |= IRQ_LEVEL;
-
        /* Configure the source. One gross hack that was there before and
         * that I've kept around is the priority to the BE which I set to
         * be the same as the interrupt source number. I don't know wether
@@ -178,10 +171,10 @@ static struct irq_chip spider_pic = {
 static int spider_host_map(struct irq_host *h, unsigned int virq,
                        irq_hw_number_t hw)
 {
-       set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq);
+       irq_set_chip_and_handler(virq, &spider_pic, handle_level_irq);
 
        /* Set default irq type */
-       set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
        return 0;
 }
@@ -207,8 +200,8 @@ static struct irq_host_ops spider_host_ops = {
 
 static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct spider_pic *pic = get_irq_desc_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct spider_pic *pic = irq_desc_get_handler_data(desc);
        unsigned int cs, virq;
 
        cs = in_be32(pic->regs + TIR_CS) >> 24;
@@ -328,8 +321,8 @@ static void __init spider_init_one(struct device_node *of_node, int chip,
        virq = spider_find_cascade_and_node(pic);
        if (virq == NO_IRQ)
                return;
-       set_irq_data(virq, pic);
-       set_irq_chained_handler(virq, spider_irq_cascade);
+       irq_set_handler_data(virq, pic);
+       irq_set_chained_handler(virq, spider_irq_cascade);
 
        printk(KERN_INFO "spider_pic: node %d, addr: 0x%lx %s\n",
               pic->node_id, addr, of_node->full_name);
index 4c1288451a2109fdbd1920905b4857204d7ce47f..122786498419b11cf5ba344d8ad78dddb0f07d59 100644 (file)
@@ -365,7 +365,7 @@ void __init chrp_setup_arch(void)
 
 static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
 
        if (cascade_irq != NO_IRQ)
@@ -517,7 +517,7 @@ static void __init chrp_find_8259(void)
                if (cascade_irq == NO_IRQ)
                        printk(KERN_ERR "i8259: failed to map cascade irq\n");
                else
-                       set_irq_chained_handler(cascade_irq,
+                       irq_set_chained_handler(cascade_irq,
                                                chrp_8259_cascade);
        }
 }
index 0aca0e28a8e546305a22a05f9c2b5e1f040215f0..12aa62b6f227d1e9316036fed5e5436fa7079b99 100644 (file)
@@ -101,16 +101,16 @@ static struct irq_host *flipper_irq_host;
 static int flipper_pic_map(struct irq_host *h, unsigned int virq,
                           irq_hw_number_t hwirq)
 {
-       set_irq_chip_data(virq, h->host_data);
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq);
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &flipper_pic, handle_level_irq);
        return 0;
 }
 
 static void flipper_pic_unmap(struct irq_host *h, unsigned int irq)
 {
-       set_irq_chip_data(irq, NULL);
-       set_irq_chip(irq, NULL);
+       irq_set_chip_data(irq, NULL);
+       irq_set_chip(irq, NULL);
 }
 
 static int flipper_pic_match(struct irq_host *h, struct device_node *np)
index 35e448bd84796c26b640fe2f3d9cff56783179d1..2bdddfc9d520bfc6669fd9b79e9f40e367d44910 100644 (file)
@@ -94,16 +94,16 @@ static struct irq_host *hlwd_irq_host;
 static int hlwd_pic_map(struct irq_host *h, unsigned int virq,
                           irq_hw_number_t hwirq)
 {
-       set_irq_chip_data(virq, h->host_data);
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
        return 0;
 }
 
 static void hlwd_pic_unmap(struct irq_host *h, unsigned int irq)
 {
-       set_irq_chip_data(irq, NULL);
-       set_irq_chip(irq, NULL);
+       irq_set_chip_data(irq, NULL);
+       irq_set_chip(irq, NULL);
 }
 
 static struct irq_host_ops hlwd_irq_host_ops = {
@@ -129,8 +129,8 @@ static unsigned int __hlwd_pic_get_irq(struct irq_host *h)
 static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
                                      struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct irq_host *irq_host = get_irq_data(cascade_virq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct irq_host *irq_host = irq_get_handler_data(cascade_virq);
        unsigned int virq;
 
        raw_spin_lock(&desc->lock);
@@ -145,7 +145,7 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
 
        raw_spin_lock(&desc->lock);
        chip->irq_ack(&desc->irq_data); /* IRQ_LEVEL */
-       if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
+       if (!irqd_irq_disabled(&desc->irq_data) && chip->irq_unmask)
                chip->irq_unmask(&desc->irq_data);
        raw_spin_unlock(&desc->lock);
 }
@@ -218,8 +218,8 @@ void hlwd_pic_probe(void)
                        host = hlwd_pic_init(np);
                        BUG_ON(!host);
                        cascade_virq = irq_of_parse_and_map(np, 0);
-                       set_irq_data(cascade_virq, host);
-                       set_irq_chained_handler(cascade_virq,
+                       irq_set_handler_data(cascade_virq, host);
+                       irq_set_chained_handler(cascade_virq,
                                                hlwd_pic_irq_cascade);
                        hlwd_irq_host = host;
                        break;
index b21fde589ca7800c14ffb4ec7d30117a1da52687..487bda0d18d86d46a07f85378c1d27fe276c8928 100644 (file)
@@ -198,8 +198,8 @@ static void __init holly_init_IRQ(void)
        cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
        pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
        tsi108_pci_int_init(cascade_node);
-       set_irq_data(cascade_pci_irq, mpic);
-       set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+       irq_set_handler_data(cascade_pci_irq, mpic);
+       irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
 #endif
        /* Configure MPIC outputs to CPU0 */
        tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
index 7a2ba39d7811a101b1fa14439e087a67b85e2e29..1cb907c9435909e6fd96f909663941a4d1a15c27 100644 (file)
@@ -153,8 +153,8 @@ static void __init mpc7448_hpc2_init_IRQ(void)
        DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__,
            (u32) cascade_pci_irq);
        tsi108_pci_int_init(cascade_node);
-       set_irq_data(cascade_pci_irq, mpic);
-       set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+       irq_set_handler_data(cascade_pci_irq, mpic);
+       irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
 #endif
        /* Configure MPIC outputs to CPU0 */
        tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
index 4fb96f0b2df6030b2220925fd170fb3dd7e7dadb..52a6889832c74ec5e334b81c062f05542bf99357 100644 (file)
@@ -220,7 +220,7 @@ void __init iSeries_activate_IRQs()
                if (!desc)
                        continue;
 
-               chip = get_irq_desc_chip(desc);
+               chip = irq_desc_get_chip(desc);
                if (chip && chip->irq_startup) {
                        raw_spin_lock_irqsave(&desc->lock, flags);
                        chip->irq_startup(&desc->irq_data);
@@ -346,7 +346,7 @@ unsigned int iSeries_get_irq(void)
 static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
                                irq_hw_number_t hw)
 {
-       set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
+       irq_set_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
 
        return 0;
 }
index 04296ffff8bf6a6a171550d1648c19e1e0ce5f4a..dd2e48b28508fab49c428d764831967a63f139de 100644 (file)
@@ -498,7 +498,7 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
                printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
                dev->irq = irq_create_mapping(NULL, 1);
                if (dev->irq != NO_IRQ)
-                       set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+                       irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
        }
 
        /* Hide AMD8111 IDE interrupt when in legacy mode so
index a6067b38d2ca2d9d2216c75346fd0aeec57aba84..7c858e6f843c1821c5900f7f6de872e05b6ac397 100644 (file)
@@ -239,7 +239,7 @@ static __init void pas_init_IRQ(void)
        if (nmiprop) {
                nmi_virq = irq_create_mapping(NULL, *nmiprop);
                mpic_irq_set_priority(nmi_virq, 15);
-               set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
                mpic_unmask_irq(irq_get_irq_data(nmi_virq));
        }
 
index 3bc075c788ef3af25bcf06223098cffee2808942..ab6898942700a3a4ebb3018038300634e95dc40a 100644 (file)
@@ -988,7 +988,7 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
            dev->vendor == PCI_VENDOR_ID_DEC &&
            dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
                dev->irq = irq_create_mapping(NULL, 60);
-               set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+               irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
        }
 #endif /* CONFIG_PPC32 */
 }
index c55812bb6a5140d75617a645fc72b70d47f441bf..023f24086a0ae08c9c1a3871a4ae24c754fe69ca 100644 (file)
@@ -157,7 +157,7 @@ static unsigned int pmac_startup_irq(struct irq_data *d)
         int i = src >> 5;
 
        raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-       if ((irq_to_desc(d->irq)->status & IRQ_LEVEL) == 0)
+       if (!irqd_is_level_type(d))
                out_le32(&pmac_irq_hw[i]->ack, bit);
         __set_bit(src, ppc_cached_irq_mask);
         __pmac_set_irq_mask(src, 0);
@@ -289,7 +289,6 @@ static int pmac_pic_host_match(struct irq_host *h, struct device_node *node)
 static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
                             irq_hw_number_t hw)
 {
-       struct irq_desc *desc = irq_to_desc(virq);
        int level;
 
        if (hw >= max_irqs)
@@ -300,9 +299,9 @@ static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
         */
        level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
        if (level)
-               desc->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &pmac_pic, level ?
-                                handle_level_irq : handle_edge_irq);
+               irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &pmac_pic,
+                                level ? handle_level_irq : handle_edge_irq);
        return 0;
 }
 
@@ -472,8 +471,8 @@ int of_irq_map_oldworld(struct device_node *device, int index,
 
 static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct mpic *mpic = get_irq_desc_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct mpic *mpic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq = mpic_get_one_irq(mpic);
 
        if (cascade_irq != NO_IRQ)
@@ -591,8 +590,8 @@ static int __init pmac_pic_probe_mpic(void)
                of_node_put(slave);
                return 0;
        }
-       set_irq_data(cascade, mpic2);
-       set_irq_chained_handler(cascade, pmac_u3_cascade);
+       irq_set_handler_data(cascade, mpic2);
+       irq_set_chained_handler(cascade, pmac_u3_cascade);
 
        of_node_put(slave);
        return 0;
index 3988c86682a5d9e8afde19711ab4b48ca9be5a20..f2f6413b81d3d8887734b6ca01902724a96d87de 100644 (file)
@@ -194,7 +194,7 @@ static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
        pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
                outlet, cpu, *virq);
 
-       result = set_irq_chip_data(*virq, pd);
+       result = irq_set_chip_data(*virq, pd);
 
        if (result) {
                pr_debug("%s:%d: set_irq_chip_data failed\n",
@@ -221,12 +221,12 @@ fail_create:
 
 static int ps3_virq_destroy(unsigned int virq)
 {
-       const struct ps3_private *pd = get_irq_chip_data(virq);
+       const struct ps3_private *pd = irq_get_chip_data(virq);
 
        pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
                __LINE__, pd->ppe_id, pd->thread_id, virq);
 
-       set_irq_chip_data(virq, NULL);
+       irq_set_chip_data(virq, NULL);
        irq_dispose_mapping(virq);
 
        pr_debug("%s:%d <-\n", __func__, __LINE__);
@@ -256,7 +256,7 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
                goto fail_setup;
        }
 
-       pd = get_irq_chip_data(*virq);
+       pd = irq_get_chip_data(*virq);
 
        /* Binds outlet to cpu + virq. */
 
@@ -291,7 +291,7 @@ EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
 int ps3_irq_plug_destroy(unsigned int virq)
 {
        int result;
-       const struct ps3_private *pd = get_irq_chip_data(virq);
+       const struct ps3_private *pd = irq_get_chip_data(virq);
 
        pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
                __LINE__, pd->ppe_id, pd->thread_id, virq);
@@ -661,7 +661,7 @@ static void dump_bmp(struct ps3_private* pd) {};
 
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
-       set_irq_chip_data(virq, NULL);
+       irq_set_chip_data(virq, NULL);
 }
 
 static int ps3_host_map(struct irq_host *h, unsigned int virq,
@@ -670,7 +670,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
        pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
                virq);
 
-       set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
+       irq_set_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
        return 0;
 }
index 18ac801f8e909186c8ef72f5f89199920538dc9b..38d24e7e7bb19830e6f9d3cc7b199c51a10cafe0 100644 (file)
@@ -137,7 +137,7 @@ static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
 
-               set_irq_msi(entry->irq, NULL);
+               irq_set_msi_desc(entry->irq, NULL);
                irq_dispose_mapping(entry->irq);
        }
 
@@ -437,7 +437,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                }
 
                dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
-               set_irq_msi(virq, entry);
+               irq_set_msi_desc(virq, entry);
 
                /* Read config space back so we can restore after reset */
                read_msi_msg(virq, &msg);
index 2a0089a2c8290361bf95cac4ad3e040d60711b04..c319d04aa79992b25344005f02ad103b9e076a01 100644 (file)
@@ -114,7 +114,7 @@ static void __init fwnmi_init(void)
 
 static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
 
        if (cascade_irq != NO_IRQ)
@@ -169,7 +169,7 @@ static void __init pseries_setup_i8259_cascade(void)
                printk(KERN_DEBUG "pic: PCI 8259 intack at 0x%016lx\n", intack);
        i8259_init(found, intack);
        of_node_put(found);
-       set_irq_chained_handler(cascade, pseries_8259_cascade);
+       irq_set_chained_handler(cascade, pseries_8259_cascade);
 }
 
 static void __init pseries_mpic_init_IRQ(void)
index 01fea46c03353b63a154c6b6441e9725d3d21298..6c1e638f0ce925df32003b1624f73c03be0df771 100644 (file)
@@ -470,8 +470,8 @@ static int xics_host_map(struct irq_host *h, unsigned int virq,
        /* Insert the interrupt mapping into the radix tree for fast lookup */
        irq_radix_revmap_insert(xics_host, virq, hw);
 
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
        return 0;
 }
 
@@ -600,7 +600,7 @@ static void xics_request_ipi(void)
         * IPIs are marked IRQF_DISABLED as they must run with irqs
         * disabled
         */
-       set_irq_handler(ipi, handle_percpu_irq);
+       irq_set_handler(ipi, handle_percpu_irq);
        if (firmware_has_feature(FW_FEATURE_LPAR))
                rc = request_irq(ipi, xics_ipi_action_lpar,
                                IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
@@ -912,7 +912,7 @@ void xics_migrate_irqs_away(void)
                if (desc == NULL || desc->action == NULL)
                        continue;
 
-               chip = get_irq_desc_chip(desc);
+               chip = irq_desc_get_chip(desc);
                if (chip == NULL || chip->irq_set_affinity == NULL)
                        continue;
 
index 0476bcc7c3e14857a33aebad80a8a0abd1cc2ceb..8b5aba2633239b217346276d91c56d88eed7ecae 100644 (file)
@@ -103,8 +103,8 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
 {
        pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
        return 0;
 }
 
index 473032556715130f3664bf112e6adda4ead4caa6..5495c1be472be68e828c04f9a8fe1724f7109e97 100644 (file)
@@ -115,32 +115,25 @@ static void cpm2_ack(struct irq_data *d)
 
 static void cpm2_end_irq(struct irq_data *d)
 {
-       struct irq_desc *desc;
        int     bit, word;
        unsigned int irq_nr = virq_to_hw(d->irq);
 
-       desc = irq_to_desc(irq_nr);
-       if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
-                       && desc->action) {
-
-               bit = irq_to_siubit[irq_nr];
-               word = irq_to_siureg[irq_nr];
+       bit = irq_to_siubit[irq_nr];
+       word = irq_to_siureg[irq_nr];
 
-               ppc_cached_irq_mask[word] |= 1 << bit;
-               out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
+       ppc_cached_irq_mask[word] |= 1 << bit;
+       out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 
-               /*
-                * Work around large numbers of spurious IRQs on PowerPC 82xx
-                * systems.
-                */
-               mb();
-       }
+       /*
+        * Work around large numbers of spurious IRQs on PowerPC 82xx
+        * systems.
+        */
+       mb();
 }
 
 static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
        unsigned int src = virq_to_hw(d->irq);
-       struct irq_desc *desc = irq_to_desc(d->irq);
        unsigned int vold, vnew, edibit;
 
        /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
@@ -162,13 +155,11 @@ static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
                        goto err_sense;
        }
 
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-       if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
-               desc->status |= IRQ_LEVEL;
-               desc->handle_irq = handle_level_irq;
-       } else
-               desc->handle_irq = handle_edge_irq;
+       irqd_set_trigger_type(d, flow_type);
+       if (flow_type & IRQ_TYPE_LEVEL_LOW)
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       else
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
 
        /* internal IRQ senses are LEVEL_LOW
         * EXT IRQ and Port C IRQ senses are programmable
@@ -179,7 +170,8 @@ static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
                if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
                        edibit = (31 - (CPM2_IRQ_PORTC0 - src));
                else
-                       return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
+                       return (flow_type & IRQ_TYPE_LEVEL_LOW) ?
+                               IRQ_SET_MASK_OK_NOCOPY : -EINVAL;
 
        vold = in_be32(&cpm2_intctl->ic_siexr);
 
@@ -190,7 +182,7 @@ static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 
        if (vold != vnew)
                out_be32(&cpm2_intctl->ic_siexr, vnew);
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 
 err_sense:
        pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
@@ -204,6 +196,7 @@ static struct irq_chip cpm2_pic = {
        .irq_ack = cpm2_ack,
        .irq_eoi = cpm2_end_irq,
        .irq_set_type = cpm2_set_irq_type,
+       .flags = IRQCHIP_EOI_IF_HANDLED,
 };
 
 unsigned int cpm2_get_irq(void)
@@ -226,8 +219,8 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
 {
        pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
        return 0;
 }
 
index 58e09b2833f2ce8111673de016a32e44e7cf8063..d5679dc1e20faddf7d5a20df6bc1374aee74e264 100644 (file)
@@ -64,10 +64,10 @@ static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
        struct fsl_msi *msi_data = h->host_data;
        struct irq_chip *chip = &fsl_msi_chip;
 
-       irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
+       irq_set_status_flags(virq, IRQ_TYPE_EDGE_FALLING);
 
-       set_irq_chip_data(virq, msi_data);
-       set_irq_chip_and_handler(virq, chip, handle_edge_irq);
+       irq_set_chip_data(virq, msi_data);
+       irq_set_chip_and_handler(virq, chip, handle_edge_irq);
 
        return 0;
 }
@@ -110,8 +110,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
        list_for_each_entry(entry, &pdev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
-               msi_data = get_irq_data(entry->irq);
-               set_irq_msi(entry->irq, NULL);
+               msi_data = irq_get_handler_data(entry->irq);
+               irq_set_msi_desc(entry->irq, NULL);
                msi_bitmap_free_hwirqs(&msi_data->bitmap,
                                       virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
@@ -168,8 +168,8 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                        rc = -ENOSPC;
                        goto out_free;
                }
-               set_irq_data(virq, msi_data);
-               set_irq_msi(virq, entry);
+               irq_set_handler_data(virq, msi_data);
+               irq_set_msi_desc(virq, entry);
 
                fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
                write_msi_msg(virq, &msg);
@@ -183,7 +183,8 @@ out_free:
 
 static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct irq_data *idata = irq_desc_get_irq_data(desc);
        unsigned int cascade_irq;
        struct fsl_msi *msi_data;
        int msir_index = -1;
@@ -192,20 +193,20 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        u32 have_shift = 0;
        struct fsl_msi_cascade_data *cascade_data;
 
-       cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
+       cascade_data = (struct fsl_msi_cascade_data *)irq_get_handler_data(irq);
        msi_data = cascade_data->msi_data;
 
        raw_spin_lock(&desc->lock);
        if ((msi_data->feature &  FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
                if (chip->irq_mask_ack)
-                       chip->irq_mask_ack(&desc->irq_data);
+                       chip->irq_mask_ack(idata);
                else {
-                       chip->irq_mask(&desc->irq_data);
-                       chip->irq_ack(&desc->irq_data);
+                       chip->irq_mask(idata);
+                       chip->irq_ack(idata);
                }
        }
 
-       if (unlikely(desc->status & IRQ_INPROGRESS))
+       if (unlikely(irqd_irq_inprogress(idata)))
                goto unlock;
 
        msir_index = cascade_data->index;
@@ -213,7 +214,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        if (msir_index >= NR_MSI_REG)
                cascade_irq = NO_IRQ;
 
-       desc->status |= IRQ_INPROGRESS;
+       irqd_set_chained_irq_inprogress(idata);
        switch (msi_data->feature & FSL_PIC_IP_MASK) {
        case FSL_PIC_IP_MPIC:
                msir_value = fsl_msi_read(msi_data->msi_regs,
@@ -235,15 +236,15 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
                have_shift += intr_index + 1;
                msir_value = msir_value >> (intr_index + 1);
        }
-       desc->status &= ~IRQ_INPROGRESS;
+       irqd_clr_chained_irq_inprogress(idata);
 
        switch (msi_data->feature & FSL_PIC_IP_MASK) {
        case FSL_PIC_IP_MPIC:
-               chip->irq_eoi(&desc->irq_data);
+               chip->irq_eoi(idata);
                break;
        case FSL_PIC_IP_IPIC:
-               if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
-                       chip->irq_unmask(&desc->irq_data);
+               if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+                       chip->irq_unmask(idata);
                break;
        }
 unlock:
@@ -261,7 +262,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
        for (i = 0; i < NR_MSI_REG; i++) {
                virq = msi->msi_virqs[i];
                if (virq != NO_IRQ) {
-                       cascade_data = get_irq_data(virq);
+                       cascade_data = irq_get_handler_data(virq);
                        kfree(cascade_data);
                        irq_dispose_mapping(virq);
                }
@@ -297,8 +298,8 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
        msi->msi_virqs[irq_index] = virt_msir;
        cascade_data->index = offset + irq_index;
        cascade_data->msi_data = msi;
-       set_irq_data(virt_msir, cascade_data);
-       set_irq_chained_handler(virt_msir, fsl_msi_cascade);
+       irq_set_handler_data(virt_msir, cascade_data);
+       irq_set_chained_handler(virt_msir, fsl_msi_cascade);
 
        return 0;
 }
index aeda4c8d0a0ae6586fd0f1bfeefda32061799f3c..142770cb84b6b75afc33c9261db336c8ad8d8d26 100644 (file)
@@ -175,13 +175,13 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,
 
        /* We block the internal cascade */
        if (hw == 2)
-               irq_to_desc(virq)->status |= IRQ_NOREQUEST;
+               irq_set_status_flags(virq, IRQ_NOREQUEST);
 
        /* We use the level handler only for now, we might want to
         * be more cautious here but that works for now
         */
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       irq_set_chip_and_handler(virq, &i8259_pic, handle_level_irq);
        return 0;
 }
 
@@ -191,7 +191,7 @@ static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
        i8259_mask_irq(irq_get_irq_data(virq));
 
        /* remove chip and handler */
-       set_irq_chip_and_handler(virq, NULL, NULL);
+       irq_set_chip_and_handler(virq, NULL, NULL);
 
        /* Make sure it's completed */
        synchronize_irq(virq);
index 497047dc986e38ea158a78c4cd8c49daba3b8da8..fa438be962b71a2519fc00ff054698226a529b75 100644 (file)
@@ -605,7 +605,6 @@ static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
        struct ipic *ipic = ipic_from_irq(d->irq);
        unsigned int src = ipic_irq_to_hw(d->irq);
-       struct irq_desc *desc = irq_to_desc(d->irq);
        unsigned int vold, vnew, edibit;
 
        if (flow_type == IRQ_TYPE_NONE)
@@ -623,17 +622,16 @@ static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
                printk(KERN_ERR "ipic: edge sense not supported on internal "
                                "interrupts\n");
                return -EINVAL;
+
        }
 
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+       irqd_set_trigger_type(d, flow_type);
        if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
-               desc->status |= IRQ_LEVEL;
-               desc->handle_irq = handle_level_irq;
-               desc->irq_data.chip = &ipic_level_irq_chip;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+               d->chip = &ipic_level_irq_chip;
        } else {
-               desc->handle_irq = handle_edge_irq;
-               desc->irq_data.chip = &ipic_edge_irq_chip;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               d->chip = &ipic_edge_irq_chip;
        }
 
        /* only EXT IRQ senses are programmable on ipic
@@ -655,7 +653,7 @@ static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
        }
        if (vold != vnew)
                ipic_write(ipic->regs, IPIC_SECNR, vnew);
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 /* level interrupts and edge interrupts have different ack operations */
@@ -687,11 +685,11 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq,
 {
        struct ipic *ipic = h->host_data;
 
-       set_irq_chip_data(virq, ipic);
-       set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
+       irq_set_chip_data(virq, ipic);
+       irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 
        /* Set default irq type */
-       set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
        return 0;
 }
index 1a75a7fb4a994ff53c7b3f239c9100a8a9a9f82d..f550e23632f8a7db81c7752714453d0dbd113b7e 100644 (file)
@@ -72,13 +72,6 @@ static void mpc8xx_end_irq(struct irq_data *d)
 
 static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
-
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-               desc->status |= IRQ_LEVEL;
-
        if (flow_type & IRQ_TYPE_EDGE_FALLING) {
                irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
                unsigned int siel = in_be32(&siu_reg->sc_siel);
@@ -87,7 +80,7 @@ static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
                if ((hw & 1) == 0) {
                        siel |= (0x80000000 >> hw);
                        out_be32(&siu_reg->sc_siel, siel);
-                       desc->handle_irq = handle_edge_irq;
+                       __irq_set_handler_locked(irq, handle_edge_irq);
                }
        }
        return 0;
@@ -124,7 +117,7 @@ static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
        pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
        /* Set default irq handle */
-       set_irq_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
+       irq_set_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
        return 0;
 }
 
index 232e701245d7ce13c35558b77ada331c73404f41..0892a2841c2bfa17ea668902b8ed2d3b5de3f382 100644 (file)
@@ -145,7 +145,7 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 
 static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_desc_data(desc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
        struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
        unsigned int mask;
 
@@ -278,9 +278,9 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
        if (mpc8xxx_gc->of_dev_id_data)
                mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
 
-       set_irq_chip_data(virq, h->host_data);
-       set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
-       set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
        return 0;
 }
@@ -369,8 +369,8 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
        out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
        out_be32(mm_gc->regs + GPIO_IMR, 0);
 
-       set_irq_data(hwirq, mpc8xxx_gc);
-       set_irq_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
+       irq_set_handler_data(hwirq, mpc8xxx_gc);
+       irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
 
 skip_irq:
        return;
index 0f7c6718d26107c37e819be52d9794bbe7b9e883..f91c065bed5a21be3f1a7fd6e186a27d72b3e6de 100644 (file)
@@ -361,7 +361,7 @@ static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
 }
 
 static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
-                                     unsigned int irqflags)
+                                     bool level)
 {
        struct mpic_irq_fixup *fixup = &mpic->fixups[source];
        unsigned long flags;
@@ -370,14 +370,14 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
        if (fixup->base == NULL)
                return;
 
-       DBG("startup_ht_interrupt(0x%x, 0x%x) index: %d\n",
-           source, irqflags, fixup->index);
+       DBG("startup_ht_interrupt(0x%x) index: %d\n",
+           source, fixup->index);
        raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
        /* Enable and configure */
        writeb(0x10 + 2 * fixup->index, fixup->base + 2);
        tmp = readl(fixup->base + 4);
        tmp &= ~(0x23U);
-       if (irqflags & IRQ_LEVEL)
+       if (level)
                tmp |= 0x22;
        writel(tmp, fixup->base + 4);
        raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags);
@@ -389,8 +389,7 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
 #endif
 }
 
-static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
-                                      unsigned int irqflags)
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source)
 {
        struct mpic_irq_fixup *fixup = &mpic->fixups[source];
        unsigned long flags;
@@ -399,7 +398,7 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
        if (fixup->base == NULL)
                return;
 
-       DBG("shutdown_ht_interrupt(0x%x, 0x%x)\n", source, irqflags);
+       DBG("shutdown_ht_interrupt(0x%x)\n", source);
 
        /* Disable */
        raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
@@ -616,7 +615,7 @@ static struct mpic *mpic_find(unsigned int irq)
        if (irq < NUM_ISA_INTERRUPTS)
                return NULL;
 
-       return get_irq_chip_data(irq);
+       return irq_get_chip_data(irq);
 }
 
 /* Determine if the linux irq is an IPI */
@@ -650,7 +649,7 @@ static inline struct mpic * mpic_from_ipi(struct irq_data *d)
 /* Get the mpic structure from the irq number */
 static inline struct mpic * mpic_from_irq(unsigned int irq)
 {
-       return get_irq_chip_data(irq);
+       return irq_get_chip_data(irq);
 }
 
 /* Get the mpic structure from the irq data */
@@ -738,7 +737,7 @@ static void mpic_unmask_ht_irq(struct irq_data *d)
 
        mpic_unmask_irq(d);
 
-       if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
+       if (irqd_is_level_type(d))
                mpic_ht_end_irq(mpic, src);
 }
 
@@ -748,7 +747,7 @@ static unsigned int mpic_startup_ht_irq(struct irq_data *d)
        unsigned int src = mpic_irq_to_hw(d->irq);
 
        mpic_unmask_irq(d);
-       mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
+       mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
 
        return 0;
 }
@@ -758,7 +757,7 @@ static void mpic_shutdown_ht_irq(struct irq_data *d)
        struct mpic *mpic = mpic_from_irq_data(d);
        unsigned int src = mpic_irq_to_hw(d->irq);
 
-       mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
+       mpic_shutdown_ht_interrupt(mpic, src);
        mpic_mask_irq(d);
 }
 
@@ -775,7 +774,7 @@ static void mpic_end_ht_irq(struct irq_data *d)
         * latched another edge interrupt coming in anyway
         */
 
-       if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
+       if (irqd_is_level_type(d))
                mpic_ht_end_irq(mpic, src);
        mpic_eoi(mpic);
 }
@@ -864,7 +863,6 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
        struct mpic *mpic = mpic_from_irq_data(d);
        unsigned int src = mpic_irq_to_hw(d->irq);
-       struct irq_desc *desc = irq_to_desc(d->irq);
        unsigned int vecpri, vold, vnew;
 
        DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
@@ -879,10 +877,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
        if (flow_type == IRQ_TYPE_NONE)
                flow_type = IRQ_TYPE_LEVEL_LOW;
 
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-               desc->status |= IRQ_LEVEL;
+       irqd_set_trigger_type(d, flow_type);
 
        if (mpic_is_ht_interrupt(mpic, src))
                vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
@@ -897,7 +892,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
        if (vold != vnew)
                mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;;
 }
 
 void mpic_set_vector(unsigned int virq, unsigned int vector)
@@ -983,8 +978,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
                WARN_ON(!(mpic->flags & MPIC_PRIMARY));
 
                DBG("mpic: mapping as IPI\n");
-               set_irq_chip_data(virq, mpic);
-               set_irq_chip_and_handler(virq, &mpic->hc_ipi,
+               irq_set_chip_data(virq, mpic);
+               irq_set_chip_and_handler(virq, &mpic->hc_ipi,
                                         handle_percpu_irq);
                return 0;
        }
@@ -1006,11 +1001,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
 
        DBG("mpic: mapping to irq chip @%p\n", chip);
 
-       set_irq_chip_data(virq, mpic);
-       set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
+       irq_set_chip_data(virq, mpic);
+       irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
 
        /* Set default irq type */
-       set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
        /* If the MPIC was reset, then all vectors have already been
         * initialized.  Otherwise, a per source lazy initialization
index 0b7794acfce1107675cc1376518dd37276462eef..38e62382070c9301135b0ff95b7181eeaab44bfd 100644 (file)
@@ -81,7 +81,7 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
 
-               set_irq_msi(entry->irq, NULL);
+               irq_set_msi_desc(entry->irq, NULL);
                msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
                                       virq_to_hw(entry->irq), ALLOC_CHUNK);
                irq_dispose_mapping(entry->irq);
@@ -131,9 +131,9 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                 */
                mpic_set_vector(virq, 0);
 
-               set_irq_msi(virq, entry);
-               set_irq_chip(virq, &mpic_pasemi_msi_chip);
-               set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+               irq_set_msi_desc(virq, entry);
+               irq_set_chip(virq, &mpic_pasemi_msi_chip);
+               irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
                pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \
                         "addr 0x%x\n", virq, hwirq, msg.address_lo);
index 71900ac78270d06711153b3027bf19ea17206912..9a7aa0ed9c1c2bfcadf7edcc496ac8e9eb85a255 100644 (file)
@@ -129,7 +129,7 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
 
-               set_irq_msi(entry->irq, NULL);
+               irq_set_msi_desc(entry->irq, NULL);
                msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
                                       virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
@@ -166,9 +166,9 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                        return -ENOSPC;
                }
 
-               set_irq_msi(virq, entry);
-               set_irq_chip(virq, &mpic_u3msi_chip);
-               set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+               irq_set_msi_desc(virq, entry);
+               irq_set_chip(virq, &mpic_u3msi_chip);
+               irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
                pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
                          virq, hwirq, (unsigned long)addr);
index bc61ebb8987c5f2b7d0650600fec9294c4693845..e9c633c7c083472c45d40e626928255d730e0210 100644 (file)
@@ -213,11 +213,12 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq,
 {
        int level1;
 
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
+       irq_set_status_flags(virq, IRQ_LEVEL);
 
        level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET;
        BUG_ON(level1 > MV64x60_LEVEL1_GPP);
-       set_irq_chip_and_handler(virq, mv64x60_chips[level1], handle_level_irq);
+       irq_set_chip_and_handler(virq, mv64x60_chips[level1],
+                                handle_level_irq);
 
        return 0;
 }
index 8c9ded8ea07c334d3bb4d949caa81274daadff64..832d6924ad1c68068a25b12a184b68842cadc746 100644 (file)
@@ -189,7 +189,7 @@ static inline void qe_ic_write(volatile __be32  __iomem * base, unsigned int reg
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
 {
-       return get_irq_chip_data(virq);
+       return irq_get_chip_data(virq);
 }
 
 static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
@@ -267,10 +267,10 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
        /* Default chip */
        chip = &qe_ic->hc_irq;
 
-       set_irq_chip_data(virq, qe_ic);
-       irq_to_desc(virq)->status |= IRQ_LEVEL;
+       irq_set_chip_data(virq, qe_ic);
+       irq_set_status_flags(virq, IRQ_LEVEL);
 
-       set_irq_chip_and_handler(virq, chip, handle_level_irq);
+       irq_set_chip_and_handler(virq, chip, handle_level_irq);
 
        return 0;
 }
@@ -386,13 +386,13 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
 
        qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
 
-       set_irq_data(qe_ic->virq_low, qe_ic);
-       set_irq_chained_handler(qe_ic->virq_low, low_handler);
+       irq_set_handler_data(qe_ic->virq_low, qe_ic);
+       irq_set_chained_handler(qe_ic->virq_low, low_handler);
 
        if (qe_ic->virq_high != NO_IRQ &&
                        qe_ic->virq_high != qe_ic->virq_low) {
-               set_irq_data(qe_ic->virq_high, qe_ic);
-               set_irq_chained_handler(qe_ic->virq_high, high_handler);
+               irq_set_handler_data(qe_ic->virq_high, qe_ic);
+               irq_set_chained_handler(qe_ic->virq_high, high_handler);
        }
 }
 
index 02c91db900374f065f443fb1bbbd01ebf3ab6f74..4d18658116e5c21b7b20376db0f5ad30c1f090ee 100644 (file)
@@ -391,8 +391,8 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
        DBG("%s(%d, 0x%lx)\n", __func__, virq, hw);
        if ((virq >= 1) && (virq <= 4)){
                irq = virq + IRQ_PCI_INTAD_BASE - 1;
-               irq_to_desc(irq)->status |= IRQ_LEVEL;
-               set_irq_chip(irq, &tsi108_pci_irq);
+               irq_set_status_flags(irq, IRQ_LEVEL);
+               irq_set_chip(irq, &tsi108_pci_irq);
        }
        return 0;
 }
@@ -431,7 +431,7 @@ void __init tsi108_pci_int_init(struct device_node *node)
 
 void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = get_pci_source();
 
        if (cascade_irq != NO_IRQ)
index 835f7958b237c75bad59588e5ef5c8703c491358..5d9138516628ec40a42abd24af14ddfef1f7bdae 100644 (file)
@@ -57,7 +57,6 @@ struct uic {
 
 static void uic_unmask_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
        struct uic *uic = irq_data_get_irq_chip_data(d);
        unsigned int src = uic_irq_to_hw(d->irq);
        unsigned long flags;
@@ -66,7 +65,7 @@ static void uic_unmask_irq(struct irq_data *d)
        sr = 1 << (31-src);
        spin_lock_irqsave(&uic->lock, flags);
        /* ack level-triggered interrupts here */
-       if (desc->status & IRQ_LEVEL)
+       if (irqd_is_level_type(d))
                mtdcr(uic->dcrbase + UIC_SR, sr);
        er = mfdcr(uic->dcrbase + UIC_ER);
        er |= sr;
@@ -101,7 +100,6 @@ static void uic_ack_irq(struct irq_data *d)
 
 static void uic_mask_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
        struct uic *uic = irq_data_get_irq_chip_data(d);
        unsigned int src = uic_irq_to_hw(d->irq);
        unsigned long flags;
@@ -120,7 +118,7 @@ static void uic_mask_ack_irq(struct irq_data *d)
         * level interrupts are ack'ed after the actual
         * isr call in the uic_unmask_irq()
         */
-       if (!(desc->status & IRQ_LEVEL))
+       if (!irqd_is_level_type(d))
                mtdcr(uic->dcrbase + UIC_SR, sr);
        spin_unlock_irqrestore(&uic->lock, flags);
 }
@@ -129,7 +127,6 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
        struct uic *uic = irq_data_get_irq_chip_data(d);
        unsigned int src = uic_irq_to_hw(d->irq);
-       struct irq_desc *desc = irq_to_desc(d->irq);
        unsigned long flags;
        int trigger, polarity;
        u32 tr, pr, mask;
@@ -166,11 +163,6 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
        mtdcr(uic->dcrbase + UIC_PR, pr);
        mtdcr(uic->dcrbase + UIC_TR, tr);
 
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-       if (!trigger)
-               desc->status |= IRQ_LEVEL;
-
        spin_unlock_irqrestore(&uic->lock, flags);
 
        return 0;
@@ -190,13 +182,13 @@ static int uic_host_map(struct irq_host *h, unsigned int virq,
 {
        struct uic *uic = h->host_data;
 
-       set_irq_chip_data(virq, uic);
+       irq_set_chip_data(virq, uic);
        /* Despite the name, handle_level_irq() works for both level
         * and edge irqs on UIC.  FIXME: check this is correct */
-       set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
+       irq_set_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
 
        /* Set default irq type */
-       set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
        return 0;
 }
@@ -220,17 +212,18 @@ static struct irq_host_ops uic_host_ops = {
 
 void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
-       struct uic *uic = get_irq_data(virq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct irq_data *idata = irq_desc_get_irq_data(desc);
+       struct uic *uic = irq_get_handler_data(virq);
        u32 msr;
        int src;
        int subvirq;
 
        raw_spin_lock(&desc->lock);
-       if (desc->status & IRQ_LEVEL)
-               chip->irq_mask(&desc->irq_data);
+       if (irqd_is_level_type(idata))
+               chip->irq_mask(idata);
        else
-               chip->irq_mask_ack(&desc->irq_data);
+               chip->irq_mask_ack(idata);
        raw_spin_unlock(&desc->lock);
 
        msr = mfdcr(uic->dcrbase + UIC_MSR);
@@ -244,10 +237,10 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 
 uic_irq_ret:
        raw_spin_lock(&desc->lock);
-       if (desc->status & IRQ_LEVEL)
-               chip->irq_ack(&desc->irq_data);
-       if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
-               chip->irq_unmask(&desc->irq_data);
+       if (irqd_is_level_type(idata))
+               chip->irq_ack(idata);
+       if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+               chip->irq_unmask(idata);
        raw_spin_unlock(&desc->lock);
 }
 
@@ -336,8 +329,8 @@ void __init uic_init_tree(void)
 
                        cascade_virq = irq_of_parse_and_map(np, 0);
 
-                       set_irq_data(cascade_virq, uic);
-                       set_irq_chained_handler(cascade_virq, uic_irq_cascade);
+                       irq_set_handler_data(cascade_virq, uic);
+                       irq_set_chained_handler(cascade_virq, uic_irq_cascade);
 
                        /* FIXME: setup critical cascade?? */
                }
index 7436f3ed4df6e0b81ae0959911018517d5c395a3..0a13fc19e287858687bae6bdf2ad12398ed8822b 100644 (file)
@@ -79,12 +79,6 @@ static void xilinx_intc_mask(struct irq_data *d)
 
 static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
 {
-       struct irq_desc *desc = irq_to_desc(d->irq);
-
-       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-               desc->status |= IRQ_LEVEL;
        return 0;
 }
 
@@ -170,15 +164,15 @@ static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct,
 static int xilinx_intc_map(struct irq_host *h, unsigned int virq,
                                  irq_hw_number_t irq)
 {
-       set_irq_chip_data(virq, h->host_data);
+       irq_set_chip_data(virq, h->host_data);
 
        if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
            xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
-               set_irq_chip_and_handler(virq, &xilinx_intc_level_irqchip,
-                       handle_level_irq);
+               irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
+                                        handle_level_irq);
        } else {
-               set_irq_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
-                       handle_edge_irq);
+               irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
+                                        handle_edge_irq);
        }
        return 0;
 }
@@ -229,7 +223,7 @@ int xilinx_intc_get_irq(void)
  */
 static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = get_irq_desc_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
 
        if (cascade_irq)
@@ -256,7 +250,7 @@ static void __init xilinx_i8259_setup_cascade(void)
        }
 
        i8259_init(cascade_node, 0);
-       set_irq_chained_handler(cascade_irq, xilinx_i8259_cascade);
+       irq_set_chained_handler(cascade_irq, xilinx_i8259_cascade);
 
        /* Program irq 7 (usb/audio), 14/15 (ide) to level sensitive */
        /* This looks like a dirty hack to me --gcl */
index 27b2295f41f378e341acd86e23582fb19d80de2e..4278bbc032ce46b0a472b5f418606ae9844acea7 100644 (file)
@@ -3,6 +3,8 @@ menu "Machine selection"
 config SCORE
        def_bool y
        select HAVE_GENERIC_HARDIRQS
+       select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
 
 choice
        prompt "System type"
index 5c7563891e288e9b972e9ecc38b8a1b1dd361ee0..37c6ac9dd6e846cd7cf2adf988296884ecadaf4a 100644 (file)
@@ -29,7 +29,7 @@ static inline unsigned long arch_local_save_flags(void)
 
 static inline unsigned long arch_local_irq_save(void)
 {
-       unsigned long flags
+       unsigned long flags;
 
        asm volatile(
                "       mfcr    r8, cr0         \n"
index 47647dde09caef3eae17a8a58db399e0649a5367..d4196732c65e9ed478e5992cc3426a3cde31a634 100644 (file)
@@ -52,9 +52,9 @@ asmlinkage void do_IRQ(int irq)
        irq_exit();
 }
 
-static void score_mask(unsigned int irq_nr)
+static void score_mask(struct irq_data *d)
 {
-       unsigned int irq_source = 63 - irq_nr;
+       unsigned int irq_source = 63 - d->irq;
 
        if (irq_source < 32)
                __raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) | \
@@ -64,9 +64,9 @@ static void score_mask(unsigned int irq_nr)
                        (1 << (irq_source - 32))), SCORE_PIC + INT_MASKH);
 }
 
-static void score_unmask(unsigned int irq_nr)
+static void score_unmask(struct irq_data *d)
 {
-       unsigned int irq_source = 63 - irq_nr;
+       unsigned int irq_source = 63 - d->irq;
 
        if (irq_source < 32)
                __raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) & \
@@ -78,9 +78,9 @@ static void score_unmask(unsigned int irq_nr)
 
 struct irq_chip score_irq_chip = {
        .name           = "Score7-level",
-       .mask           = score_mask,
-       .mask_ack       = score_mask,
-       .unmask         = score_unmask,
+       .irq_mask       = score_mask,
+       .irq_mask_ack   = score_mask,
+       .irq_unmask     = score_unmask,
 };
 
 /*
@@ -92,7 +92,7 @@ void __init init_IRQ(void)
        unsigned long target_addr;
 
        for (index = 0; index < NR_IRQS; ++index)
-               set_irq_chip_and_handler(index, &score_irq_chip,
+               irq_set_chip_and_handler(index, &score_irq_chip,
                                         handle_level_irq);
 
        for (target_addr = IRQ_VECTOR_BASE_ADDR;
@@ -109,40 +109,3 @@ void __init init_IRQ(void)
                : : "r" (EXCEPTION_VECTOR_BASE_ADDR | \
                        VECTOR_ADDRESS_OFFSET_MODE16));
 }
-
-/*
- * Generic, controller-independent functions:
- */
-int show_interrupts(struct seq_file *p, void *v)
-{
-       int i = *(loff_t *)v, cpu;
-       struct irqaction *action;
-       unsigned long flags;
-
-       if (i == 0) {
-               seq_puts(p, "           ");
-               for_each_online_cpu(cpu)
-                       seq_printf(p, "CPU%d       ", cpu);
-               seq_putc(p, '\n');
-       }
-
-       if (i < NR_IRQS) {
-               spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
-               if (!action)
-                       goto unlock;
-
-               seq_printf(p, "%3d: ", i);
-               seq_printf(p, "%10u ", kstat_irqs(i));
-               seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
-               seq_printf(p, "  %s", action->name);
-               for (action = action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-unlock:
-               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       }
-
-       return 0;
-}
index efba450a051838fa49d792676f3a9285ae9a1ff8..93f5039099b708d4ac86e7fcda1f007185d91772 100644 (file)
@@ -388,12 +388,12 @@ static void __init init_mpr2_IRQ(void)
 {
        plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-5 */
 
-       set_irq_type(32, IRQ_TYPE_LEVEL_LOW);    /* IRQ0 CAN1 */
-       set_irq_type(33, IRQ_TYPE_LEVEL_LOW);    /* IRQ1 CAN2 */
-       set_irq_type(34, IRQ_TYPE_LEVEL_LOW);    /* IRQ2 CAN3 */
-       set_irq_type(35, IRQ_TYPE_LEVEL_LOW);    /* IRQ3 SMSC9115 */
-       set_irq_type(36, IRQ_TYPE_EDGE_RISING);  /* IRQ4 touchscreen */
-       set_irq_type(37, IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
+       irq_set_irq_type(32, IRQ_TYPE_LEVEL_LOW);    /* IRQ0 CAN1 */
+       irq_set_irq_type(33, IRQ_TYPE_LEVEL_LOW);    /* IRQ1 CAN2 */
+       irq_set_irq_type(34, IRQ_TYPE_LEVEL_LOW);    /* IRQ2 CAN3 */
+       irq_set_irq_type(35, IRQ_TYPE_LEVEL_LOW);    /* IRQ3 SMSC9115 */
+       irq_set_irq_type(36, IRQ_TYPE_EDGE_RISING);  /* IRQ4 touchscreen */
+       irq_set_irq_type(37, IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
 
        intc_set_priority(32, 13);              /* IRQ0 CAN1 */
        intc_set_priority(33, 13);              /* IRQ0 CAN2 */
index 3e5fc3bbf3ed08044a2cd71bc1da588910a16ea6..636d8318a72a2c76136c99b4d509247d7aa3c959 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/delay.h>
@@ -423,7 +423,7 @@ static struct resource sdhi0_cn3_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0x04ce0000,
-               .end    = 0x04ce01ff,
+               .end    = 0x04ce00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -453,7 +453,7 @@ static struct resource sdhi1_cn7_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0x04cf0000,
-               .end    = 0x04cf01ff,
+               .end    = 0x04cf00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index d7ac5af9d10239c9a056c583877faa4853ed5521..311bcebdbd07ab2039cb50be96e6d9d369c684af 100644 (file)
@@ -149,8 +149,8 @@ void init_cayman_irq(void)
        }
 
        for (i = 0; i < NR_EXT_IRQS; i++) {
-               set_irq_chip_and_handler(START_EXT_IRQS + i, &cayman_irq_type,
-                                        handle_level_irq);
+               irq_set_chip_and_handler(START_EXT_IRQS + i,
+                                        &cayman_irq_type, handle_level_irq);
        }
 
        /* Setup the SMSC interrupt */
index 72e7ac9549dacd7da513d06f72aa6bb4caec35b1..78cf2ab89d7aa2f2ce1ee20c2c2112c8957b2ed2 100644 (file)
@@ -161,7 +161,6 @@ void systemasic_irq_init(void)
                        return;
                }
 
-               set_irq_chip_and_handler(i, &systemasic_int,
-                                        handle_level_irq);
+               irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq);
        }
 }
index e44480ce2ea8c32555c84e4f7caf3e033f65a850..fd4ff25f23b2f95ecd34166226a9896521f2f853 100644 (file)
@@ -11,9 +11,9 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
@@ -464,7 +464,7 @@ static struct i2c_board_info ts_i2c_clients = {
        .irq            = IRQ0,
 };
 
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
 /* SDHI0 */
 static void sdhi0_set_pwr(struct platform_device *pdev, int state)
 {
@@ -482,7 +482,7 @@ static struct resource sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0x04ce0000,
-               .end    = 0x04ce01ff,
+               .end    = 0x04ce00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -522,7 +522,7 @@ static struct resource sdhi1_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0x04cf0000,
-               .end    = 0x04cf01ff,
+               .end    = 0x04cf00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -880,7 +880,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
        &ceu0_device,
        &ceu1_device,
        &keysc_device,
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
        &sdhi0_device,
 #if !defined(CONFIG_MMC_SH_MMCIF)
        &sdhi1_device,
@@ -1102,7 +1102,7 @@ static int __init arch_setup(void)
 
                /* enable TouchScreen */
                i2c_register_board_info(0, &ts_i2c_clients, 1);
-               set_irq_type(IRQ0, IRQ_TYPE_LEVEL_LOW);
+               irq_set_irq_type(IRQ0, IRQ_TYPE_LEVEL_LOW);
        }
 
        /* enable CEU0 */
@@ -1162,7 +1162,7 @@ static int __init arch_setup(void)
        gpio_direction_input(GPIO_PTR5);
        gpio_direction_input(GPIO_PTR6);
 
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
        /* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
        gpio_request(GPIO_FN_SDHI0CD,  NULL);
        gpio_request(GPIO_FN_SDHI0WP,  NULL);
index 7504daaa85da72b26139f7930605e4f5ea8a813d..8b4abbbd1477f1fb6112de54ac2c35dff9b260e1 100644 (file)
@@ -10,8 +10,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/onenand.h>
@@ -354,7 +354,7 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0x04ce0000,
-               .end    = 0x04ce01ff,
+               .end    = 0x04ce00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index c35001fd90329caf7fca0f88531ddfc858fb03f0..4fb00369f0e2ebde486ccb67b68897198a423b0d 100644 (file)
@@ -117,7 +117,7 @@ static struct irq_chip microdev_irq_type = {
 static void __init make_microdev_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
-       set_irq_chip_and_handler(irq, &microdev_irq_type, handle_level_irq);
+       irq_set_chip_and_handler(irq, &microdev_irq_type, handle_level_irq);
        disable_microdev_irq(irq_get_irq_data(irq));
 }
 
index 03a7ffe729d534b61efd0cf7f3e8d23ae920fca3..184fde16913282c76e51c6ba1a2ddab1d267d789 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
 #include <linux/i2c.h>
@@ -399,7 +399,7 @@ static struct resource sdhi_cn9_resources[] = {
        [0] = {
                .name   = "SDHI",
                .start  = 0x04ce0000,
-               .end    = 0x04ce01ff,
+               .end    = 0x04ce00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index 9070d7e607047fccec2d51b865dfe89307cd5d41..0db058e709e9e92082b09c7306aeb19e0ed27c4f 100644 (file)
@@ -92,9 +92,8 @@ static void eoi_se7206_irq(struct irq_data *data)
 {
        unsigned short sts0,sts1;
        unsigned int irq = data->irq;
-       struct irq_desc *desc = irq_to_desc(irq);
 
-       if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+       if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data))
                enable_se7206_irq(data);
        /* FPGA isr clear */
        sts0 = __raw_readw(INTSTS0);
@@ -126,7 +125,7 @@ static struct irq_chip se7206_irq_chip __read_mostly = {
 static void make_se7206_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
-       set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
+       irq_set_chip_and_handler_name(irq, &se7206_irq_chip,
                                      handle_level_irq, "level");
        disable_se7206_irq(irq_get_irq_data(irq));
 }
index 76255a19417fe38c100c33e82e59276e09e75e13..fd45ffc48340b898cac839d6be1d5e038693d52a 100644 (file)
@@ -67,19 +67,20 @@ void __init init_7343se_IRQ(void)
                        return;
                se7343_fpga_irq[i] = irq;
 
-               set_irq_chip_and_handler_name(se7343_fpga_irq[i],
+               irq_set_chip_and_handler_name(se7343_fpga_irq[i],
                                              &se7343_irq_chip,
-                                             handle_level_irq, "level");
+                                             handle_level_irq,
+                                             "level");
 
-               set_irq_chip_data(se7343_fpga_irq[i], (void *)i);
+               irq_set_chip_data(se7343_fpga_irq[i], (void *)i);
        }
 
-       set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux);
-       set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
-       set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux);
-       set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
-       set_irq_chained_handler(IRQ4_IRQ, se7343_irq_demux);
-       set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
-       set_irq_chained_handler(IRQ5_IRQ, se7343_irq_demux);
-       set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux);
+       irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux);
+       irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux);
+       irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux);
+       irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
index c013f95628ed382b6f73b8e24d6bdabcea43f353..aac92f21ebd23e945b680550eb90274ec622ca0d 100644 (file)
@@ -67,16 +67,17 @@ void __init init_se7722_IRQ(void)
                        return;
                se7722_fpga_irq[i] = irq;
 
-               set_irq_chip_and_handler_name(se7722_fpga_irq[i],
+               irq_set_chip_and_handler_name(se7722_fpga_irq[i],
                                              &se7722_irq_chip,
-                                             handle_level_irq, "level");
+                                             handle_level_irq,
+                                             "level");
 
-               set_irq_chip_data(se7722_fpga_irq[i], (void *)i);
+               irq_set_chip_data(se7722_fpga_irq[i], (void *)i);
        }
 
-       set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux);
-       set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux);
+       irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
 
-       set_irq_chained_handler(IRQ1_IRQ, se7722_irq_demux);
-       set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux);
+       irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
index 5bd87c22b65b613b88743f9f564d01fafdabc1e6..c6342ce7768df0432b4e67190a50cc808bb65da6 100644 (file)
@@ -140,17 +140,16 @@ void __init init_se7724_IRQ(void)
                        return;
                }
 
-               set_irq_chip_and_handler_name(irq,
-                                             &se7724_irq_chip,
+               irq_set_chip_and_handler_name(irq, &se7724_irq_chip,
                                              handle_level_irq, "level");
        }
 
-       set_irq_chained_handler(IRQ0_IRQ, se7724_irq_demux);
-       set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
+       irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
 
-       set_irq_chained_handler(IRQ1_IRQ, se7724_irq_demux);
-       set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ1_IRQ, se7724_irq_demux);
+       irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 
-       set_irq_chained_handler(IRQ2_IRQ, se7724_irq_demux);
-       set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(IRQ2_IRQ, se7724_irq_demux);
+       irq_set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
index c8bcf6a19b55d7ce8f6a9425602f07be470e8d6a..12357671023e38c8e1df3ccf5cfd211f2fc31ff8 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
 #include <linux/smc91x.h>
@@ -456,7 +456,7 @@ static struct resource sdhi0_cn7_resources[] = {
        [0] = {
                .name   = "SDHI0",
                .start  = 0x04ce0000,
-               .end    = 0x04ce01ff,
+               .end    = 0x04ce00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -488,7 +488,7 @@ static struct resource sdhi1_cn8_resources[] = {
        [0] = {
                .name   = "SDHI1",
                .start  = 0x04cf0000,
-               .end    = 0x04cf01ff,
+               .end    = 0x04cf00ff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index 239e74066253e68920ff08253777d9478e37b185..f33b2b57019c298dd9a6622085fe85ef107bf8d9 100644 (file)
@@ -102,8 +102,8 @@ int __init x3proto_gpio_setup(void)
 
                spin_lock_irqsave(&x3proto_gpio_lock, flags);
                x3proto_gpio_irq_map[i] = irq;
-               set_irq_chip_and_handler_name(irq, &dummy_irq_chip,
-                                       handle_simple_irq, "gpio");
+               irq_set_chip_and_handler_name(irq, &dummy_irq_chip,
+                                             handle_simple_irq, "gpio");
                spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
        }
 
@@ -113,8 +113,8 @@ int __init x3proto_gpio_setup(void)
                x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
                ilsel);
 
-       set_irq_chained_handler(ilsel, x3proto_gpio_irq_handler);
-       set_irq_wake(ilsel, 1);
+       irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler);
+       irq_set_irq_wake(ilsel, 1);
 
        return 0;
 
index 177a10b25cad166f2530bb4a598ad5f0e9c2a032..eb4ea4d44d59527c0cc4e691904b1c516deb24e7 100644 (file)
@@ -107,12 +107,12 @@ int __init setup_hd64461(void)
                        return -EINVAL;
                }
 
-               set_irq_chip_and_handler(i, &hd64461_irq_chip,
+               irq_set_chip_and_handler(i, &hd64461_irq_chip,
                                         handle_level_irq);
        }
 
-       set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
-       set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
+       irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
+       irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
 
 #ifdef CONFIG_HD64461_ENABLER
        printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
index 32c825c9488e8160b9a218c911f6b7cc2bacbef2..39b6a24c159d96081854dbd59d02f94d4db5e8a5 100644 (file)
@@ -80,6 +80,6 @@ static struct irq_chip imask_irq_chip = {
 
 void make_imask_irq(unsigned int irq)
 {
-       set_irq_chip_and_handler_name(irq, &imask_irq_chip,
-                                     handle_level_irq, "level");
+       irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq,
+                                     "level");
 }
index 5af48f8357e50539574914295e87e115484a3725..9e056a3a0c73f98ad26917f810c2538c9fb30492 100644 (file)
@@ -135,7 +135,7 @@ void __init plat_irq_setup(void)
 
        /* Set default: per-line enable/disable, priority driven ack/eoi */
        for (i = 0; i < NR_INTC_IRQS; i++)
-               set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+               irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
 
 
        /* Disable all interrupts and set all priorities to 0 to avoid trouble */
index 7516c35ee5149ffd9e45fb34b9002e05995cef96..5de6dff5c21b5b5ddcc9b4b713c85ce2d2e35e41 100644 (file)
@@ -74,9 +74,9 @@ void register_ipr_controller(struct ipr_desc *desc)
                }
 
                disable_irq_nosync(p->irq);
-               set_irq_chip_and_handler_name(p->irq, &desc->chip,
-                                     handle_level_irq, "level");
-               set_irq_chip_data(p->irq, p);
+               irq_set_chip_and_handler_name(p->irq, &desc->chip,
+                                             handle_level_irq, "level");
+               irq_set_chip_data(p->irq, p);
                disable_ipr_irq(irq_get_irq_data(p->irq));
        }
 }
index f766e6bf370ebb2e8972a0cbdfd28b54f752d97c..14b234631f5f4fe278ba5b4faa43346d68c9c58c 100644 (file)
@@ -52,6 +52,8 @@ config SPARC64
        select PERF_USE_VMALLOC
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
+       select IRQ_PREFLOW_FASTEOI
 
 config ARCH_DEFCONFIG
        string
index eb16e3b8a2dd3c80eed85733b6bb14d791b98131..b1d275ce34352fa0f8c1dc136e047614cebe9e82 100644 (file)
@@ -162,47 +162,14 @@ void irq_free(unsigned int irq)
 /*
  * /proc/interrupts printing:
  */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int i = *(loff_t *) v, j;
-       struct irqaction * action;
-       unsigned long flags;
+       int j;
 
-       if (i == 0) {
-               seq_printf(p, "           ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "CPU%d       ",j);
-               seq_putc(p, '\n');
-       }
-
-       if (i < NR_IRQS) {
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
-               if (!action)
-                       goto skip;
-               seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-               seq_printf(p, " %9s", irq_desc[i].irq_data.chip->name);
-               seq_printf(p, "  %s", action->name);
-
-               for (action=action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-skip:
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS) {
-               seq_printf(p, "NMI: ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
-               seq_printf(p, "     Non-maskable interrupts\n");
-       }
+       seq_printf(p, "NMI: ");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
+       seq_printf(p, "     Non-maskable interrupts\n");
        return 0;
 }
 
@@ -344,10 +311,6 @@ static void sun4u_irq_disable(struct irq_data *data)
 static void sun4u_irq_eoi(struct irq_data *data)
 {
        struct irq_handler_data *handler_data = data->handler_data;
-       struct irq_desc *desc = irq_desc + data->irq;
-
-       if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               return;
 
        if (likely(handler_data))
                upa_writeq(ICLR_IDLE, handler_data->iclr);
@@ -402,12 +365,8 @@ static void sun4v_irq_disable(struct irq_data *data)
 static void sun4v_irq_eoi(struct irq_data *data)
 {
        unsigned int ino = irq_table[data->irq].dev_ino;
-       struct irq_desc *desc = irq_desc + data->irq;
        int err;
 
-       if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               return;
-
        err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
        if (err != HV_EOK)
                printk(KERN_ERR "sun4v_intr_setstate(%x): "
@@ -481,13 +440,9 @@ static void sun4v_virq_disable(struct irq_data *data)
 
 static void sun4v_virq_eoi(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_desc + data->irq;
        unsigned long dev_handle, dev_ino;
        int err;
 
-       if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               return;
-
        dev_handle = irq_table[data->irq].dev_handle;
        dev_ino = irq_table[data->irq].dev_ino;
 
@@ -505,6 +460,7 @@ static struct irq_chip sun4u_irq = {
        .irq_disable            = sun4u_irq_disable,
        .irq_eoi                = sun4u_irq_eoi,
        .irq_set_affinity       = sun4u_set_affinity,
+       .flags                  = IRQCHIP_EOI_IF_HANDLED,
 };
 
 static struct irq_chip sun4v_irq = {
@@ -513,6 +469,7 @@ static struct irq_chip sun4v_irq = {
        .irq_disable            = sun4v_irq_disable,
        .irq_eoi                = sun4v_irq_eoi,
        .irq_set_affinity       = sun4v_set_affinity,
+       .flags                  = IRQCHIP_EOI_IF_HANDLED,
 };
 
 static struct irq_chip sun4v_virq = {
@@ -521,30 +478,28 @@ static struct irq_chip sun4v_virq = {
        .irq_disable            = sun4v_virq_disable,
        .irq_eoi                = sun4v_virq_eoi,
        .irq_set_affinity       = sun4v_virt_set_affinity,
+       .flags                  = IRQCHIP_EOI_IF_HANDLED,
 };
 
-static void pre_flow_handler(unsigned int irq, struct irq_desc *desc)
+static void pre_flow_handler(struct irq_data *d)
 {
-       struct irq_handler_data *handler_data = get_irq_data(irq);
-       unsigned int ino = irq_table[irq].dev_ino;
+       struct irq_handler_data *handler_data = irq_data_get_irq_handler_data(d);
+       unsigned int ino = irq_table[d->irq].dev_ino;
 
        handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2);
-
-       handle_fasteoi_irq(irq, desc);
 }
 
 void irq_install_pre_handler(int irq,
                             void (*func)(unsigned int, void *, void *),
                             void *arg1, void *arg2)
 {
-       struct irq_handler_data *handler_data = get_irq_data(irq);
-       struct irq_desc *desc = irq_desc + irq;
+       struct irq_handler_data *handler_data = irq_get_handler_data(irq);
 
        handler_data->pre_handler = func;
        handler_data->arg1 = arg1;
        handler_data->arg2 = arg2;
 
-       desc->handle_irq = pre_flow_handler;
+       __irq_set_preflow_handler(irq, pre_flow_handler);
 }
 
 unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
@@ -562,13 +517,11 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
        if (!irq) {
                irq = irq_alloc(0, ino);
                bucket_set_irq(__pa(bucket), irq);
-               set_irq_chip_and_handler_name(irq,
-                                             &sun4u_irq,
-                                             handle_fasteoi_irq,
-                                             "IVEC");
+               irq_set_chip_and_handler_name(irq, &sun4u_irq,
+                                             handle_fasteoi_irq, "IVEC");
        }
 
-       handler_data = get_irq_data(irq);
+       handler_data = irq_get_handler_data(irq);
        if (unlikely(handler_data))
                goto out;
 
@@ -577,7 +530,7 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
                prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
                prom_halt();
        }
-       set_irq_data(irq, handler_data);
+       irq_set_handler_data(irq, handler_data);
 
        handler_data->imap  = imap;
        handler_data->iclr  = iclr;
@@ -600,12 +553,11 @@ static unsigned int sun4v_build_common(unsigned long sysino,
        if (!irq) {
                irq = irq_alloc(0, sysino);
                bucket_set_irq(__pa(bucket), irq);
-               set_irq_chip_and_handler_name(irq, chip,
-                                             handle_fasteoi_irq,
+               irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq,
                                              "IVEC");
        }
 
-       handler_data = get_irq_data(irq);
+       handler_data = irq_get_handler_data(irq);
        if (unlikely(handler_data))
                goto out;
 
@@ -614,7 +566,7 @@ static unsigned int sun4v_build_common(unsigned long sysino,
                prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
                prom_halt();
        }
-       set_irq_data(irq, handler_data);
+       irq_set_handler_data(irq, handler_data);
 
        /* Catch accidental accesses to these things.  IMAP/ICLR handling
         * is done by hypervisor calls on sun4v platforms, not by direct
@@ -639,7 +591,6 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
        struct irq_handler_data *handler_data;
        unsigned long hv_err, cookie;
        struct ino_bucket *bucket;
-       struct irq_desc *desc;
        unsigned int irq;
 
        bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
@@ -660,8 +611,7 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
        irq = irq_alloc(devhandle, devino);
        bucket_set_irq(__pa(bucket), irq);
 
-       set_irq_chip_and_handler_name(irq, &sun4v_virq,
-                                     handle_fasteoi_irq,
+       irq_set_chip_and_handler_name(irq, &sun4v_virq, handle_fasteoi_irq,
                                      "IVEC");
 
        handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
@@ -672,10 +622,8 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
         * especially wrt. locking, we do not let request_irq() enable
         * the interrupt.
         */
-       desc = irq_desc + irq;
-       desc->status |= IRQ_NOAUTOEN;
-
-       set_irq_data(irq, handler_data);
+       irq_set_status_flags(irq, IRQ_NOAUTOEN);
+       irq_set_handler_data(irq, handler_data);
 
        /* Catch accidental accesses to these things.  IMAP/ICLR handling
         * is done by hypervisor calls on sun4v platforms, not by direct
@@ -734,7 +682,6 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
        orig_sp = set_hardirq_stack();
 
        while (bucket_pa) {
-               struct irq_desc *desc;
                unsigned long next_pa;
                unsigned int irq;
 
@@ -742,10 +689,7 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
                irq = bucket_get_irq(bucket_pa);
                bucket_clear_chain_pa(bucket_pa);
 
-               desc = irq_desc + irq;
-
-               if (!(desc->status & IRQ_DISABLED))
-                       desc->handle_irq(irq, desc);
+               generic_handle_irq(irq);
 
                bucket_pa = next_pa;
        }
@@ -788,19 +732,18 @@ void fixup_irqs(void)
        unsigned int irq;
 
        for (irq = 0; irq < NR_IRQS; irq++) {
+               struct irq_desc *desc = irq_to_desc(irq);
+               struct irq_data *data = irq_desc_get_irq_data(desc);
                unsigned long flags;
 
-               raw_spin_lock_irqsave(&irq_desc[irq].lock, flags);
-               if (irq_desc[irq].action &&
-                   !(irq_desc[irq].status & IRQ_PER_CPU)) {
-                       struct irq_data *data = irq_get_irq_data(irq);
-
+               raw_spin_lock_irqsave(&desc->lock, flags);
+               if (desc->action && !irqd_is_per_cpu(data)) {
                        if (data->chip->irq_set_affinity)
                                data->chip->irq_set_affinity(data,
-                                                            data->affinity,
-                                                            false);
+                                                            data->affinity,
+                                                            false);
                }
-               raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
        }
 
        tick_ops->disable_irq();
@@ -1038,5 +981,5 @@ void __init init_IRQ(void)
                             : "i" (PSTATE_IE)
                             : "g1");
 
-       irq_desc[0].action = &timer_irq_action;
+       irq_to_desc(0)->action = &timer_irq_action;
 }
index 44f41e312f73ecde4d0d0c627ca6013abf978b46..713dc91020a623f8ba5c6904810220b256092545 100644 (file)
@@ -1012,7 +1012,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 
 void arch_teardown_msi_irq(unsigned int irq)
 {
-       struct msi_desc *entry = get_irq_msi(irq);
+       struct msi_desc *entry = irq_get_msi_desc(irq);
        struct pci_dev *pdev = entry->dev;
        struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 
index 550e937720e70c3df552f1b68cadd90e39a85cc0..30982e9ab62669ae90ce804c977b3cdb7b20c6e8 100644 (file)
@@ -30,13 +30,10 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie)
 
                err = ops->dequeue_msi(pbm, msiqid, &head, &msi);
                if (likely(err > 0)) {
-                       struct irq_desc *desc;
                        unsigned int irq;
 
                        irq = pbm->msi_irq_table[msi - pbm->msi_first];
-                       desc = irq_desc + irq;
-
-                       desc->handle_irq(irq, desc);
+                       generic_handle_irq(irq);
                }
 
                if (unlikely(err < 0))
@@ -136,8 +133,8 @@ static int sparc64_setup_msi_irq(unsigned int *irq_p,
        if (!*irq_p)
                goto out_err;
 
-       set_irq_chip_and_handler_name(*irq_p, &msi_irq,
-                                     handle_simple_irq, "MSI");
+       irq_set_chip_and_handler_name(*irq_p, &msi_irq, handle_simple_irq,
+                                     "MSI");
 
        err = alloc_msi(pbm);
        if (unlikely(err < 0))
@@ -163,7 +160,7 @@ static int sparc64_setup_msi_irq(unsigned int *irq_p,
        }
        msg.data = msi;
 
-       set_irq_msi(*irq_p, entry);
+       irq_set_msi_desc(*irq_p, entry);
        write_msi_msg(*irq_p, &msg);
 
        return 0;
@@ -172,7 +169,7 @@ out_msi_free:
        free_msi(pbm, msi);
 
 out_irq_free:
-       set_irq_chip(*irq_p, NULL);
+       irq_set_chip(*irq_p, NULL);
        irq_free(*irq_p);
        *irq_p = 0;
 
@@ -211,7 +208,7 @@ static void sparc64_teardown_msi_irq(unsigned int irq,
 
        free_msi(pbm, msi_num);
 
-       set_irq_chip(irq, NULL);
+       irq_set_chip(irq, NULL);
        irq_free(irq);
 }
 
index f3b78701c2197d332dc8718c67fa28af5ea86853..5e34a9fee9b392ede27092c2fd14fd13a42b041f 100644 (file)
@@ -12,6 +12,7 @@ config TILE
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
index 0baa7580121fb720246215b86378472f570c68be..aa0134db2dd683e4f2bde38823bcabc931f7d8ef 100644 (file)
@@ -241,14 +241,14 @@ void tile_irq_activate(unsigned int irq, int tile_irq_type)
        irq_flow_handler_t handle = handle_level_irq;
        if (tile_irq_type == TILE_IRQ_PERCPU)
                handle = handle_percpu_irq;
-       set_irq_chip_and_handler(irq, &tile_irq_chip, handle);
+       irq_set_chip_and_handler(irq, &tile_irq_chip, handle);
 
        /*
         * Flag interrupts that are hardware-cleared so that ack()
         * won't clear them.
         */
        if (tile_irq_type == TILE_IRQ_HW_CLEAR)
-               set_irq_chip_data(irq, (void *)IS_HW_CLEARED);
+               irq_set_chip_data(irq, (void *)IS_HW_CLEARED);
 }
 EXPORT_SYMBOL(tile_irq_activate);
 
@@ -262,47 +262,6 @@ void ack_bad_irq(unsigned int irq)
  * Generic, controller-independent functions:
  */
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-       int i = *(loff_t *) v, j;
-       struct irqaction *action;
-       unsigned long flags;
-
-       if (i == 0) {
-               seq_printf(p, "           ");
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "CPU%-8d", j);
-               seq_putc(p, '\n');
-       }
-
-       if (i < NR_IRQS) {
-               struct irq_desc *desc = irq_to_desc(i);
-
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               action = desc->action;
-               if (!action)
-                       goto skip;
-               seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-               seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
-               seq_printf(p, "  %s", action->name);
-
-               for (action = action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-skip:
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       }
-       return 0;
-}
-
 #if CHIP_HAS_IPI()
 int create_irq(void)
 {
index 4a36db45fb3dae11d16b4618118558b09e45a205..04e024919b2b5afe3f7a72b1bd77b947bd788753 100644 (file)
@@ -11,6 +11,7 @@ config UNICORE32
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
        select GENERIC_HARDIRQS_NO_DEPRECATED
+       select GENERIC_IRQ_SHOW
        select ARCH_WANT_FRAME_POINTERS
        help
          UniCore-32 is 32-bit Instruction Set Architecture,
index b23624cf30624acda1df7560a015813d49509465..2aa30a364bbe426e0749a758e26b11c000be0428 100644 (file)
@@ -321,24 +321,24 @@ void __init init_IRQ(void)
        writel(1, INTC_ICCR);
 
        for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
-               set_irq_chip(irq, &puv3_low_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip(irq, &puv3_low_gpio_chip);
+               irq_set_handler(irq, handle_edge_irq);
                irq_modify_status(irq,
                        IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
                        0);
        }
 
        for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
-               set_irq_chip(irq, &puv3_normal_chip);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip(irq, &puv3_normal_chip);
+               irq_set_handler(irq, handle_level_irq);
                irq_modify_status(irq,
                        IRQ_NOREQUEST | IRQ_NOAUTOEN,
                        IRQ_NOPROBE);
        }
 
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
-               set_irq_chip(irq, &puv3_high_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip(irq, &puv3_high_gpio_chip);
+               irq_set_handler(irq, handle_edge_irq);
                irq_modify_status(irq,
                        IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
                        0);
@@ -347,56 +347,14 @@ void __init init_IRQ(void)
        /*
         * Install handler for GPIO 0-27 edge detect interrupts
         */
-       set_irq_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
-       set_irq_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
+       irq_set_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
+       irq_set_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
 
 #ifdef CONFIG_PUV3_GPIO
        puv3_init_gpio();
 #endif
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-       int i = *(loff_t *) v, cpu;
-       struct irq_desc *desc;
-       struct irqaction *action;
-       unsigned long flags;
-
-       if (i == 0) {
-               char cpuname[12];
-
-               seq_printf(p, "    ");
-               for_each_present_cpu(cpu) {
-                       sprintf(cpuname, "CPU%d", cpu);
-                       seq_printf(p, " %10s", cpuname);
-               }
-               seq_putc(p, '\n');
-       }
-
-       if (i < nr_irqs) {
-               desc = irq_to_desc(i);
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               action = desc->action;
-               if (!action)
-                       goto unlock;
-
-               seq_printf(p, "%3d: ", i);
-               for_each_present_cpu(cpu)
-                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-               seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
-               seq_printf(p, "  %s", action->name);
-               for (action = action->next; action; action = action->next)
-                       seq_printf(p, ", %s", action->name);
-
-               seq_putc(p, '\n');
-unlock:
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       } else if (i == nr_irqs) {
-               seq_printf(p, "Error in interrupt!\n");
-       }
-       return 0;
-}
-
 /*
  * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
index adcf794b22e208f8fa88847b06b466e3e1c88c75..be6d9e365a800a8569fb4915fccbfc50b0793a09 100644 (file)
@@ -1612,6 +1612,7 @@ _zero_cipher_left_encrypt:
         movdqa SHUF_MASK(%rip), %xmm10
        PSHUFB_XMM %xmm10, %xmm0
 
+
        ENCRYPT_SINGLE_BLOCK    %xmm0, %xmm1        # Encrypt(K, Yn)
        sub $16, %r11
        add %r13, %r11
@@ -1634,7 +1635,9 @@ _zero_cipher_left_encrypt:
        # GHASH computation for the last <16 byte block
        sub     %r13, %r11
        add     $16, %r11
-       PSHUFB_XMM %xmm10, %xmm1
+
+       movdqa SHUF_MASK(%rip), %xmm10
+       PSHUFB_XMM %xmm10, %xmm0
 
        # shuffle xmm0 back to output as ciphertext
 
index e0e6340c8dad35be4b4c922b96c44300ea301879..2577613fb32b04ea65893f5a838bac0f4b317496 100644 (file)
@@ -828,9 +828,15 @@ static int rfc4106_init(struct crypto_tfm *tfm)
        struct cryptd_aead *cryptd_tfm;
        struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *)
                PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
+       struct crypto_aead *cryptd_child;
+       struct aesni_rfc4106_gcm_ctx *child_ctx;
        cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0);
        if (IS_ERR(cryptd_tfm))
                return PTR_ERR(cryptd_tfm);
+
+       cryptd_child = cryptd_aead_child(cryptd_tfm);
+       child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child);
+       memcpy(child_ctx, ctx, sizeof(*ctx));
        ctx->cryptd_tfm = cryptd_tfm;
        tfm->crt_aead.reqsize = sizeof(struct aead_request)
                + crypto_aead_reqsize(&cryptd_tfm->base);
@@ -923,6 +929,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
        int ret = 0;
        struct crypto_tfm *tfm = crypto_aead_tfm(parent);
        struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
+       struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+       struct aesni_rfc4106_gcm_ctx *child_ctx =
+                                 aesni_rfc4106_gcm_ctx_get(cryptd_child);
        u8 *new_key_mem = NULL;
 
        if (key_len < 4) {
@@ -966,6 +975,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
                goto exit;
        }
        ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
+       memcpy(child_ctx, ctx, sizeof(*ctx));
 exit:
        kfree(new_key_mem);
        return ret;
@@ -997,7 +1007,6 @@ static int rfc4106_encrypt(struct aead_request *req)
        int ret;
        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
        struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-       struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
        if (!irq_fpu_usable()) {
                struct aead_request *cryptd_req =
@@ -1006,6 +1015,7 @@ static int rfc4106_encrypt(struct aead_request *req)
                aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
                return crypto_aead_encrypt(cryptd_req);
        } else {
+               struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
                kernel_fpu_begin();
                ret = cryptd_child->base.crt_aead.encrypt(req);
                kernel_fpu_end();
@@ -1018,7 +1028,6 @@ static int rfc4106_decrypt(struct aead_request *req)
        int ret;
        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
        struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-       struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
        if (!irq_fpu_usable()) {
                struct aead_request *cryptd_req =
@@ -1027,6 +1036,7 @@ static int rfc4106_decrypt(struct aead_request *req)
                aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
                return crypto_aead_decrypt(cryptd_req);
        } else {
+               struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
                kernel_fpu_begin();
                ret = cryptd_child->base.crt_aead.decrypt(req);
                kernel_fpu_end();
index a09e1f052d84b198bdc2d5cf9da0807bb0585116..d475b4398d8b858cadd87ad36514b79465dc795c 100644 (file)
@@ -45,7 +45,7 @@
 #include <linux/stringify.h>
 
 #ifdef CONFIG_SMP
-#define __percpu_arg(x)                "%%"__stringify(__percpu_seg)":%P" #x
+#define __percpu_prefix                "%%"__stringify(__percpu_seg)":"
 #define __my_cpu_offset                percpu_read(this_cpu_off)
 
 /*
        (typeof(*(ptr)) __kernel __force *)tcp_ptr__;   \
 })
 #else
-#define __percpu_arg(x)                "%P" #x
+#define __percpu_prefix                ""
 #endif
 
+#define __percpu_arg(x)                __percpu_prefix "%P" #x
+
 /*
  * Initialized pointers to per-cpu variables needed for the boot
  * processor need to use these macros to get the proper address
@@ -516,11 +518,11 @@ do {                                                                      \
        typeof(o2) __n2 = n2;                                           \
        typeof(o2) __dummy;                                             \
        alternative_io("call this_cpu_cmpxchg16b_emu\n\t" P6_NOP4,      \
-                      "cmpxchg16b %%gs:(%%rsi)\n\tsetz %0\n\t",        \
+                      "cmpxchg16b " __percpu_prefix "(%%rsi)\n\tsetz %0\n\t",  \
                       X86_FEATURE_CX16,                                \
                       ASM_OUTPUT2("=a"(__ret), "=d"(__dummy)),         \
                       "S" (&pcp1), "b"(__n1), "c"(__n2),               \
-                      "a"(__o1), "d"(__o2));                           \
+                      "a"(__o1), "d"(__o2) : "memory");                \
        __ret;                                                          \
 })
 
index 3e8b08a6de2bf9f3992752d04639fbe7601bd832..1e572c507d06c2ff4d8cb00deee4ac624d7e6f69 100644 (file)
 #include <asm/frame.h>
 #include <asm/dwarf2.h>
 
+#ifdef CONFIG_SMP
+#define SEG_PREFIX %gs:
+#else
+#define SEG_PREFIX
+#endif
+
 .text
 
 /*
@@ -37,13 +43,13 @@ this_cpu_cmpxchg16b_emu:
        pushf
        cli
 
-       cmpq %gs:(%rsi), %rax
+       cmpq SEG_PREFIX(%rsi), %rax
        jne not_same
-       cmpq %gs:8(%rsi), %rdx
+       cmpq SEG_PREFIX 8(%rsi), %rdx
        jne not_same
 
-       movq %rbx, %gs:(%rsi)
-       movq %rcx, %gs:8(%rsi)
+       movq %rbx, SEG_PREFIX(%rsi)
+       movq %rcx, SEG_PREFIX 8(%rsi)
 
        popf
        mov $1, %al
index 99513642a0e6b324bc7b148fd7160222d043c87e..ab81fb271760ff8f666512944b3a54dec155963d 100644 (file)
@@ -72,9 +72,9 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "can't fetch device resource info\n");
                return -EIO;
        }
-       if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
+       if (strcmp(pdev->name, "cs5535-pms") == 0)
                pms_base = res->start;
-       else if (strcmp(pdev->name, "olpc-xo1-ac-acpi") == 0)
+       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
                acpi_base = res->start;
 
        /* If we have both addresses, we can override the poweroff hook */
@@ -90,9 +90,9 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)
 {
        mfd_cell_disable(pdev);
 
-       if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
+       if (strcmp(pdev->name, "cs5535-pms") == 0)
                pms_base = 0;
-       else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0)
+       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
                acpi_base = 0;
 
        pm_power_off = NULL;
@@ -101,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)
 
 static struct platform_driver cs5535_pms_drv = {
        .driver = {
-               .name = "olpc-xo1-pms",
+               .name = "cs5535-pms",
                .owner = THIS_MODULE,
        },
        .probe = olpc_xo1_probe,
@@ -110,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = {
 
 static struct platform_driver cs5535_acpi_drv = {
        .driver = {
-               .name = "olpc-xo1-acpi",
+               .name = "olpc-xo1-pm-acpi",
                .owner = THIS_MODULE,
        },
        .probe = olpc_xo1_probe,
@@ -121,22 +121,21 @@ static int __init olpc_xo1_init(void)
 {
        int r;
 
-       r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms");
+       r = platform_driver_register(&cs5535_pms_drv);
        if (r)
                return r;
 
-       r = mfd_shared_platform_driver_register(&cs5535_acpi_drv,
-                       "cs5535-acpi");
+       r = platform_driver_register(&cs5535_acpi_drv);
        if (r)
-               mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
+               platform_driver_unregister(&cs5535_pms_drv);
 
        return r;
 }
 
 static void __exit olpc_xo1_exit(void)
 {
-       mfd_shared_platform_driver_unregister(&cs5535_acpi_drv);
-       mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
+       platform_driver_unregister(&cs5535_acpi_drv);
+       platform_driver_unregister(&cs5535_pms_drv);
 }
 
 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
index 215a3ce6106820d029c38d0216c7ea4384f20a0b..141eb0de8b06f82d2fb9f42eb2e2af18d3969f0e 100644 (file)
@@ -497,7 +497,7 @@ static bool alloc_p2m(unsigned long pfn)
        return true;
 }
 
-bool __early_alloc_p2m(unsigned long pfn)
+static bool __init __early_alloc_p2m(unsigned long pfn)
 {
        unsigned topidx, mididx, idx;
 
@@ -530,7 +530,7 @@ bool __early_alloc_p2m(unsigned long pfn)
        }
        return idx != 0;
 }
-unsigned long set_phys_range_identity(unsigned long pfn_s,
+unsigned long __init set_phys_range_identity(unsigned long pfn_s,
                                      unsigned long pfn_e)
 {
        unsigned long pfn;
@@ -671,7 +671,9 @@ int m2p_add_override(unsigned long mfn, struct page *page)
        page->private = mfn;
        page->index = pfn_to_mfn(pfn);
 
-       __set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
+       if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
+               return -ENOMEM;
+
        if (!PageHighMem(page))
                /* Just zap old mapping for now */
                pte_clear(&init_mm, address, ptep);
@@ -709,7 +711,7 @@ int m2p_remove_override(struct page *page)
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
-       __set_phys_to_machine(pfn, page->index);
+       set_phys_to_machine(pfn, page->index);
 
        if (!PageHighMem(page))
                set_pte_at(&init_mm, address, ptep,
index a18e497f1c3ca92722fd5f8bc8e36bb774d7b982..31e9e10f657eb6dda1ad9c58171ff38a523a1c34 100644 (file)
@@ -824,11 +824,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->backlight->props.brightness =
                                acpi_video_get_brightness(device->backlight);
 
-               result = sysfs_create_link(&device->backlight->dev.kobj,
-                                          &device->dev->dev.kobj, "device");
-               if (result)
-                       printk(KERN_ERR PREFIX "Create sysfs link\n");
-
                device->cooling_dev = thermal_cooling_device_register("LCD",
                                        device->dev, &video_cooling_ops);
                if (IS_ERR(device->cooling_dev)) {
@@ -1381,7 +1376,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
                       "Cant remove video notify handler\n");
        }
        if (device->backlight) {
-               sysfs_remove_link(&device->backlight->dev.kobj, "device");
                backlight_device_unregister(device->backlight);
                device->backlight = NULL;
        }
index 5253b271b3fe7a39cdbcbe01ee1f9f60dc421ae4..f6b3f995f58a3c91c93a8ff56b478572e466962f 100644 (file)
@@ -167,7 +167,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq)
-               set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 
        /* Setup expansion bus chip selects */
        *data->cs0_cfg = data->cs0_bits;
index baeaf938d55bcad895c91dd673620dd1c928eabb..1b9d10d9c5d912b8306b9cd73d30e5d521cfd6a7 100644 (file)
@@ -60,10 +60,10 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
        struct rb532_cf_info *info = ah->private_data;
 
        if (gpio_get_value(info->gpio_line)) {
-               set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
+               irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
                ata_sff_interrupt(info->irq, dev_instance);
        } else {
-               set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+               irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
        }
 
        return IRQ_HANDLED;
index 35658f445fca4a494071438ad0f4788bab936231..9bf13988f1a2f813ff20d6d65d5c9dd22426579e 100644 (file)
@@ -193,7 +193,7 @@ static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev,
        u64 *cfg_offset);
 static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
        unsigned long *memory_bar);
-
+static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag);
 
 /* performant mode helper functions */
 static void  calc_bucket_map(int *bucket, int num_buckets, int nsgs,
@@ -231,7 +231,7 @@ static const struct block_device_operations cciss_fops = {
  */
 static void set_performant_mode(ctlr_info_t *h, CommandList_struct *c)
 {
-       if (likely(h->transMethod == CFGTBL_Trans_Performant))
+       if (likely(h->transMethod & CFGTBL_Trans_Performant))
                c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
 }
 
@@ -556,6 +556,44 @@ static void __devinit cciss_procinit(ctlr_info_t *h)
 #define to_hba(n) container_of(n, struct ctlr_info, dev)
 #define to_drv(n) container_of(n, drive_info_struct, dev)
 
+/* List of controllers which cannot be reset on kexec with reset_devices */
+static u32 unresettable_controller[] = {
+       0x324a103C, /* Smart Array P712m */
+       0x324b103C, /* SmartArray P711m */
+       0x3223103C, /* Smart Array P800 */
+       0x3234103C, /* Smart Array P400 */
+       0x3235103C, /* Smart Array P400i */
+       0x3211103C, /* Smart Array E200i */
+       0x3212103C, /* Smart Array E200 */
+       0x3213103C, /* Smart Array E200i */
+       0x3214103C, /* Smart Array E200i */
+       0x3215103C, /* Smart Array E200i */
+       0x3237103C, /* Smart Array E500 */
+       0x323D103C, /* Smart Array P700m */
+       0x409C0E11, /* Smart Array 6400 */
+       0x409D0E11, /* Smart Array 6400 EM */
+};
+
+static int ctlr_is_resettable(struct ctlr_info *h)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
+               if (unresettable_controller[i] == h->board_id)
+                       return 0;
+       return 1;
+}
+
+static ssize_t host_show_resettable(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct ctlr_info *h = to_hba(dev);
+
+       return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
+}
+static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL);
+
 static ssize_t host_store_rescan(struct device *dev,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
@@ -741,6 +779,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL);
 
 static struct attribute *cciss_host_attrs[] = {
        &dev_attr_rescan.attr,
+       &dev_attr_resettable.attr,
        NULL
 };
 
@@ -973,8 +1012,8 @@ static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c)
        temp64.val32.upper = c->ErrDesc.Addr.upper;
        pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
                            c->err_info, (dma_addr_t) temp64.val);
-       pci_free_consistent(h->pdev, sizeof(CommandList_struct),
-                           c, (dma_addr_t) c->busaddr);
+       pci_free_consistent(h->pdev, sizeof(CommandList_struct), c,
+               (dma_addr_t) cciss_tag_discard_error_bits(h, (u32) c->busaddr));
 }
 
 static inline ctlr_info_t *get_host(struct gendisk *disk)
@@ -1490,8 +1529,7 @@ static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
                return -EINVAL;
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
-       ioc = (BIG_IOCTL_Command_struct *)
-           kmalloc(sizeof(*ioc), GFP_KERNEL);
+       ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
        if (!ioc) {
                status = -ENOMEM;
                goto cleanup1;
@@ -2653,6 +2691,10 @@ static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c)
                        c->Request.CDB[0]);
                return_status = IO_NEEDS_RETRY;
                break;
+       case CMD_UNABORTABLE:
+               dev_warn(&h->pdev->dev, "cmd unabortable\n");
+               return_status = IO_ERROR;
+               break;
        default:
                dev_warn(&h->pdev->dev, "cmd 0x%02x returned "
                       "unknown status %x\n", c->Request.CDB[0],
@@ -3103,6 +3145,13 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
                        (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ?
                                DID_PASSTHROUGH : DID_ERROR);
                break;
+       case CMD_UNABORTABLE:
+               dev_warn(&h->pdev->dev, "cmd %p unabortable\n", cmd);
+               rq->errors = make_status_bytes(SAM_STAT_GOOD,
+                       cmd->err_info->CommandStatus, DRIVER_OK,
+                       cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC ?
+                               DID_PASSTHROUGH : DID_ERROR);
+               break;
        default:
                dev_warn(&h->pdev->dev, "cmd %p returned "
                       "unknown status %x\n", cmd,
@@ -3136,10 +3185,13 @@ static inline u32 cciss_tag_to_index(u32 tag)
        return tag >> DIRECT_LOOKUP_SHIFT;
 }
 
-static inline u32 cciss_tag_discard_error_bits(u32 tag)
+static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag)
 {
-#define CCISS_ERROR_BITS 0x03
-       return tag & ~CCISS_ERROR_BITS;
+#define CCISS_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
+#define CCISS_SIMPLE_ERROR_BITS 0x03
+       if (likely(h->transMethod & CFGTBL_Trans_Performant))
+               return tag & ~CCISS_PERF_ERROR_BITS;
+       return tag & ~CCISS_SIMPLE_ERROR_BITS;
 }
 
 static inline void cciss_mark_tag_indexed(u32 *tag)
@@ -3359,7 +3411,7 @@ static inline u32 next_command(ctlr_info_t *h)
 {
        u32 a;
 
-       if (unlikely(h->transMethod != CFGTBL_Trans_Performant))
+       if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
                return h->access.command_completed(h);
 
        if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
@@ -3394,14 +3446,12 @@ static inline u32 process_indexed_cmd(ctlr_info_t *h, u32 raw_tag)
 /* process completion of a non-indexed command */
 static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag)
 {
-       u32 tag;
        CommandList_struct *c = NULL;
        __u32 busaddr_masked, tag_masked;
 
-       tag = cciss_tag_discard_error_bits(raw_tag);
+       tag_masked = cciss_tag_discard_error_bits(h, raw_tag);
        list_for_each_entry(c, &h->cmpQ, list) {
-               busaddr_masked = cciss_tag_discard_error_bits(c->busaddr);
-               tag_masked = cciss_tag_discard_error_bits(tag);
+               busaddr_masked = cciss_tag_discard_error_bits(h, c->busaddr);
                if (busaddr_masked == tag_masked) {
                        finish_cmd(h, c, raw_tag);
                        return next_command(h);
@@ -3753,7 +3803,8 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
        }
 }
 
-static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
+static __devinit void cciss_enter_performant_mode(ctlr_info_t *h,
+       u32 use_short_tags)
 {
        /* This is a bit complicated.  There are 8 registers on
         * the controller which we write to to tell it 8 different
@@ -3808,7 +3859,7 @@ static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
        writel(0, &h->transtable->RepQCtrAddrHigh32);
        writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
        writel(0, &h->transtable->RepQAddr0High32);
-       writel(CFGTBL_Trans_Performant,
+       writel(CFGTBL_Trans_Performant | use_short_tags,
                        &(h->cfgtable->HostWrite.TransportRequest));
 
        writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
@@ -3855,7 +3906,8 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
        if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
                goto clean_up;
 
-       cciss_enter_performant_mode(h);
+       cciss_enter_performant_mode(h,
+               trans_support & CFGTBL_Trans_use_short_tags);
 
        /* Change the access methods to the performant access methods */
        h->access = SA5_performant_access;
index 579f7491849304cfc311ed9a9e46580013e116b7..554bbd907d144500817a615702ab6155cb7f7243 100644 (file)
@@ -222,6 +222,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
                        h->ctlr, c->busaddr);
 #endif /* CCISS_DEBUG */
          writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+       readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
         h->commands_outstanding++;
         if ( h->commands_outstanding > h->max_outstanding)
                h->max_outstanding = h->commands_outstanding;
index 35463d2f0ee7ce71d80943105f1594eb556141d4..cd441bef031f1a4806ba29df8067c47b050bfae7 100644 (file)
@@ -56,6 +56,7 @@
 
 #define CFGTBL_Trans_Simple     0x00000002l
 #define CFGTBL_Trans_Performant 0x00000004l
+#define CFGTBL_Trans_use_short_tags 0x20000000l
 
 #define CFGTBL_BusType_Ultra2   0x00000001l
 #define CFGTBL_BusType_Ultra3   0x00000002l
index 727d0225b7d049e9f529655c081c513267d248bc..df793803f5ae5c70615df404a442d525442184a0 100644 (file)
@@ -824,13 +824,18 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
                        break;
                        case CMD_UNSOLICITED_ABORT:
                                cmd->result = DID_ABORT << 16;
-                               dev_warn(&h->pdev->dev, "%p aborted do to an "
+                               dev_warn(&h->pdev->dev, "%p aborted due to an "
                                        "unsolicited abort\n", c);
                        break;
                        case CMD_TIMEOUT:
                                cmd->result = DID_TIME_OUT << 16;
                                dev_warn(&h->pdev->dev, "%p timedout\n", c);
                        break;
+                       case CMD_UNABORTABLE:
+                               cmd->result = DID_ERROR << 16;
+                               dev_warn(&h->pdev->dev, "c %p command "
+                                       "unabortable\n", c);
+                       break;
                        default:
                                cmd->result = DID_ERROR << 16;
                                dev_warn(&h->pdev->dev,
@@ -1007,11 +1012,15 @@ cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c)
                break;
                case CMD_UNSOLICITED_ABORT:
                        dev_warn(&h->pdev->dev,
-                               "%p aborted do to an unsolicited abort\n", c);
+                               "%p aborted due to an unsolicited abort\n", c);
                break;
                case CMD_TIMEOUT:
                        dev_warn(&h->pdev->dev, "%p timedout\n", c);
                break;
+               case CMD_UNABORTABLE:
+                       dev_warn(&h->pdev->dev,
+                               "%p unabortable\n", c);
+               break;
                default:
                        dev_warn(&h->pdev->dev,
                                "%p returned unknown status %x\n",
index aca302492ff20a25e65ac645a601dbf51ada2f33..2a1642bc451d6cdaffebc8e9c6bf9ba9fa895077 100644 (file)
@@ -92,7 +92,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
        bio->bi_end_io = drbd_md_io_complete;
        bio->bi_rw = rw;
 
-       if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
+       if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
                bio_endio(bio, -EIO);
        else
                submit_bio(rw, bio);
@@ -176,13 +176,17 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
        struct lc_element *al_ext;
        struct lc_element *tmp;
        unsigned long     al_flags = 0;
+       int wake;
 
        spin_lock_irq(&mdev->al_lock);
        tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
        if (unlikely(tmp != NULL)) {
                struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
                if (test_bit(BME_NO_WRITES, &bm_ext->flags)) {
+                       wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
                        spin_unlock_irq(&mdev->al_lock);
+                       if (wake)
+                               wake_up(&mdev->al_wait);
                        return NULL;
                }
        }
@@ -258,6 +262,33 @@ void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector)
        spin_unlock_irqrestore(&mdev->al_lock, flags);
 }
 
+#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)
+/* Currently BM_BLOCK_SHIFT, BM_EXT_SHIFT and AL_EXTENT_SHIFT
+ * are still coupled, or assume too much about their relation.
+ * Code below will not work if this is violated.
+ * Will be cleaned up with some followup patch.
+ */
+# error FIXME
+#endif
+
+static unsigned int al_extent_to_bm_page(unsigned int al_enr)
+{
+       return al_enr >>
+               /* bit to page */
+               ((PAGE_SHIFT + 3) -
+               /* al extent number to bit */
+                (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT));
+}
+
+static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
+{
+       return rs_enr >>
+               /* bit to page */
+               ((PAGE_SHIFT + 3) -
+               /* al extent number to bit */
+                (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
+}
+
 int
 w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
@@ -285,7 +316,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
         * For now, we must not write the transaction,
         * if we cannot write out the bitmap of the evicted extent. */
        if (mdev->state.conn < C_CONNECTED && evicted != LC_FREE)
-               drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT);
+               drbd_bm_write_page(mdev, al_extent_to_bm_page(evicted));
 
        /* The bitmap write may have failed, causing a state change. */
        if (mdev->state.disk < D_INCONSISTENT) {
@@ -334,7 +365,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
                + mdev->ldev->md.al_offset + mdev->al_tr_pos;
 
        if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE))
-               drbd_chk_io_error(mdev, 1, TRUE);
+               drbd_chk_io_error(mdev, 1, true);
 
        if (++mdev->al_tr_pos >
            div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT))
@@ -511,225 +542,6 @@ cancel:
        return 1;
 }
 
-static void atodb_endio(struct bio *bio, int error)
-{
-       struct drbd_atodb_wait *wc = bio->bi_private;
-       struct drbd_conf *mdev = wc->mdev;
-       struct page *page;
-       int uptodate = bio_flagged(bio, BIO_UPTODATE);
-
-       /* strange behavior of some lower level drivers...
-        * fail the request by clearing the uptodate flag,
-        * but do not return any error?! */
-       if (!error && !uptodate)
-               error = -EIO;
-
-       drbd_chk_io_error(mdev, error, TRUE);
-       if (error && wc->error == 0)
-               wc->error = error;
-
-       if (atomic_dec_and_test(&wc->count))
-               complete(&wc->io_done);
-
-       page = bio->bi_io_vec[0].bv_page;
-       put_page(page);
-       bio_put(bio);
-       mdev->bm_writ_cnt++;
-       put_ldev(mdev);
-}
-
-/* sector to word */
-#define S2W(s) ((s)<<(BM_EXT_SHIFT-BM_BLOCK_SHIFT-LN2_BPL))
-
-/* activity log to on disk bitmap -- prepare bio unless that sector
- * is already covered by previously prepared bios */
-static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
-                                       struct bio **bios,
-                                       unsigned int enr,
-                                       struct drbd_atodb_wait *wc) __must_hold(local)
-{
-       struct bio *bio;
-       struct page *page;
-       sector_t on_disk_sector;
-       unsigned int page_offset = PAGE_SIZE;
-       int offset;
-       int i = 0;
-       int err = -ENOMEM;
-
-       /* We always write aligned, full 4k blocks,
-        * so we can ignore the logical_block_size (for now) */
-       enr &= ~7U;
-       on_disk_sector = enr + mdev->ldev->md.md_offset
-                            + mdev->ldev->md.bm_offset;
-
-       D_ASSERT(!(on_disk_sector & 7U));
-
-       /* Check if that enr is already covered by an already created bio.
-        * Caution, bios[] is not NULL terminated,
-        * but only initialized to all NULL.
-        * For completely scattered activity log,
-        * the last invocation iterates over all bios,
-        * and finds the last NULL entry.
-        */
-       while ((bio = bios[i])) {
-               if (bio->bi_sector == on_disk_sector)
-                       return 0;
-               i++;
-       }
-       /* bios[i] == NULL, the next not yet used slot */
-
-       /* GFP_KERNEL, we are not in the write-out path */
-       bio = bio_alloc(GFP_KERNEL, 1);
-       if (bio == NULL)
-               return -ENOMEM;
-
-       if (i > 0) {
-               const struct bio_vec *prev_bv = bios[i-1]->bi_io_vec;
-               page_offset = prev_bv->bv_offset + prev_bv->bv_len;
-               page = prev_bv->bv_page;
-       }
-       if (page_offset == PAGE_SIZE) {
-               page = alloc_page(__GFP_HIGHMEM);
-               if (page == NULL)
-                       goto out_bio_put;
-               page_offset = 0;
-       } else {
-               get_page(page);
-       }
-
-       offset = S2W(enr);
-       drbd_bm_get_lel(mdev, offset,
-                       min_t(size_t, S2W(8), drbd_bm_words(mdev) - offset),
-                       kmap(page) + page_offset);
-       kunmap(page);
-
-       bio->bi_private = wc;
-       bio->bi_end_io = atodb_endio;
-       bio->bi_bdev = mdev->ldev->md_bdev;
-       bio->bi_sector = on_disk_sector;
-
-       if (bio_add_page(bio, page, 4096, page_offset) != 4096)
-               goto out_put_page;
-
-       atomic_inc(&wc->count);
-       /* we already know that we may do this...
-        * get_ldev_if_state(mdev,D_ATTACHING);
-        * just get the extra reference, so that the local_cnt reflects
-        * the number of pending IO requests DRBD at its backing device.
-        */
-       atomic_inc(&mdev->local_cnt);
-
-       bios[i] = bio;
-
-       return 0;
-
-out_put_page:
-       err = -EINVAL;
-       put_page(page);
-out_bio_put:
-       bio_put(bio);
-       return err;
-}
-
-/**
- * drbd_al_to_on_disk_bm() -  * Writes bitmap parts covered by active AL extents
- * @mdev:      DRBD device.
- *
- * Called when we detach (unconfigure) local storage,
- * or when we go from R_PRIMARY to R_SECONDARY role.
- */
-void drbd_al_to_on_disk_bm(struct drbd_conf *mdev)
-{
-       int i, nr_elements;
-       unsigned int enr;
-       struct bio **bios;
-       struct drbd_atodb_wait wc;
-
-       ERR_IF (!get_ldev_if_state(mdev, D_ATTACHING))
-               return; /* sorry, I don't have any act_log etc... */
-
-       wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-
-       nr_elements = mdev->act_log->nr_elements;
-
-       /* GFP_KERNEL, we are not in anyone's write-out path */
-       bios = kzalloc(sizeof(struct bio *) * nr_elements, GFP_KERNEL);
-       if (!bios)
-               goto submit_one_by_one;
-
-       atomic_set(&wc.count, 0);
-       init_completion(&wc.io_done);
-       wc.mdev = mdev;
-       wc.error = 0;
-
-       for (i = 0; i < nr_elements; i++) {
-               enr = lc_element_by_index(mdev->act_log, i)->lc_number;
-               if (enr == LC_FREE)
-                       continue;
-               /* next statement also does atomic_inc wc.count and local_cnt */
-               if (atodb_prepare_unless_covered(mdev, bios,
-                                               enr/AL_EXT_PER_BM_SECT,
-                                               &wc))
-                       goto free_bios_submit_one_by_one;
-       }
-
-       /* unnecessary optimization? */
-       lc_unlock(mdev->act_log);
-       wake_up(&mdev->al_wait);
-
-       /* all prepared, submit them */
-       for (i = 0; i < nr_elements; i++) {
-               if (bios[i] == NULL)
-                       break;
-               if (FAULT_ACTIVE(mdev, DRBD_FAULT_MD_WR)) {
-                       bios[i]->bi_rw = WRITE;
-                       bio_endio(bios[i], -EIO);
-               } else {
-                       submit_bio(WRITE, bios[i]);
-               }
-       }
-
-       /* always (try to) flush bitmap to stable storage */
-       drbd_md_flush(mdev);
-
-       /* In case we did not submit a single IO do not wait for
-        * them to complete. ( Because we would wait forever here. )
-        *
-        * In case we had IOs and they are already complete, there
-        * is not point in waiting anyways.
-        * Therefore this if () ... */
-       if (atomic_read(&wc.count))
-               wait_for_completion(&wc.io_done);
-
-       put_ldev(mdev);
-
-       kfree(bios);
-       return;
-
- free_bios_submit_one_by_one:
-       /* free everything by calling the endio callback directly. */
-       for (i = 0; i < nr_elements && bios[i]; i++)
-               bio_endio(bios[i], 0);
-
-       kfree(bios);
-
- submit_one_by_one:
-       dev_warn(DEV, "Using the slow drbd_al_to_on_disk_bm()\n");
-
-       for (i = 0; i < mdev->act_log->nr_elements; i++) {
-               enr = lc_element_by_index(mdev->act_log, i)->lc_number;
-               if (enr == LC_FREE)
-                       continue;
-               /* Really slow: if we have al-extents 16..19 active,
-                * sector 4 will be written four times! Synchronous! */
-               drbd_bm_write_sect(mdev, enr/AL_EXT_PER_BM_SECT);
-       }
-
-       lc_unlock(mdev->act_log);
-       wake_up(&mdev->al_wait);
-       put_ldev(mdev);
-}
-
 /**
  * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents
  * @mdev:      DRBD device.
@@ -809,7 +621,7 @@ static int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused
                return 1;
        }
 
-       drbd_bm_write_sect(mdev, udw->enr);
+       drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr));
        put_ldev(mdev);
 
        kfree(udw);
@@ -889,7 +701,6 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
                                dev_warn(DEV, "Kicking resync_lru element enr=%u "
                                     "out with rs_failed=%d\n",
                                     ext->lce.lc_number, ext->rs_failed);
-                               set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
                        }
                        ext->rs_left = rs_left;
                        ext->rs_failed = success ? 0 : count;
@@ -908,7 +719,6 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
                                drbd_queue_work_front(&mdev->data.work, &udw->w);
                        } else {
                                dev_warn(DEV, "Could not kmalloc an udw\n");
-                               set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
                        }
                }
        } else {
@@ -919,6 +729,22 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
        }
 }
 
+void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go)
+{
+       unsigned long now = jiffies;
+       unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+       int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+       if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+               if (mdev->rs_mark_left[mdev->rs_last_mark] != still_to_go &&
+                   mdev->state.conn != C_PAUSED_SYNC_T &&
+                   mdev->state.conn != C_PAUSED_SYNC_S) {
+                       mdev->rs_mark_time[next] = now;
+                       mdev->rs_mark_left[next] = still_to_go;
+                       mdev->rs_last_mark = next;
+               }
+       }
+}
+
 /* clear the bit corresponding to the piece of storage in question:
  * size byte of data starting from sector.  Only clear a bits of the affected
  * one ore more _aligned_ BM_BLOCK_SIZE blocks.
@@ -936,7 +762,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
        int wake_up = 0;
        unsigned long flags;
 
-       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
                dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
                                (unsigned long long)sector, size);
                return;
@@ -969,21 +795,9 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
         */
        count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
        if (count && get_ldev(mdev)) {
-               unsigned long now = jiffies;
-               unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
-               int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
-               if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
-                       unsigned long tw = drbd_bm_total_weight(mdev);
-                       if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
-                           mdev->state.conn != C_PAUSED_SYNC_T &&
-                           mdev->state.conn != C_PAUSED_SYNC_S) {
-                               mdev->rs_mark_time[next] = now;
-                               mdev->rs_mark_left[next] = tw;
-                               mdev->rs_last_mark = next;
-                       }
-               }
+               drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev));
                spin_lock_irqsave(&mdev->al_lock, flags);
-               drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+               drbd_try_clear_on_disk_bm(mdev, sector, count, true);
                spin_unlock_irqrestore(&mdev->al_lock, flags);
 
                /* just wake_up unconditional now, various lc_chaged(),
@@ -998,27 +812,27 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 /*
  * this is intended to set one request worth of data out of sync.
  * affects at least 1 bit,
- * and at most 1+DRBD_MAX_SEGMENT_SIZE/BM_BLOCK_SIZE bits.
+ * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits.
  *
  * called by tl_clear and drbd_send_dblock (==drbd_make_request).
  * so this can be _any_ process.
  */
-void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
+int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
                            const char *file, const unsigned int line)
 {
        unsigned long sbnr, ebnr, lbnr, flags;
        sector_t esector, nr_sectors;
-       unsigned int enr, count;
+       unsigned int enr, count = 0;
        struct lc_element *e;
 
-       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
                dev_err(DEV, "sector: %llus, size: %d\n",
                        (unsigned long long)sector, size);
-               return;
+               return 0;
        }
 
        if (!get_ldev(mdev))
-               return; /* no disk, no metadata, no bitmap to set bits in */
+               return 0; /* no disk, no metadata, no bitmap to set bits in */
 
        nr_sectors = drbd_get_capacity(mdev->this_bdev);
        esector = sector + (size >> 9) - 1;
@@ -1048,6 +862,8 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 
 out:
        put_ldev(mdev);
+
+       return count;
 }
 
 static
@@ -1128,7 +944,10 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
        unsigned int enr = BM_SECT_TO_EXT(sector);
        struct bm_extent *bm_ext;
        int i, sig;
+       int sa = 200; /* Step aside 200 times, then grab the extent and let app-IO wait.
+                        200 times -> 20 seconds. */
 
+retry:
        sig = wait_event_interruptible(mdev->al_wait,
                        (bm_ext = _bme_get(mdev, enr)));
        if (sig)
@@ -1139,16 +958,25 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 
        for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
                sig = wait_event_interruptible(mdev->al_wait,
-                               !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i));
-               if (sig) {
+                                              !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i) ||
+                                              test_bit(BME_PRIORITY, &bm_ext->flags));
+
+               if (sig || (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)) {
                        spin_lock_irq(&mdev->al_lock);
                        if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
-                               clear_bit(BME_NO_WRITES, &bm_ext->flags);
+                               bm_ext->flags = 0; /* clears BME_NO_WRITES and eventually BME_PRIORITY */
                                mdev->resync_locked--;
                                wake_up(&mdev->al_wait);
                        }
                        spin_unlock_irq(&mdev->al_lock);
-                       return -EINTR;
+                       if (sig)
+                               return -EINTR;
+                       if (schedule_timeout_interruptible(HZ/10))
+                               return -EINTR;
+                       if (sa && --sa == 0)
+                               dev_warn(DEV,"drbd_rs_begin_io() stepped aside for 20sec."
+                                        "Resync stalled?\n");
+                       goto retry;
                }
        }
        set_bit(BME_LOCKED, &bm_ext->flags);
@@ -1291,8 +1119,7 @@ void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector)
        }
 
        if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
-               clear_bit(BME_LOCKED, &bm_ext->flags);
-               clear_bit(BME_NO_WRITES, &bm_ext->flags);
+               bm_ext->flags = 0; /* clear BME_LOCKED, BME_NO_WRITES and BME_PRIORITY */
                mdev->resync_locked--;
                wake_up(&mdev->al_wait);
        }
@@ -1383,7 +1210,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
        sector_t esector, nr_sectors;
        int wake_up = 0;
 
-       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
                dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
                                (unsigned long long)sector, size);
                return;
@@ -1420,7 +1247,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
                mdev->rs_failed += count;
 
                if (get_ldev(mdev)) {
-                       drbd_try_clear_on_disk_bm(mdev, sector, count, FALSE);
+                       drbd_try_clear_on_disk_bm(mdev, sector, count, false);
                        put_ldev(mdev);
                }
 
index 0645ca829a94163c57f4ee5ac43e96aaa344870d..76210ba401ac4d3e8871c4eac99336aa67d899cd 100644 (file)
 #include <linux/drbd.h>
 #include <linux/slab.h>
 #include <asm/kmap_types.h>
+
 #include "drbd_int.h"
 
+
 /* OPAQUE outside this file!
  * interface defined in drbd_int.h
 
  * convention:
  * function name drbd_bm_... => used elsewhere, "public".
  * function name      bm_... => internal to implementation, "private".
+ */
 
- * Note that since find_first_bit returns int, at the current granularity of
- * the bitmap (4KB per byte), this implementation "only" supports up to
- * 1<<(32+12) == 16 TB...
+
+/*
+ * LIMITATIONS:
+ * We want to support >= peta byte of backend storage, while for now still using
+ * a granularity of one bit per 4KiB of storage.
+ * 1 << 50             bytes backend storage (1 PiB)
+ * 1 << (50 - 12)      bits needed
+ *     38 --> we need u64 to index and count bits
+ * 1 << (38 - 3)       bitmap bytes needed
+ *     35 --> we still need u64 to index and count bytes
+ *                     (that's 32 GiB of bitmap for 1 PiB storage)
+ * 1 << (35 - 2)       32bit longs needed
+ *     33 --> we'd even need u64 to index and count 32bit long words.
+ * 1 << (35 - 3)       64bit longs needed
+ *     32 --> we could get away with a 32bit unsigned int to index and count
+ *     64bit long words, but I rather stay with unsigned long for now.
+ *     We probably should neither count nor point to bytes or long words
+ *     directly, but either by bitnumber, or by page index and offset.
+ * 1 << (35 - 12)
+ *     22 --> we need that much 4KiB pages of bitmap.
+ *     1 << (22 + 3) --> on a 64bit arch,
+ *     we need 32 MiB to store the array of page pointers.
+ *
+ * Because I'm lazy, and because the resulting patch was too large, too ugly
+ * and still incomplete, on 32bit we still "only" support 16 TiB (minus some),
+ * (1 << 32) bits * 4k storage.
+ *
+
+ * bitmap storage and IO:
+ *     Bitmap is stored little endian on disk, and is kept little endian in
+ *     core memory. Currently we still hold the full bitmap in core as long
+ *     as we are "attached" to a local disk, which at 32 GiB for 1PiB storage
+ *     seems excessive.
+ *
+ *     We plan to reduce the amount of in-core bitmap pages by pageing them in
+ *     and out against their on-disk location as necessary, but need to make
+ *     sure we don't cause too much meta data IO, and must not deadlock in
+ *     tight memory situations. This needs some more work.
  */
 
 /*
 struct drbd_bitmap {
        struct page **bm_pages;
        spinlock_t bm_lock;
-       /* WARNING unsigned long bm_*:
-        * 32bit number of bit offset is just enough for 512 MB bitmap.
-        * it will blow up if we make the bitmap bigger...
-        * not that it makes much sense to have a bitmap that large,
-        * rather change the granularity to 16k or 64k or something.
-        * (that implies other problems, however...)
-        */
+
+       /* see LIMITATIONS: above */
+
        unsigned long bm_set;       /* nr of set bits; THINK maybe atomic_t? */
        unsigned long bm_bits;
        size_t   bm_words;
@@ -69,29 +103,18 @@ struct drbd_bitmap {
        sector_t bm_dev_capacity;
        struct mutex bm_change; /* serializes resize operations */
 
-       atomic_t bm_async_io;
-       wait_queue_head_t bm_io_wait;
+       wait_queue_head_t bm_io_wait; /* used to serialize IO of single pages */
 
-       unsigned long  bm_flags;
+       enum bm_flag bm_flags;
 
        /* debugging aid, in case we are still racy somewhere */
        char          *bm_why;
        struct task_struct *bm_task;
 };
 
-/* definition of bits in bm_flags */
-#define BM_LOCKED       0
-#define BM_MD_IO_ERROR  1
-#define BM_P_VMALLOCED  2
-
 static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
                               unsigned long e, int val, const enum km_type km);
 
-static int bm_is_locked(struct drbd_bitmap *b)
-{
-       return test_bit(BM_LOCKED, &b->bm_flags);
-}
-
 #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__)
 static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func)
 {
@@ -108,7 +131,7 @@ static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func)
            b->bm_task == mdev->worker.task   ? "worker"   : "?");
 }
 
-void drbd_bm_lock(struct drbd_conf *mdev, char *why)
+void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags)
 {
        struct drbd_bitmap *b = mdev->bitmap;
        int trylock_failed;
@@ -131,8 +154,9 @@ void drbd_bm_lock(struct drbd_conf *mdev, char *why)
                    b->bm_task == mdev->worker.task   ? "worker"   : "?");
                mutex_lock(&b->bm_change);
        }
-       if (__test_and_set_bit(BM_LOCKED, &b->bm_flags))
+       if (BM_LOCKED_MASK & b->bm_flags)
                dev_err(DEV, "FIXME bitmap already locked in bm_lock\n");
+       b->bm_flags |= flags & BM_LOCKED_MASK;
 
        b->bm_why  = why;
        b->bm_task = current;
@@ -146,31 +170,137 @@ void drbd_bm_unlock(struct drbd_conf *mdev)
                return;
        }
 
-       if (!__test_and_clear_bit(BM_LOCKED, &mdev->bitmap->bm_flags))
+       if (!(BM_LOCKED_MASK & mdev->bitmap->bm_flags))
                dev_err(DEV, "FIXME bitmap not locked in bm_unlock\n");
 
+       b->bm_flags &= ~BM_LOCKED_MASK;
        b->bm_why  = NULL;
        b->bm_task = NULL;
        mutex_unlock(&b->bm_change);
 }
 
-/* word offset to long pointer */
-static unsigned long *__bm_map_paddr(struct drbd_bitmap *b, unsigned long offset, const enum km_type km)
+/* we store some "meta" info about our pages in page->private */
+/* at a granularity of 4k storage per bitmap bit:
+ * one peta byte storage: 1<<50 byte, 1<<38 * 4k storage blocks
+ *  1<<38 bits,
+ *  1<<23 4k bitmap pages.
+ * Use 24 bits as page index, covers 2 peta byte storage
+ * at a granularity of 4k per bit.
+ * Used to report the failed page idx on io error from the endio handlers.
+ */
+#define BM_PAGE_IDX_MASK       ((1UL<<24)-1)
+/* this page is currently read in, or written back */
+#define BM_PAGE_IO_LOCK                31
+/* if there has been an IO error for this page */
+#define BM_PAGE_IO_ERROR       30
+/* this is to be able to intelligently skip disk IO,
+ * set if bits have been set since last IO. */
+#define BM_PAGE_NEED_WRITEOUT  29
+/* to mark for lazy writeout once syncer cleared all clearable bits,
+ * we if bits have been cleared since last IO. */
+#define BM_PAGE_LAZY_WRITEOUT  28
+
+/* store_page_idx uses non-atomic assingment. It is only used directly after
+ * allocating the page.  All other bm_set_page_* and bm_clear_page_* need to
+ * use atomic bit manipulation, as set_out_of_sync (and therefore bitmap
+ * changes) may happen from various contexts, and wait_on_bit/wake_up_bit
+ * requires it all to be atomic as well. */
+static void bm_store_page_idx(struct page *page, unsigned long idx)
+{
+       BUG_ON(0 != (idx & ~BM_PAGE_IDX_MASK));
+       page_private(page) |= idx;
+}
+
+static unsigned long bm_page_to_idx(struct page *page)
 {
-       struct page *page;
-       unsigned long page_nr;
+       return page_private(page) & BM_PAGE_IDX_MASK;
+}
+
+/* As is very unlikely that the same page is under IO from more than one
+ * context, we can get away with a bit per page and one wait queue per bitmap.
+ */
+static void bm_page_lock_io(struct drbd_conf *mdev, int page_nr)
+{
+       struct drbd_bitmap *b = mdev->bitmap;
+       void *addr = &page_private(b->bm_pages[page_nr]);
+       wait_event(b->bm_io_wait, !test_and_set_bit(BM_PAGE_IO_LOCK, addr));
+}
+
+static void bm_page_unlock_io(struct drbd_conf *mdev, int page_nr)
+{
+       struct drbd_bitmap *b = mdev->bitmap;
+       void *addr = &page_private(b->bm_pages[page_nr]);
+       clear_bit(BM_PAGE_IO_LOCK, addr);
+       smp_mb__after_clear_bit();
+       wake_up(&mdev->bitmap->bm_io_wait);
+}
+
+/* set _before_ submit_io, so it may be reset due to being changed
+ * while this page is in flight... will get submitted later again */
+static void bm_set_page_unchanged(struct page *page)
+{
+       /* use cmpxchg? */
+       clear_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
+       clear_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
 
+static void bm_set_page_need_writeout(struct page *page)
+{
+       set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
+}
+
+static int bm_test_page_unchanged(struct page *page)
+{
+       volatile const unsigned long *addr = &page_private(page);
+       return (*addr & ((1UL<<BM_PAGE_NEED_WRITEOUT)|(1UL<<BM_PAGE_LAZY_WRITEOUT))) == 0;
+}
+
+static void bm_set_page_io_err(struct page *page)
+{
+       set_bit(BM_PAGE_IO_ERROR, &page_private(page));
+}
+
+static void bm_clear_page_io_err(struct page *page)
+{
+       clear_bit(BM_PAGE_IO_ERROR, &page_private(page));
+}
+
+static void bm_set_page_lazy_writeout(struct page *page)
+{
+       set_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
+
+static int bm_test_page_lazy_writeout(struct page *page)
+{
+       return test_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
+
+/* on a 32bit box, this would allow for exactly (2<<38) bits. */
+static unsigned int bm_word_to_page_idx(struct drbd_bitmap *b, unsigned long long_nr)
+{
        /* page_nr = (word*sizeof(long)) >> PAGE_SHIFT; */
-       page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3);
+       unsigned int page_nr = long_nr >> (PAGE_SHIFT - LN2_BPL + 3);
        BUG_ON(page_nr >= b->bm_number_of_pages);
-       page = b->bm_pages[page_nr];
+       return page_nr;
+}
 
+static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr)
+{
+       /* page_nr = (bitnr/8) >> PAGE_SHIFT; */
+       unsigned int page_nr = bitnr >> (PAGE_SHIFT + 3);
+       BUG_ON(page_nr >= b->bm_number_of_pages);
+       return page_nr;
+}
+
+static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx, const enum km_type km)
+{
+       struct page *page = b->bm_pages[idx];
        return (unsigned long *) kmap_atomic(page, km);
 }
 
-static unsigned long * bm_map_paddr(struct drbd_bitmap *b, unsigned long offset)
+static unsigned long *bm_map_pidx(struct drbd_bitmap *b, unsigned int idx)
 {
-       return __bm_map_paddr(b, offset, KM_IRQ1);
+       return __bm_map_pidx(b, idx, KM_IRQ1);
 }
 
 static void __bm_unmap(unsigned long *p_addr, const enum km_type km)
@@ -202,6 +332,7 @@ static void bm_unmap(unsigned long *p_addr)
  * to be able to report device specific.
  */
 
+
 static void bm_free_pages(struct page **pages, unsigned long number)
 {
        unsigned long i;
@@ -269,6 +400,9 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
                                bm_vk_free(new_pages, vmalloced);
                                return NULL;
                        }
+                       /* we want to know which page it is
+                        * from the endio handlers */
+                       bm_store_page_idx(page, i);
                        new_pages[i] = page;
                }
        } else {
@@ -280,9 +414,9 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
        }
 
        if (vmalloced)
-               set_bit(BM_P_VMALLOCED, &b->bm_flags);
+               b->bm_flags |= BM_P_VMALLOCED;
        else
-               clear_bit(BM_P_VMALLOCED, &b->bm_flags);
+               b->bm_flags &= ~BM_P_VMALLOCED;
 
        return new_pages;
 }
@@ -319,7 +453,7 @@ void drbd_bm_cleanup(struct drbd_conf *mdev)
 {
        ERR_IF (!mdev->bitmap) return;
        bm_free_pages(mdev->bitmap->bm_pages, mdev->bitmap->bm_number_of_pages);
-       bm_vk_free(mdev->bitmap->bm_pages, test_bit(BM_P_VMALLOCED, &mdev->bitmap->bm_flags));
+       bm_vk_free(mdev->bitmap->bm_pages, (BM_P_VMALLOCED & mdev->bitmap->bm_flags));
        kfree(mdev->bitmap);
        mdev->bitmap = NULL;
 }
@@ -329,22 +463,39 @@ void drbd_bm_cleanup(struct drbd_conf *mdev)
  * this masks out the remaining bits.
  * Returns the number of bits cleared.
  */
+#define BITS_PER_PAGE          (1UL << (PAGE_SHIFT + 3))
+#define BITS_PER_PAGE_MASK     (BITS_PER_PAGE - 1)
+#define BITS_PER_LONG_MASK     (BITS_PER_LONG - 1)
 static int bm_clear_surplus(struct drbd_bitmap *b)
 {
-       const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1;
-       size_t w = b->bm_bits >> LN2_BPL;
-       int cleared = 0;
+       unsigned long mask;
        unsigned long *p_addr, *bm;
+       int tmp;
+       int cleared = 0;
 
-       p_addr = bm_map_paddr(b, w);
-       bm = p_addr + MLPP(w);
-       if (w < b->bm_words) {
+       /* number of bits modulo bits per page */
+       tmp = (b->bm_bits & BITS_PER_PAGE_MASK);
+       /* mask the used bits of the word containing the last bit */
+       mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1;
+       /* bitmap is always stored little endian,
+        * on disk and in core memory alike */
+       mask = cpu_to_lel(mask);
+
+       p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1);
+       bm = p_addr + (tmp/BITS_PER_LONG);
+       if (mask) {
+               /* If mask != 0, we are not exactly aligned, so bm now points
+                * to the long containing the last bit.
+                * If mask == 0, bm already points to the word immediately
+                * after the last (long word aligned) bit. */
                cleared = hweight_long(*bm & ~mask);
                *bm &= mask;
-               w++; bm++;
+               bm++;
        }
 
-       if (w < b->bm_words) {
+       if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) {
+               /* on a 32bit arch, we may need to zero out
+                * a padding long to align with a 64bit remote */
                cleared += hweight_long(*bm);
                *bm = 0;
        }
@@ -354,66 +505,75 @@ static int bm_clear_surplus(struct drbd_bitmap *b)
 
 static void bm_set_surplus(struct drbd_bitmap *b)
 {
-       const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1;
-       size_t w = b->bm_bits >> LN2_BPL;
+       unsigned long mask;
        unsigned long *p_addr, *bm;
-
-       p_addr = bm_map_paddr(b, w);
-       bm = p_addr + MLPP(w);
-       if (w < b->bm_words) {
+       int tmp;
+
+       /* number of bits modulo bits per page */
+       tmp = (b->bm_bits & BITS_PER_PAGE_MASK);
+       /* mask the used bits of the word containing the last bit */
+       mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1;
+       /* bitmap is always stored little endian,
+        * on disk and in core memory alike */
+       mask = cpu_to_lel(mask);
+
+       p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1);
+       bm = p_addr + (tmp/BITS_PER_LONG);
+       if (mask) {
+               /* If mask != 0, we are not exactly aligned, so bm now points
+                * to the long containing the last bit.
+                * If mask == 0, bm already points to the word immediately
+                * after the last (long word aligned) bit. */
                *bm |= ~mask;
-               bm++; w++;
+               bm++;
        }
 
-       if (w < b->bm_words) {
-               *bm = ~(0UL);
+       if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) {
+               /* on a 32bit arch, we may need to zero out
+                * a padding long to align with a 64bit remote */
+               *bm = ~0UL;
        }
        bm_unmap(p_addr);
 }
 
-static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endian)
+/* you better not modify the bitmap while this is running,
+ * or its results will be stale */
+static unsigned long bm_count_bits(struct drbd_bitmap *b)
 {
-       unsigned long *p_addr, *bm, offset = 0;
+       unsigned long *p_addr;
        unsigned long bits = 0;
-       unsigned long i, do_now;
-
-       while (offset < b->bm_words) {
-               i = do_now = min_t(size_t, b->bm_words-offset, LWPP);
-               p_addr = __bm_map_paddr(b, offset, KM_USER0);
-               bm = p_addr + MLPP(offset);
-               while (i--) {
-#ifndef __LITTLE_ENDIAN
-                       if (swap_endian)
-                               *bm = lel_to_cpu(*bm);
-#endif
-                       bits += hweight_long(*bm++);
-               }
+       unsigned long mask = (1UL << (b->bm_bits & BITS_PER_LONG_MASK)) -1;
+       int idx, i, last_word;
+
+       /* all but last page */
+       for (idx = 0; idx < b->bm_number_of_pages - 1; idx++) {
+               p_addr = __bm_map_pidx(b, idx, KM_USER0);
+               for (i = 0; i < LWPP; i++)
+                       bits += hweight_long(p_addr[i]);
                __bm_unmap(p_addr, KM_USER0);
-               offset += do_now;
                cond_resched();
        }
-
+       /* last (or only) page */
+       last_word = ((b->bm_bits - 1) & BITS_PER_PAGE_MASK) >> LN2_BPL;
+       p_addr = __bm_map_pidx(b, idx, KM_USER0);
+       for (i = 0; i < last_word; i++)
+               bits += hweight_long(p_addr[i]);
+       p_addr[last_word] &= cpu_to_lel(mask);
+       bits += hweight_long(p_addr[last_word]);
+       /* 32bit arch, may have an unused padding long */
+       if (BITS_PER_LONG == 32 && (last_word & 1) == 0)
+               p_addr[last_word+1] = 0;
+       __bm_unmap(p_addr, KM_USER0);
        return bits;
 }
 
-static unsigned long bm_count_bits(struct drbd_bitmap *b)
-{
-       return __bm_count_bits(b, 0);
-}
-
-static unsigned long bm_count_bits_swap_endian(struct drbd_bitmap *b)
-{
-       return __bm_count_bits(b, 1);
-}
-
 /* offset and len in long words.*/
 static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
 {
        unsigned long *p_addr, *bm;
+       unsigned int idx;
        size_t do_now, end;
 
-#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512)
-
        end = offset + len;
 
        if (end > b->bm_words) {
@@ -423,15 +583,16 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
 
        while (offset < end) {
                do_now = min_t(size_t, ALIGN(offset + 1, LWPP), end) - offset;
-               p_addr = bm_map_paddr(b, offset);
+               idx = bm_word_to_page_idx(b, offset);
+               p_addr = bm_map_pidx(b, idx);
                bm = p_addr + MLPP(offset);
                if (bm+do_now > p_addr + LWPP) {
                        printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
                               p_addr, bm, (int)do_now);
-                       break; /* breaks to after catch_oob_access_end() only! */
-               }
-               memset(bm, c, do_now * sizeof(long));
+               } else
+                       memset(bm, c, do_now * sizeof(long));
                bm_unmap(p_addr);
+               bm_set_page_need_writeout(b->bm_pages[idx]);
                offset += do_now;
        }
 }
@@ -447,7 +608,7 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
 int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 {
        struct drbd_bitmap *b = mdev->bitmap;
-       unsigned long bits, words, owords, obits, *p_addr, *bm;
+       unsigned long bits, words, owords, obits;
        unsigned long want, have, onpages; /* number of pages */
        struct page **npages, **opages = NULL;
        int err = 0, growing;
@@ -455,7 +616,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 
        ERR_IF(!b) return -ENOMEM;
 
-       drbd_bm_lock(mdev, "resize");
+       drbd_bm_lock(mdev, "resize", BM_LOCKED_MASK);
 
        dev_info(DEV, "drbd_bm_resize called with capacity == %llu\n",
                        (unsigned long long)capacity);
@@ -463,7 +624,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
        if (capacity == b->bm_dev_capacity)
                goto out;
 
-       opages_vmalloced = test_bit(BM_P_VMALLOCED, &b->bm_flags);
+       opages_vmalloced = (BM_P_VMALLOCED & b->bm_flags);
 
        if (capacity == 0) {
                spin_lock_irq(&b->bm_lock);
@@ -491,18 +652,23 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
        words = ALIGN(bits, 64) >> LN2_BPL;
 
        if (get_ldev(mdev)) {
-               D_ASSERT((u64)bits <= (((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12));
+               u64 bits_on_disk = ((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12;
                put_ldev(mdev);
+               if (bits > bits_on_disk) {
+                       dev_info(DEV, "bits = %lu\n", bits);
+                       dev_info(DEV, "bits_on_disk = %llu\n", bits_on_disk);
+                       err = -ENOSPC;
+                       goto out;
+               }
        }
 
-       /* one extra long to catch off by one errors */
-       want = ALIGN((words+1)*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT;
+       want = ALIGN(words*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT;
        have = b->bm_number_of_pages;
        if (want == have) {
                D_ASSERT(b->bm_pages != NULL);
                npages = b->bm_pages;
        } else {
-               if (FAULT_ACTIVE(mdev, DRBD_FAULT_BM_ALLOC))
+               if (drbd_insert_fault(mdev, DRBD_FAULT_BM_ALLOC))
                        npages = NULL;
                else
                        npages = bm_realloc_pages(b, want);
@@ -542,11 +708,6 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
                bm_free_pages(opages + want, have - want);
        }
 
-       p_addr = bm_map_paddr(b, words);
-       bm = p_addr + MLPP(words);
-       *bm = DRBD_MAGIC;
-       bm_unmap(p_addr);
-
        (void)bm_clear_surplus(b);
 
        spin_unlock_irq(&b->bm_lock);
@@ -554,7 +715,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
                bm_vk_free(opages, opages_vmalloced);
        if (!growing)
                b->bm_set = bm_count_bits(b);
-       dev_info(DEV, "resync bitmap: bits=%lu words=%lu\n", bits, words);
+       dev_info(DEV, "resync bitmap: bits=%lu words=%lu pages=%lu\n", bits, words, want);
 
  out:
        drbd_bm_unlock(mdev);
@@ -624,6 +785,7 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
        struct drbd_bitmap *b = mdev->bitmap;
        unsigned long *p_addr, *bm;
        unsigned long word, bits;
+       unsigned int idx;
        size_t end, do_now;
 
        end = offset + number;
@@ -638,16 +800,18 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
        spin_lock_irq(&b->bm_lock);
        while (offset < end) {
                do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset;
-               p_addr = bm_map_paddr(b, offset);
+               idx = bm_word_to_page_idx(b, offset);
+               p_addr = bm_map_pidx(b, idx);
                bm = p_addr + MLPP(offset);
                offset += do_now;
                while (do_now--) {
                        bits = hweight_long(*bm);
-                       word = *bm | lel_to_cpu(*buffer++);
+                       word = *bm | *buffer++;
                        *bm++ = word;
                        b->bm_set += hweight_long(word) - bits;
                }
                bm_unmap(p_addr);
+               bm_set_page_need_writeout(b->bm_pages[idx]);
        }
        /* with 32bit <-> 64bit cross-platform connect
         * this is only correct for current usage,
@@ -656,7 +820,6 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
         */
        if (end == b->bm_words)
                b->bm_set -= bm_clear_surplus(b);
-
        spin_unlock_irq(&b->bm_lock);
 }
 
@@ -686,11 +849,11 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
        else {
                while (offset < end) {
                        do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset;
-                       p_addr = bm_map_paddr(b, offset);
+                       p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, offset));
                        bm = p_addr + MLPP(offset);
                        offset += do_now;
                        while (do_now--)
-                               *buffer++ = cpu_to_lel(*bm++);
+                               *buffer++ = *bm++;
                        bm_unmap(p_addr);
                }
        }
@@ -724,9 +887,22 @@ void drbd_bm_clear_all(struct drbd_conf *mdev)
        spin_unlock_irq(&b->bm_lock);
 }
 
+struct bm_aio_ctx {
+       struct drbd_conf *mdev;
+       atomic_t in_flight;
+       struct completion done;
+       unsigned flags;
+#define BM_AIO_COPY_PAGES      1
+       int error;
+};
+
+/* bv_page may be a copy, or may be the original */
 static void bm_async_io_complete(struct bio *bio, int error)
 {
-       struct drbd_bitmap *b = bio->bi_private;
+       struct bm_aio_ctx *ctx = bio->bi_private;
+       struct drbd_conf *mdev = ctx->mdev;
+       struct drbd_bitmap *b = mdev->bitmap;
+       unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page);
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
 
@@ -737,38 +913,83 @@ static void bm_async_io_complete(struct bio *bio, int error)
        if (!error && !uptodate)
                error = -EIO;
 
+       if ((ctx->flags & BM_AIO_COPY_PAGES) == 0 &&
+           !bm_test_page_unchanged(b->bm_pages[idx]))
+               dev_warn(DEV, "bitmap page idx %u changed during IO!\n", idx);
+
        if (error) {
-               /* doh. what now?
-                * for now, set all bits, and flag MD_IO_ERROR */
-               __set_bit(BM_MD_IO_ERROR, &b->bm_flags);
+               /* ctx error will hold the completed-last non-zero error code,
+                * in case error codes differ. */
+               ctx->error = error;
+               bm_set_page_io_err(b->bm_pages[idx]);
+               /* Not identical to on disk version of it.
+                * Is BM_PAGE_IO_ERROR enough? */
+               if (__ratelimit(&drbd_ratelimit_state))
+                       dev_err(DEV, "IO ERROR %d on bitmap page idx %u\n",
+                                       error, idx);
+       } else {
+               bm_clear_page_io_err(b->bm_pages[idx]);
+               dynamic_dev_dbg(DEV, "bitmap page idx %u completed\n", idx);
        }
-       if (atomic_dec_and_test(&b->bm_async_io))
-               wake_up(&b->bm_io_wait);
+
+       bm_page_unlock_io(mdev, idx);
+
+       /* FIXME give back to page pool */
+       if (ctx->flags & BM_AIO_COPY_PAGES)
+               put_page(bio->bi_io_vec[0].bv_page);
 
        bio_put(bio);
+
+       if (atomic_dec_and_test(&ctx->in_flight))
+               complete(&ctx->done);
 }
 
-static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int page_nr, int rw) __must_hold(local)
+static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local)
 {
        /* we are process context. we always get a bio */
        struct bio *bio = bio_alloc(GFP_KERNEL, 1);
+       struct drbd_conf *mdev = ctx->mdev;
+       struct drbd_bitmap *b = mdev->bitmap;
+       struct page *page;
        unsigned int len;
+
        sector_t on_disk_sector =
                mdev->ldev->md.md_offset + mdev->ldev->md.bm_offset;
        on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9);
 
        /* this might happen with very small
-        * flexible external meta data device */
+        * flexible external meta data device,
+        * or with PAGE_SIZE > 4k */
        len = min_t(unsigned int, PAGE_SIZE,
                (drbd_md_last_sector(mdev->ldev) - on_disk_sector + 1)<<9);
 
+       /* serialize IO on this page */
+       bm_page_lock_io(mdev, page_nr);
+       /* before memcpy and submit,
+        * so it can be redirtied any time */
+       bm_set_page_unchanged(b->bm_pages[page_nr]);
+
+       if (ctx->flags & BM_AIO_COPY_PAGES) {
+               /* FIXME alloc_page is good enough for now, but actually needs
+                * to use pre-allocated page pool */
+               void *src, *dest;
+               page = alloc_page(__GFP_HIGHMEM|__GFP_WAIT);
+               dest = kmap_atomic(page, KM_USER0);
+               src = kmap_atomic(b->bm_pages[page_nr], KM_USER1);
+               memcpy(dest, src, PAGE_SIZE);
+               kunmap_atomic(src, KM_USER1);
+               kunmap_atomic(dest, KM_USER0);
+               bm_store_page_idx(page, page_nr);
+       } else
+               page = b->bm_pages[page_nr];
+
        bio->bi_bdev = mdev->ldev->md_bdev;
        bio->bi_sector = on_disk_sector;
-       bio_add_page(bio, b->bm_pages[page_nr], len, 0);
-       bio->bi_private = b;
+       bio_add_page(bio, page, len, 0);
+       bio->bi_private = ctx;
        bio->bi_end_io = bm_async_io_complete;
 
-       if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
+       if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
                bio->bi_rw |= rw;
                bio_endio(bio, -EIO);
        } else {
@@ -776,87 +997,84 @@ static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int
        }
 }
 
-# if defined(__LITTLE_ENDIAN)
-       /* nothing to do, on disk == in memory */
-# define bm_cpu_to_lel(x) ((void)0)
-# else
-static void bm_cpu_to_lel(struct drbd_bitmap *b)
-{
-       /* need to cpu_to_lel all the pages ...
-        * this may be optimized by using
-        * cpu_to_lel(-1) == -1 and cpu_to_lel(0) == 0;
-        * the following is still not optimal, but better than nothing */
-       unsigned int i;
-       unsigned long *p_addr, *bm;
-       if (b->bm_set == 0) {
-               /* no page at all; avoid swap if all is 0 */
-               i = b->bm_number_of_pages;
-       } else if (b->bm_set == b->bm_bits) {
-               /* only the last page */
-               i = b->bm_number_of_pages - 1;
-       } else {
-               /* all pages */
-               i = 0;
-       }
-       for (; i < b->bm_number_of_pages; i++) {
-               p_addr = kmap_atomic(b->bm_pages[i], KM_USER0);
-               for (bm = p_addr; bm < p_addr + PAGE_SIZE/sizeof(long); bm++)
-                       *bm = cpu_to_lel(*bm);
-               kunmap_atomic(p_addr, KM_USER0);
-       }
-}
-# endif
-/* lel_to_cpu == cpu_to_lel */
-# define bm_lel_to_cpu(x) bm_cpu_to_lel(x)
-
 /*
  * bm_rw: read/write the whole bitmap from/to its on disk location.
  */
-static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local)
+static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local)
 {
+       struct bm_aio_ctx ctx = {
+               .mdev = mdev,
+               .in_flight = ATOMIC_INIT(1),
+               .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done),
+               .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0,
+       };
        struct drbd_bitmap *b = mdev->bitmap;
-       /* sector_t sector; */
-       int bm_words, num_pages, i;
+       int num_pages, i, count = 0;
        unsigned long now;
        char ppb[10];
        int err = 0;
 
-       WARN_ON(!bm_is_locked(b));
-
-       /* no spinlock here, the drbd_bm_lock should be enough! */
-
-       bm_words  = drbd_bm_words(mdev);
-       num_pages = (bm_words*sizeof(long) + PAGE_SIZE-1) >> PAGE_SHIFT;
+       /*
+        * We are protected against bitmap disappearing/resizing by holding an
+        * ldev reference (caller must have called get_ldev()).
+        * For read/write, we are protected against changes to the bitmap by
+        * the bitmap lock (see drbd_bitmap_io).
+        * For lazy writeout, we don't care for ongoing changes to the bitmap,
+        * as we submit copies of pages anyways.
+        */
+       if (!ctx.flags)
+               WARN_ON(!(BM_LOCKED_MASK & b->bm_flags));
 
-       /* on disk bitmap is little endian */
-       if (rw == WRITE)
-               bm_cpu_to_lel(b);
+       num_pages = b->bm_number_of_pages;
 
        now = jiffies;
-       atomic_set(&b->bm_async_io, num_pages);
-       __clear_bit(BM_MD_IO_ERROR, &b->bm_flags);
 
        /* let the layers below us try to merge these bios... */
-       for (i = 0; i < num_pages; i++)
-               bm_page_io_async(mdev, b, i, rw);
+       for (i = 0; i < num_pages; i++) {
+               /* ignore completely unchanged pages */
+               if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
+                       break;
+               if (rw & WRITE) {
+                       if (bm_test_page_unchanged(b->bm_pages[i])) {
+                               dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
+                               continue;
+                       }
+                       /* during lazy writeout,
+                        * ignore those pages not marked for lazy writeout. */
+                       if (lazy_writeout_upper_idx &&
+                           !bm_test_page_lazy_writeout(b->bm_pages[i])) {
+                               dynamic_dev_dbg(DEV, "skipped bm lazy write for idx %u\n", i);
+                               continue;
+                       }
+               }
+               atomic_inc(&ctx.in_flight);
+               bm_page_io_async(&ctx, i, rw);
+               ++count;
+               cond_resched();
+       }
 
-       wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0);
+       /*
+        * We initialize ctx.in_flight to one to make sure bm_async_io_complete
+        * will not complete() early, and decrement / test it here.  If there
+        * are still some bios in flight, we need to wait for them here.
+        */
+       if (!atomic_dec_and_test(&ctx.in_flight))
+               wait_for_completion(&ctx.done);
+       dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
+                       rw == WRITE ? "WRITE" : "READ",
+                       count, jiffies - now);
 
-       if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) {
+       if (ctx.error) {
                dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n");
-               drbd_chk_io_error(mdev, 1, TRUE);
-               err = -EIO;
+               drbd_chk_io_error(mdev, 1, true);
+               err = -EIO; /* ctx.error ? */
        }
 
        now = jiffies;
        if (rw == WRITE) {
-               /* swap back endianness */
-               bm_lel_to_cpu(b);
-               /* flush bitmap to stable storage */
                drbd_md_flush(mdev);
        } else /* rw == READ */ {
-               /* just read, if necessary adjust endianness */
-               b->bm_set = bm_count_bits_swap_endian(b);
+               b->bm_set = bm_count_bits(b);
                dev_info(DEV, "recounting of set bits took additional %lu jiffies\n",
                     jiffies - now);
        }
@@ -874,112 +1092,128 @@ static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local)
  */
 int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local)
 {
-       return bm_rw(mdev, READ);
+       return bm_rw(mdev, READ, 0);
 }
 
 /**
  * drbd_bm_write() - Write the whole bitmap to its on disk location.
  * @mdev:      DRBD device.
+ *
+ * Will only write pages that have changed since last IO.
  */
 int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
 {
-       return bm_rw(mdev, WRITE);
+       return bm_rw(mdev, WRITE, 0);
 }
 
 /**
- * drbd_bm_write_sect: Writes a 512 (MD_SECTOR_SIZE) byte piece of the bitmap
+ * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
  * @mdev:      DRBD device.
- * @enr:       Extent number in the resync lru (happens to be sector offset)
- *
- * The BM_EXT_SIZE is on purpose exactly the amount of the bitmap covered
- * by a single sector write. Therefore enr == sector offset from the
- * start of the bitmap.
+ * @upper_idx: 0: write all changed pages; +ve: page index to stop scanning for changed pages
  */
-int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local)
+int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local)
 {
-       sector_t on_disk_sector = enr + mdev->ldev->md.md_offset
-                                     + mdev->ldev->md.bm_offset;
-       int bm_words, num_words, offset;
-       int err = 0;
+       return bm_rw(mdev, WRITE, upper_idx);
+}
+
 
-       mutex_lock(&mdev->md_io_mutex);
-       bm_words  = drbd_bm_words(mdev);
-       offset    = S2W(enr);   /* word offset into bitmap */
-       num_words = min(S2W(1), bm_words - offset);
-       if (num_words < S2W(1))
-               memset(page_address(mdev->md_io_page), 0, MD_SECTOR_SIZE);
-       drbd_bm_get_lel(mdev, offset, num_words,
-                       page_address(mdev->md_io_page));
-       if (!drbd_md_sync_page_io(mdev, mdev->ldev, on_disk_sector, WRITE)) {
-               int i;
-               err = -EIO;
-               dev_err(DEV, "IO ERROR writing bitmap sector %lu "
-                   "(meta-disk sector %llus)\n",
-                   enr, (unsigned long long)on_disk_sector);
-               drbd_chk_io_error(mdev, 1, TRUE);
-               for (i = 0; i < AL_EXT_PER_BM_SECT; i++)
-                       drbd_bm_ALe_set_all(mdev, enr*AL_EXT_PER_BM_SECT+i);
+/**
+ * drbd_bm_write_page: Writes a PAGE_SIZE aligned piece of bitmap
+ * @mdev:      DRBD device.
+ * @idx:       bitmap page index
+ *
+ * We don't want to special case on logical_block_size of the backend device,
+ * so we submit PAGE_SIZE aligned pieces.
+ * Note that on "most" systems, PAGE_SIZE is 4k.
+ *
+ * In case this becomes an issue on systems with larger PAGE_SIZE,
+ * we may want to change this again to write 4k aligned 4k pieces.
+ */
+int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local)
+{
+       struct bm_aio_ctx ctx = {
+               .mdev = mdev,
+               .in_flight = ATOMIC_INIT(1),
+               .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done),
+               .flags = BM_AIO_COPY_PAGES,
+       };
+
+       if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) {
+               dynamic_dev_dbg(DEV, "skipped bm page write for idx %u\n", idx);
+               return 0;
        }
+
+       bm_page_io_async(&ctx, idx, WRITE_SYNC);
+       wait_for_completion(&ctx.done);
+
+       if (ctx.error)
+               drbd_chk_io_error(mdev, 1, true);
+               /* that should force detach, so the in memory bitmap will be
+                * gone in a moment as well. */
+
        mdev->bm_writ_cnt++;
-       mutex_unlock(&mdev->md_io_mutex);
-       return err;
+       return ctx.error;
 }
 
 /* NOTE
  * find_first_bit returns int, we return unsigned long.
- * should not make much difference anyways, but ...
+ * For this to work on 32bit arch with bitnumbers > (1<<32),
+ * we'd need to return u64, and get a whole lot of other places
+ * fixed where we still use unsigned long.
  *
  * this returns a bit number, NOT a sector!
  */
-#define BPP_MASK ((1UL << (PAGE_SHIFT+3)) - 1)
 static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
        const int find_zero_bit, const enum km_type km)
 {
        struct drbd_bitmap *b = mdev->bitmap;
-       unsigned long i = -1UL;
        unsigned long *p_addr;
-       unsigned long bit_offset; /* bit offset of the mapped page. */
+       unsigned long bit_offset;
+       unsigned i;
+
 
        if (bm_fo > b->bm_bits) {
                dev_err(DEV, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits);
+               bm_fo = DRBD_END_OF_BITMAP;
        } else {
                while (bm_fo < b->bm_bits) {
-                       unsigned long offset;
-                       bit_offset = bm_fo & ~BPP_MASK; /* bit offset of the page */
-                       offset = bit_offset >> LN2_BPL;    /* word offset of the page */
-                       p_addr = __bm_map_paddr(b, offset, km);
+                       /* bit offset of the first bit in the page */
+                       bit_offset = bm_fo & ~BITS_PER_PAGE_MASK;
+                       p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo), km);
 
                        if (find_zero_bit)
-                               i = find_next_zero_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK);
+                               i = find_next_zero_bit_le(p_addr,
+                                               PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK);
                        else
-                               i = find_next_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK);
+                               i = find_next_bit_le(p_addr,
+                                               PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK);
 
                        __bm_unmap(p_addr, km);
                        if (i < PAGE_SIZE*8) {
-                               i = bit_offset + i;
-                               if (i >= b->bm_bits)
+                               bm_fo = bit_offset + i;
+                               if (bm_fo >= b->bm_bits)
                                        break;
                                goto found;
                        }
                        bm_fo = bit_offset + PAGE_SIZE*8;
                }
-               i = -1UL;
+               bm_fo = DRBD_END_OF_BITMAP;
        }
  found:
-       return i;
+       return bm_fo;
 }
 
 static unsigned long bm_find_next(struct drbd_conf *mdev,
        unsigned long bm_fo, const int find_zero_bit)
 {
        struct drbd_bitmap *b = mdev->bitmap;
-       unsigned long i = -1UL;
+       unsigned long i = DRBD_END_OF_BITMAP;
 
        ERR_IF(!b) return i;
        ERR_IF(!b->bm_pages) return i;
 
        spin_lock_irq(&b->bm_lock);
-       if (bm_is_locked(b))
+       if (BM_DONT_TEST & b->bm_flags)
                bm_print_lock_info(mdev);
 
        i = __bm_find_next(mdev, bm_fo, find_zero_bit, KM_IRQ1);
@@ -1005,13 +1239,13 @@ unsigned long drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo
  * you must take drbd_bm_lock() first */
 unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo)
 {
-       /* WARN_ON(!bm_is_locked(mdev)); */
+       /* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
        return __bm_find_next(mdev, bm_fo, 0, KM_USER1);
 }
 
 unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo)
 {
-       /* WARN_ON(!bm_is_locked(mdev)); */
+       /* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
        return __bm_find_next(mdev, bm_fo, 1, KM_USER1);
 }
 
@@ -1027,8 +1261,9 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
        struct drbd_bitmap *b = mdev->bitmap;
        unsigned long *p_addr = NULL;
        unsigned long bitnr;
-       unsigned long last_page_nr = -1UL;
+       unsigned int last_page_nr = -1U;
        int c = 0;
+       int changed_total = 0;
 
        if (e >= b->bm_bits) {
                dev_err(DEV, "ASSERT FAILED: bit_s=%lu bit_e=%lu bm_bits=%lu\n",
@@ -1036,23 +1271,33 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
                e = b->bm_bits ? b->bm_bits -1 : 0;
        }
        for (bitnr = s; bitnr <= e; bitnr++) {
-               unsigned long offset = bitnr>>LN2_BPL;
-               unsigned long page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3);
+               unsigned int page_nr = bm_bit_to_page_idx(b, bitnr);
                if (page_nr != last_page_nr) {
                        if (p_addr)
                                __bm_unmap(p_addr, km);
-                       p_addr = __bm_map_paddr(b, offset, km);
+                       if (c < 0)
+                               bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
+                       else if (c > 0)
+                               bm_set_page_need_writeout(b->bm_pages[last_page_nr]);
+                       changed_total += c;
+                       c = 0;
+                       p_addr = __bm_map_pidx(b, page_nr, km);
                        last_page_nr = page_nr;
                }
                if (val)
-                       c += (0 == __test_and_set_bit(bitnr & BPP_MASK, p_addr));
+                       c += (0 == __test_and_set_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr));
                else
-                       c -= (0 != __test_and_clear_bit(bitnr & BPP_MASK, p_addr));
+                       c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr));
        }
        if (p_addr)
                __bm_unmap(p_addr, km);
-       b->bm_set += c;
-       return c;
+       if (c < 0)
+               bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
+       else if (c > 0)
+               bm_set_page_need_writeout(b->bm_pages[last_page_nr]);
+       changed_total += c;
+       b->bm_set += changed_total;
+       return changed_total;
 }
 
 /* returns number of bits actually changed.
@@ -1070,7 +1315,7 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
        ERR_IF(!b->bm_pages) return 0;
 
        spin_lock_irqsave(&b->bm_lock, flags);
-       if (bm_is_locked(b))
+       if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags)
                bm_print_lock_info(mdev);
 
        c = __bm_change_bits_to(mdev, s, e, val, KM_IRQ1);
@@ -1187,12 +1432,11 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
        ERR_IF(!b->bm_pages) return 0;
 
        spin_lock_irqsave(&b->bm_lock, flags);
-       if (bm_is_locked(b))
+       if (BM_DONT_TEST & b->bm_flags)
                bm_print_lock_info(mdev);
        if (bitnr < b->bm_bits) {
-               unsigned long offset = bitnr>>LN2_BPL;
-               p_addr = bm_map_paddr(b, offset);
-               i = test_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0;
+               p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr));
+               i = test_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr) ? 1 : 0;
                bm_unmap(p_addr);
        } else if (bitnr == b->bm_bits) {
                i = -1;
@@ -1210,10 +1454,10 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 {
        unsigned long flags;
        struct drbd_bitmap *b = mdev->bitmap;
-       unsigned long *p_addr = NULL, page_nr = -1;
+       unsigned long *p_addr = NULL;
        unsigned long bitnr;
+       unsigned int page_nr = -1U;
        int c = 0;
-       size_t w;
 
        /* If this is called without a bitmap, that is a bug.  But just to be
         * robust in case we screwed up elsewhere, in that case pretend there
@@ -1223,20 +1467,20 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
        ERR_IF(!b->bm_pages) return 1;
 
        spin_lock_irqsave(&b->bm_lock, flags);
-       if (bm_is_locked(b))
+       if (BM_DONT_TEST & b->bm_flags)
                bm_print_lock_info(mdev);
        for (bitnr = s; bitnr <= e; bitnr++) {
-               w = bitnr >> LN2_BPL;
-               if (page_nr != w >> (PAGE_SHIFT - LN2_BPL + 3)) {
-                       page_nr = w >> (PAGE_SHIFT - LN2_BPL + 3);
+               unsigned int idx = bm_bit_to_page_idx(b, bitnr);
+               if (page_nr != idx) {
+                       page_nr = idx;
                        if (p_addr)
                                bm_unmap(p_addr);
-                       p_addr = bm_map_paddr(b, w);
+                       p_addr = bm_map_pidx(b, idx);
                }
                ERR_IF (bitnr >= b->bm_bits) {
                        dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
                } else {
-                       c += (0 != test_bit(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
+                       c += (0 != test_bit_le(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
                }
        }
        if (p_addr)
@@ -1271,7 +1515,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
        ERR_IF(!b->bm_pages) return 0;
 
        spin_lock_irqsave(&b->bm_lock, flags);
-       if (bm_is_locked(b))
+       if (BM_DONT_TEST & b->bm_flags)
                bm_print_lock_info(mdev);
 
        s = S2W(enr);
@@ -1279,7 +1523,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
        count = 0;
        if (s < b->bm_words) {
                int n = e-s;
-               p_addr = bm_map_paddr(b, s);
+               p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s));
                bm = p_addr + MLPP(s);
                while (n--)
                        count += hweight_long(*bm++);
@@ -1291,18 +1535,20 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
        return count;
 }
 
-/* set all bits covered by the AL-extent al_enr */
+/* Set all bits covered by the AL-extent al_enr.
+ * Returns number of bits changed. */
 unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr)
 {
        struct drbd_bitmap *b = mdev->bitmap;
        unsigned long *p_addr, *bm;
        unsigned long weight;
-       int count, s, e, i, do_now;
+       unsigned long s, e;
+       int count, i, do_now;
        ERR_IF(!b) return 0;
        ERR_IF(!b->bm_pages) return 0;
 
        spin_lock_irq(&b->bm_lock);
-       if (bm_is_locked(b))
+       if (BM_DONT_SET & b->bm_flags)
                bm_print_lock_info(mdev);
        weight = b->bm_set;
 
@@ -1314,7 +1560,7 @@ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr)
        count = 0;
        if (s < b->bm_words) {
                i = do_now = e-s;
-               p_addr = bm_map_paddr(b, s);
+               p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s));
                bm = p_addr + MLPP(s);
                while (i--) {
                        count += hweight_long(*bm);
@@ -1326,7 +1572,7 @@ unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr)
                if (e == b->bm_words)
                        b->bm_set -= bm_clear_surplus(b);
        } else {
-               dev_err(DEV, "start offset (%d) too large in drbd_bm_ALe_set_all\n", s);
+               dev_err(DEV, "start offset (%lu) too large in drbd_bm_ALe_set_all\n", s);
        }
        weight = b->bm_set - weight;
        spin_unlock_irq(&b->bm_lock);
index b0bd27dfc1e8a88deab0c49705b3ed201da7309c..81030d8d654b26115e8d32a425cd9974e30737d1 100644 (file)
@@ -72,13 +72,6 @@ extern int fault_devs;
 extern char usermode_helper[];
 
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
 /* I don't remember why XCPU ...
  * This is used to wake the asender,
  * and to interrupt sending the sending task
@@ -104,6 +97,7 @@ extern char usermode_helper[];
 #define ID_SYNCER (-1ULL)
 #define ID_VACANT 0
 #define is_syncer_block_id(id) ((id) == ID_SYNCER)
+#define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL)
 
 struct drbd_conf;
 
@@ -137,20 +131,19 @@ enum {
        DRBD_FAULT_MAX,
 };
 
-#ifdef CONFIG_DRBD_FAULT_INJECTION
 extern unsigned int
 _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type);
+
 static inline int
 drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
+#ifdef CONFIG_DRBD_FAULT_INJECTION
        return fault_rate &&
                (enable_faults & (1<<type)) &&
                _drbd_insert_fault(mdev, type);
-}
-#define FAULT_ACTIVE(_m, _t) (drbd_insert_fault((_m), (_t)))
-
 #else
-#define FAULT_ACTIVE(_m, _t) (0)
+       return 0;
 #endif
+}
 
 /* integer division, round _UP_ to the next integer */
 #define div_ceil(A, B) ((A)/(B) + ((A)%(B) ? 1 : 0))
@@ -212,8 +205,10 @@ enum drbd_packets {
        /* P_CKPT_FENCE_REQ      = 0x25, * currently reserved for protocol D */
        /* P_CKPT_DISABLE_REQ    = 0x26, * currently reserved for protocol D */
        P_DELAY_PROBE         = 0x27, /* is used on BOTH sockets */
+       P_OUT_OF_SYNC         = 0x28, /* Mark as out of sync (Outrunning), data socket */
+       P_RS_CANCEL           = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */
 
-       P_MAX_CMD             = 0x28,
+       P_MAX_CMD             = 0x2A,
        P_MAY_IGNORE          = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
        P_MAX_OPT_CMD         = 0x101,
 
@@ -269,6 +264,7 @@ static inline const char *cmdname(enum drbd_packets cmd)
                [P_RS_IS_IN_SYNC]       = "CsumRSIsInSync",
                [P_COMPRESSED_BITMAP]   = "CBitmap",
                [P_DELAY_PROBE]         = "DelayProbe",
+               [P_OUT_OF_SYNC]         = "OutOfSync",
                [P_MAX_CMD]             = NULL,
        };
 
@@ -512,7 +508,7 @@ struct p_sizes {
        u64         d_size;  /* size of disk */
        u64         u_size;  /* user requested size */
        u64         c_size;  /* current exported size */
-       u32         max_segment_size;  /* Maximal size of a BIO */
+       u32         max_bio_size;  /* Maximal size of a BIO */
        u16         queue_order_type;  /* not yet implemented in DRBD*/
        u16         dds_flags; /* use enum dds_flags here. */
 } __packed;
@@ -550,6 +546,13 @@ struct p_discard {
        u32         pad;
 } __packed;
 
+struct p_block_desc {
+       struct p_header80 head;
+       u64 sector;
+       u32 blksize;
+       u32 pad;        /* to multiple of 8 Byte */
+} __packed;
+
 /* Valid values for the encoding field.
  * Bump proto version when changing this. */
 enum drbd_bitmap_code {
@@ -647,6 +650,7 @@ union p_polymorph {
         struct p_block_req       block_req;
        struct p_delay_probe93   delay_probe93;
        struct p_rs_uuid         rs_uuid;
+       struct p_block_desc      block_desc;
 } __packed;
 
 /**********************************************************************/
@@ -677,13 +681,6 @@ static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
        return thi->t_state;
 }
 
-
-/*
- * Having this as the first member of a struct provides sort of "inheritance".
- * "derived" structs can be "drbd_queue_work()"ed.
- * The callback should know and cast back to the descendant struct.
- * drbd_request and drbd_epoch_entry are descendants of drbd_work.
- */
 struct drbd_work;
 typedef int (*drbd_work_cb)(struct drbd_conf *, struct drbd_work *, int cancel);
 struct drbd_work {
@@ -712,9 +709,6 @@ struct drbd_request {
         * starting a new epoch...
         */
 
-       /* up to here, the struct layout is identical to drbd_epoch_entry;
-        * we might be able to use that to our advantage...  */
-
        struct list_head tl_requests; /* ring list in the transfer log */
        struct bio *master_bio;       /* master bio pointer */
        unsigned long rq_state; /* see comments above _req_mod() */
@@ -831,7 +825,7 @@ enum {
        CRASHED_PRIMARY,        /* This node was a crashed primary.
                                 * Gets cleared when the state.conn
                                 * goes into C_CONNECTED state. */
-       WRITE_BM_AFTER_RESYNC,  /* A kmalloc() during resync failed */
+       NO_BARRIER_SUPP,        /* underlying block device doesn't implement barriers */
        CONSIDER_RESYNC,
 
        MD_NO_FUA,              /* Users wants us to not use FUA/FLUSH on meta data dev */
@@ -856,10 +850,37 @@ enum {
        GOT_PING_ACK,           /* set when we receive a ping_ack packet, misc wait gets woken */
        NEW_CUR_UUID,           /* Create new current UUID when thawing IO */
        AL_SUSPENDED,           /* Activity logging is currently suspended. */
+       AHEAD_TO_SYNC_SOURCE,   /* Ahead -> SyncSource queued */
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
 
+/* definition of bits in bm_flags to be used in drbd_bm_lock
+ * and drbd_bitmap_io and friends. */
+enum bm_flag {
+       /* do we need to kfree, or vfree bm_pages? */
+       BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */
+
+       /* currently locked for bulk operation */
+       BM_LOCKED_MASK = 0x7,
+
+       /* in detail, that is: */
+       BM_DONT_CLEAR = 0x1,
+       BM_DONT_SET   = 0x2,
+       BM_DONT_TEST  = 0x4,
+
+       /* (test bit, count bit) allowed (common case) */
+       BM_LOCKED_TEST_ALLOWED = 0x3,
+
+       /* testing bits, as well as setting new bits allowed, but clearing bits
+        * would be unexpected.  Used during bitmap receive.  Setting new bits
+        * requires sending of "out-of-sync" information, though. */
+       BM_LOCKED_SET_ALLOWED = 0x1,
+
+       /* clear is not expected while bitmap is locked for bulk operation */
+};
+
+
 /* TODO sort members for performance
  * MAYBE group them further */
 
@@ -925,6 +946,7 @@ struct drbd_md_io {
 struct bm_io_work {
        struct drbd_work w;
        char *why;
+       enum bm_flag flags;
        int (*io_fn)(struct drbd_conf *mdev);
        void (*done)(struct drbd_conf *mdev, int rv);
 };
@@ -963,9 +985,12 @@ struct drbd_conf {
        struct drbd_work  resync_work,
                          unplug_work,
                          go_diskless,
-                         md_sync_work;
+                         md_sync_work,
+                         start_resync_work;
        struct timer_list resync_timer;
        struct timer_list md_sync_timer;
+       struct timer_list start_resync_timer;
+       struct timer_list request_timer;
 #ifdef DRBD_DEBUG_MD_SYNC
        struct {
                unsigned int line;
@@ -1000,9 +1025,9 @@ struct drbd_conf {
        struct hlist_head *tl_hash;
        unsigned int tl_hash_s;
 
-       /* blocks to sync in this run [unit BM_BLOCK_SIZE] */
+       /* blocks to resync in this run [unit BM_BLOCK_SIZE] */
        unsigned long rs_total;
-       /* number of sync IOs that failed in this run */
+       /* number of resync blocks that failed in this run */
        unsigned long rs_failed;
        /* Syncer's start time [unit jiffies] */
        unsigned long rs_start;
@@ -1102,6 +1127,7 @@ struct drbd_conf {
        struct fifo_buffer rs_plan_s; /* correction values of resync planer */
        int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
        int rs_planed;    /* resync sectors already planed */
+       atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1163,14 +1189,19 @@ enum dds_flags {
 };
 
 extern void drbd_init_set_defaults(struct drbd_conf *mdev);
-extern int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
-                       union drbd_state mask, union drbd_state val);
+extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
+                                           enum chg_state_flags f,
+                                           union drbd_state mask,
+                                           union drbd_state val);
 extern void drbd_force_state(struct drbd_conf *, union drbd_state,
                        union drbd_state);
-extern int _drbd_request_state(struct drbd_conf *, union drbd_state,
-                       union drbd_state, enum chg_state_flags);
-extern int __drbd_set_state(struct drbd_conf *, union drbd_state,
-                           enum chg_state_flags, struct completion *done);
+extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
+                                             union drbd_state,
+                                             union drbd_state,
+                                             enum chg_state_flags);
+extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
+                                          enum chg_state_flags,
+                                          struct completion *done);
 extern void print_st_err(struct drbd_conf *, union drbd_state,
                        union drbd_state, int);
 extern int  drbd_thread_start(struct drbd_thread *thi);
@@ -1195,7 +1226,7 @@ extern int drbd_send(struct drbd_conf *mdev, struct socket *sock,
 extern int drbd_send_protocol(struct drbd_conf *mdev);
 extern int drbd_send_uuids(struct drbd_conf *mdev);
 extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev);
-extern int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val);
+extern int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
 extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags);
 extern int _drbd_send_state(struct drbd_conf *mdev);
 extern int drbd_send_state(struct drbd_conf *mdev);
@@ -1220,11 +1251,10 @@ extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
                        struct p_data *dp, int data_size);
 extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
                            sector_t sector, int blksize, u64 block_id);
+extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
                           struct drbd_epoch_entry *e);
 extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req);
-extern int _drbd_send_barrier(struct drbd_conf *mdev,
-                       struct drbd_tl_epoch *barrier);
 extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
                              sector_t sector, int size, u64 block_id);
 extern int drbd_send_drequest_csum(struct drbd_conf *mdev,
@@ -1235,14 +1265,13 @@ extern int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size)
 
 extern int drbd_send_bitmap(struct drbd_conf *mdev);
 extern int _drbd_send_bitmap(struct drbd_conf *mdev);
-extern int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode);
+extern int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode);
 extern void drbd_free_bc(struct drbd_backing_dev *ldev);
 extern void drbd_mdev_cleanup(struct drbd_conf *mdev);
+void drbd_print_uuids(struct drbd_conf *mdev, const char *text);
 
-/* drbd_meta-data.c (still in drbd_main.c) */
 extern void drbd_md_sync(struct drbd_conf *mdev);
 extern int  drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
-/* maybe define them below as inline? */
 extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
@@ -1261,10 +1290,12 @@ extern void drbd_md_mark_dirty_(struct drbd_conf *mdev,
 extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
                                 int (*io_fn)(struct drbd_conf *),
                                 void (*done)(struct drbd_conf *, int),
-                                char *why);
+                                char *why, enum bm_flag flags);
+extern int drbd_bitmap_io(struct drbd_conf *mdev,
+               int (*io_fn)(struct drbd_conf *),
+               char *why, enum bm_flag flags);
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
-extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why);
 extern void drbd_go_diskless(struct drbd_conf *mdev);
 extern void drbd_ldev_destroy(struct drbd_conf *mdev);
 
@@ -1313,6 +1344,7 @@ struct bm_extent {
 
 #define BME_NO_WRITES  0  /* bm_extent.flags: no more requests on this one! */
 #define BME_LOCKED     1  /* bm_extent.flags: syncer active on this one. */
+#define BME_PRIORITY   2  /* finish resync IO on this extent ASAP! App IO waiting! */
 
 /* drbd_bitmap.c */
 /*
@@ -1390,7 +1422,9 @@ struct bm_extent {
  * you should use 64bit OS for that much storage, anyways. */
 #define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0xffff7fff)
 #else
-#define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0x1LU << 32)
+/* we allow up to 1 PiB now on 64bit architecture with "flexible" meta data */
+#define DRBD_MAX_SECTORS_FLEX (1UL << 51)
+/* corresponds to (1UL << 38) bits right now. */
 #endif
 #endif
 
@@ -1398,7 +1432,7 @@ struct bm_extent {
  * With a value of 8 all IO in one 128K block make it to the same slot of the
  * hash table. */
 #define HT_SHIFT 8
-#define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT))
+#define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT))
 
 #define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
 
@@ -1410,16 +1444,20 @@ extern int  drbd_bm_resize(struct drbd_conf *mdev, sector_t sectors, int set_new
 extern void drbd_bm_cleanup(struct drbd_conf *mdev);
 extern void drbd_bm_set_all(struct drbd_conf *mdev);
 extern void drbd_bm_clear_all(struct drbd_conf *mdev);
+/* set/clear/test only a few bits at a time */
 extern int  drbd_bm_set_bits(
                struct drbd_conf *mdev, unsigned long s, unsigned long e);
 extern int  drbd_bm_clear_bits(
                struct drbd_conf *mdev, unsigned long s, unsigned long e);
-/* bm_set_bits variant for use while holding drbd_bm_lock */
+extern int drbd_bm_count_bits(
+       struct drbd_conf *mdev, const unsigned long s, const unsigned long e);
+/* bm_set_bits variant for use while holding drbd_bm_lock,
+ * may process the whole bitmap in one go */
 extern void _drbd_bm_set_bits(struct drbd_conf *mdev,
                const unsigned long s, const unsigned long e);
 extern int  drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr);
 extern int  drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
-extern int  drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local);
+extern int  drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
 extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
 extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
@@ -1427,6 +1465,8 @@ extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
 extern size_t       drbd_bm_words(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_bits(struct drbd_conf *mdev);
 extern sector_t      drbd_bm_capacity(struct drbd_conf *mdev);
+
+#define DRBD_END_OF_BITMAP     (~(unsigned long)0)
 extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
 /* bm_find_next variants for use while you hold drbd_bm_lock() */
 extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
@@ -1437,14 +1477,12 @@ extern int drbd_bm_rs_done(struct drbd_conf *mdev);
 /* for receive_bitmap */
 extern void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset,
                size_t number, unsigned long *buffer);
-/* for _drbd_send_bitmap and drbd_bm_write_sect */
+/* for _drbd_send_bitmap */
 extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset,
                size_t number, unsigned long *buffer);
 
-extern void drbd_bm_lock(struct drbd_conf *mdev, char *why);
+extern void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags);
 extern void drbd_bm_unlock(struct drbd_conf *mdev);
-
-extern int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e);
 /* drbd_main.c */
 
 extern struct kmem_cache *drbd_request_cache;
@@ -1467,7 +1505,7 @@ extern void drbd_free_mdev(struct drbd_conf *mdev);
 extern int proc_details;
 
 /* drbd_req */
-extern int drbd_make_request_26(struct request_queue *q, struct bio *bio);
+extern int drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
@@ -1482,8 +1520,9 @@ enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew =
 extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local);
 extern void resync_after_online_grow(struct drbd_conf *);
 extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
-extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
-               int force);
+extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev,
+                                       enum drbd_role new_role,
+                                       int force);
 extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
 extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
 extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
@@ -1499,6 +1538,7 @@ extern int drbd_resync_finished(struct drbd_conf *mdev);
 extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
                struct drbd_backing_dev *bdev, sector_t sector, int rw);
 extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int);
+extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
 
 static inline void ov_oos_print(struct drbd_conf *mdev)
 {
@@ -1522,21 +1562,23 @@ extern int w_e_end_csum_rs_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_end_ov_reply(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
-extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int);
+extern int w_resync_timer(struct drbd_conf *, struct drbd_work *, int);
 extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
-extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
 extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
+extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int);
+extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
+extern void start_resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
-extern int drbd_rs_should_slow_down(struct drbd_conf *mdev);
+extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector);
 extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
                const unsigned rw, const int fault_type);
 extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
@@ -1619,16 +1661,16 @@ extern int drbd_rs_del_all(struct drbd_conf *mdev);
 extern void drbd_rs_failed_io(struct drbd_conf *mdev,
                sector_t sector, int size);
 extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *);
+extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go);
 extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector,
                int size, const char *file, const unsigned int line);
 #define drbd_set_in_sync(mdev, sector, size) \
        __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__)
-extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
+extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
                int size, const char *file, const unsigned int line);
 #define drbd_set_out_of_sync(mdev, sector, size) \
        __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__)
 extern void drbd_al_apply_to_bm(struct drbd_conf *mdev);
-extern void drbd_al_to_on_disk_bm(struct drbd_conf *mdev);
 extern void drbd_al_shrink(struct drbd_conf *mdev);
 
 
@@ -1747,11 +1789,11 @@ static inline void drbd_state_unlock(struct drbd_conf *mdev)
        wake_up(&mdev->misc_wait);
 }
 
-static inline int _drbd_set_state(struct drbd_conf *mdev,
-                                  union drbd_state ns, enum chg_state_flags flags,
-                                  struct completion *done)
+static inline enum drbd_state_rv
+_drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+               enum chg_state_flags flags, struct completion *done)
 {
-       int rv;
+       enum drbd_state_rv rv;
 
        read_lock(&global_state_lock);
        rv = __drbd_set_state(mdev, ns, flags, done);
@@ -1982,17 +2024,17 @@ static inline int drbd_send_ping_ack(struct drbd_conf *mdev)
 
 static inline void drbd_thread_stop(struct drbd_thread *thi)
 {
-       _drbd_thread_stop(thi, FALSE, TRUE);
+       _drbd_thread_stop(thi, false, true);
 }
 
 static inline void drbd_thread_stop_nowait(struct drbd_thread *thi)
 {
-       _drbd_thread_stop(thi, FALSE, FALSE);
+       _drbd_thread_stop(thi, false, false);
 }
 
 static inline void drbd_thread_restart_nowait(struct drbd_thread *thi)
 {
-       _drbd_thread_stop(thi, TRUE, FALSE);
+       _drbd_thread_stop(thi, true, false);
 }
 
 /* counts how many answer packets packets we expect from our peer,
@@ -2146,17 +2188,18 @@ extern int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
 static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
                unsigned long *bits_left, unsigned int *per_mil_done)
 {
-       /*
-        * this is to break it at compile time when we change that
-        * (we may feel 4TB maximum storage per drbd is not enough)
-        */
+       /* this is to break it at compile time when we change that, in case we
+        * want to support more than (1<<32) bits on a 32bit arch. */
        typecheck(unsigned long, mdev->rs_total);
 
        /* note: both rs_total and rs_left are in bits, i.e. in
         * units of BM_BLOCK_SIZE.
         * for the percentage, we don't care. */
 
-       *bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+       if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+               *bits_left = mdev->ov_left;
+       else
+               *bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
        /* >> 10 to prevent overflow,
         * +1 to prevent division by zero */
        if (*bits_left > mdev->rs_total) {
@@ -2171,10 +2214,19 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
                                *bits_left, mdev->rs_total, mdev->rs_failed);
                *per_mil_done = 0;
        } else {
-               /* make sure the calculation happens in long context */
-               unsigned long tmp = 1000UL -
-                               (*bits_left >> 10)*1000UL
-                               / ((mdev->rs_total >> 10) + 1UL);
+               /* Make sure the division happens in long context.
+                * We allow up to one petabyte storage right now,
+                * at a granularity of 4k per bit that is 2**38 bits.
+                * After shift right and multiplication by 1000,
+                * this should still fit easily into a 32bit long,
+                * so we don't need a 64bit division on 32bit arch.
+                * Note: currently we don't support such large bitmaps on 32bit
+                * arch anyways, but no harm done to be prepared for it here.
+                */
+               unsigned int shift = mdev->rs_total >= (1ULL << 32) ? 16 : 10;
+               unsigned long left = *bits_left >> shift;
+               unsigned long total = 1UL + (mdev->rs_total >> shift);
+               unsigned long tmp = 1000UL - left * 1000UL/total;
                *per_mil_done = tmp;
        }
 }
@@ -2193,8 +2245,9 @@ static inline int drbd_get_max_buffers(struct drbd_conf *mdev)
        return mxb;
 }
 
-static inline int drbd_state_is_stable(union drbd_state s)
+static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 {
+       union drbd_state s = mdev->state;
 
        /* DO NOT add a default clause, we want the compiler to warn us
         * for any newly introduced state we may have forgotten to add here */
@@ -2211,11 +2264,9 @@ static inline int drbd_state_is_stable(union drbd_state s)
        case C_VERIFY_T:
        case C_PAUSED_SYNC_S:
        case C_PAUSED_SYNC_T:
-               /* maybe stable, look at the disk state */
-               break;
-
-       /* no new io accepted during tansitional states
-        * like handshake or teardown */
+       case C_AHEAD:
+       case C_BEHIND:
+               /* transitional states, IO allowed */
        case C_DISCONNECTING:
        case C_UNCONNECTED:
        case C_TIMEOUT:
@@ -2226,7 +2277,15 @@ static inline int drbd_state_is_stable(union drbd_state s)
        case C_WF_REPORT_PARAMS:
        case C_STARTING_SYNC_S:
        case C_STARTING_SYNC_T:
+               break;
+
+               /* Allow IO in BM exchange states with new protocols */
        case C_WF_BITMAP_S:
+               if (mdev->agreed_pro_version < 96)
+                       return 0;
+               break;
+
+               /* no new io accepted in these states */
        case C_WF_BITMAP_T:
        case C_WF_SYNC_UUID:
        case C_MASK:
@@ -2261,41 +2320,47 @@ static inline int is_susp(union drbd_state s)
        return s.susp || s.susp_nod || s.susp_fen;
 }
 
-static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
+static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
 {
        int mxb = drbd_get_max_buffers(mdev);
 
        if (is_susp(mdev->state))
-               return 0;
+               return false;
        if (test_bit(SUSPEND_IO, &mdev->flags))
-               return 0;
+               return false;
 
        /* to avoid potential deadlock or bitmap corruption,
         * in various places, we only allow new application io
         * to start during "stable" states. */
 
        /* no new io accepted when attaching or detaching the disk */
-       if (!drbd_state_is_stable(mdev->state))
-               return 0;
+       if (!drbd_state_is_stable(mdev))
+               return false;
 
        /* since some older kernels don't have atomic_add_unless,
         * and we are within the spinlock anyways, we have this workaround.  */
        if (atomic_read(&mdev->ap_bio_cnt) > mxb)
-               return 0;
+               return false;
        if (test_bit(BITMAP_IO, &mdev->flags))
-               return 0;
-       return 1;
+               return false;
+       return true;
 }
 
-/* I'd like to use wait_event_lock_irq,
- * but I'm not sure when it got introduced,
- * and not sure when it has 3 or 4 arguments */
-static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+static inline bool inc_ap_bio_cond(struct drbd_conf *mdev, int count)
 {
-       /* compare with after_state_ch,
-        * os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S */
-       DEFINE_WAIT(wait);
+       bool rv = false;
+
+       spin_lock_irq(&mdev->req_lock);
+       rv = may_inc_ap_bio(mdev);
+       if (rv)
+               atomic_add(count, &mdev->ap_bio_cnt);
+       spin_unlock_irq(&mdev->req_lock);
+
+       return rv;
+}
 
+static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+{
        /* we wait here
         *    as long as the device is suspended
         *    until the bitmap is no longer on the fly during connection
@@ -2304,16 +2369,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
         * to avoid races with the reconnect code,
         * we need to atomic_inc within the spinlock. */
 
-       spin_lock_irq(&mdev->req_lock);
-       while (!__inc_ap_bio_cond(mdev)) {
-               prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
-               spin_unlock_irq(&mdev->req_lock);
-               schedule();
-               finish_wait(&mdev->misc_wait, &wait);
-               spin_lock_irq(&mdev->req_lock);
-       }
-       atomic_add(count, &mdev->ap_bio_cnt);
-       spin_unlock_irq(&mdev->req_lock);
+       wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev, count));
 }
 
 static inline void dec_ap_bio(struct drbd_conf *mdev)
@@ -2333,9 +2389,11 @@ static inline void dec_ap_bio(struct drbd_conf *mdev)
        }
 }
 
-static inline void drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
+static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
 {
+       int changed = mdev->ed_uuid != val;
        mdev->ed_uuid = val;
+       return changed;
 }
 
 static inline int seq_cmp(u32 a, u32 b)
index 8a43ce0edeed12f1007cfeb9474ed857fc8f39cd..dfc85f32d3177bb90bcc2b53f8d3921de82df544 100644 (file)
@@ -85,7 +85,8 @@ MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
 MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION);
 MODULE_VERSION(REL_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices (1-255)");
+MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices ("
+                __stringify(DRBD_MINOR_COUNT_MIN) "-" __stringify(DRBD_MINOR_COUNT_MAX) ")");
 MODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR);
 
 #include <linux/moduleparam.h>
@@ -115,7 +116,7 @@ module_param(fault_devs, int, 0644);
 #endif
 
 /* module parameter, defined */
-unsigned int minor_count = 32;
+unsigned int minor_count = DRBD_MINOR_COUNT_DEF;
 int disable_sendpage;
 int allow_oos;
 unsigned int cn_idx = CN_IDX_DRBD;
@@ -335,6 +336,7 @@ bail:
        drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 }
 
+
 /**
  * _tl_restart() - Walks the transfer log, and applies an action to all requests
  * @mdev:      DRBD device.
@@ -456,7 +458,7 @@ void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
 }
 
 /**
- * cl_wide_st_chg() - TRUE if the state change is a cluster wide one
+ * cl_wide_st_chg() - true if the state change is a cluster wide one
  * @mdev:      DRBD device.
  * @os:                old (current) state.
  * @ns:                new (wanted) state.
@@ -473,12 +475,13 @@ static int cl_wide_st_chg(struct drbd_conf *mdev,
                (os.conn == C_CONNECTED && ns.conn == C_VERIFY_S);
 }
 
-int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
-                     union drbd_state mask, union drbd_state val)
+enum drbd_state_rv
+drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
+                 union drbd_state mask, union drbd_state val)
 {
        unsigned long flags;
        union drbd_state os, ns;
-       int rv;
+       enum drbd_state_rv rv;
 
        spin_lock_irqsave(&mdev->req_lock, flags);
        os = mdev->state;
@@ -502,20 +505,22 @@ void drbd_force_state(struct drbd_conf *mdev,
        drbd_change_state(mdev, CS_HARD, mask, val);
 }
 
-static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns);
-static int is_valid_state_transition(struct drbd_conf *,
-                                    union drbd_state, union drbd_state);
+static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
+static enum drbd_state_rv is_valid_state_transition(struct drbd_conf *,
+                                                   union drbd_state,
+                                                   union drbd_state);
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
                                       union drbd_state ns, const char **warn_sync_abort);
 int drbd_send_state_req(struct drbd_conf *,
                        union drbd_state, union drbd_state);
 
-static enum drbd_state_ret_codes _req_st_cond(struct drbd_conf *mdev,
-                                   union drbd_state mask, union drbd_state val)
+static enum drbd_state_rv
+_req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
+            union drbd_state val)
 {
        union drbd_state os, ns;
        unsigned long flags;
-       int rv;
+       enum drbd_state_rv rv;
 
        if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags))
                return SS_CW_SUCCESS;
@@ -536,7 +541,7 @@ static enum drbd_state_ret_codes _req_st_cond(struct drbd_conf *mdev,
                if (rv == SS_SUCCESS) {
                        rv = is_valid_state_transition(mdev, ns, os);
                        if (rv == SS_SUCCESS)
-                               rv = 0; /* cont waiting, otherwise fail. */
+                               rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
                }
        }
        spin_unlock_irqrestore(&mdev->req_lock, flags);
@@ -554,14 +559,14 @@ static enum drbd_state_ret_codes _req_st_cond(struct drbd_conf *mdev,
  * Should not be called directly, use drbd_request_state() or
  * _drbd_request_state().
  */
-static int drbd_req_state(struct drbd_conf *mdev,
-                         union drbd_state mask, union drbd_state val,
-                         enum chg_state_flags f)
+static enum drbd_state_rv
+drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
+              union drbd_state val, enum chg_state_flags f)
 {
        struct completion done;
        unsigned long flags;
        union drbd_state os, ns;
-       int rv;
+       enum drbd_state_rv rv;
 
        init_completion(&done);
 
@@ -636,10 +641,11 @@ abort:
  * Cousin of drbd_request_state(), useful with the CS_WAIT_COMPLETE
  * flag, or when logging of failed state change requests is not desired.
  */
-int _drbd_request_state(struct drbd_conf *mdev,        union drbd_state mask,
-                       union drbd_state val,   enum chg_state_flags f)
+enum drbd_state_rv
+_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask,
+                   union drbd_state val, enum chg_state_flags f)
 {
-       int rv;
+       enum drbd_state_rv rv;
 
        wait_event(mdev->state_wait,
                   (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE);
@@ -663,8 +669,8 @@ static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
            );
 }
 
-void print_st_err(struct drbd_conf *mdev,
-       union drbd_state os, union drbd_state ns, int err)
+void print_st_err(struct drbd_conf *mdev, union drbd_state os,
+                 union drbd_state ns, enum drbd_state_rv err)
 {
        if (err == SS_IN_TRANSIENT_STATE)
                return;
@@ -674,32 +680,18 @@ void print_st_err(struct drbd_conf *mdev,
 }
 
 
-#define drbd_peer_str drbd_role_str
-#define drbd_pdsk_str drbd_disk_str
-
-#define drbd_susp_str(A)     ((A) ? "1" : "0")
-#define drbd_aftr_isp_str(A) ((A) ? "1" : "0")
-#define drbd_peer_isp_str(A) ((A) ? "1" : "0")
-#define drbd_user_isp_str(A) ((A) ? "1" : "0")
-
-#define PSC(A) \
-       ({ if (ns.A != os.A) { \
-               pbp += sprintf(pbp, #A "( %s -> %s ) ", \
-                             drbd_##A##_str(os.A), \
-                             drbd_##A##_str(ns.A)); \
-       } })
-
 /**
  * is_valid_state() - Returns an SS_ error code if ns is not valid
  * @mdev:      DRBD device.
  * @ns:                State to consider.
  */
-static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
+static enum drbd_state_rv
+is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
 {
        /* See drbd_state_sw_errors in drbd_strings.c */
 
        enum drbd_fencing_p fp;
-       int rv = SS_SUCCESS;
+       enum drbd_state_rv rv = SS_SUCCESS;
 
        fp = FP_DONT_CARE;
        if (get_ldev(mdev)) {
@@ -762,10 +754,11 @@ static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
  * @ns:                new state.
  * @os:                old state.
  */
-static int is_valid_state_transition(struct drbd_conf *mdev,
-                                    union drbd_state ns, union drbd_state os)
+static enum drbd_state_rv
+is_valid_state_transition(struct drbd_conf *mdev, union drbd_state ns,
+                         union drbd_state os)
 {
-       int rv = SS_SUCCESS;
+       enum drbd_state_rv rv = SS_SUCCESS;
 
        if ((ns.conn == C_STARTING_SYNC_T || ns.conn == C_STARTING_SYNC_S) &&
            os.conn > C_CONNECTED)
@@ -800,6 +793,10 @@ static int is_valid_state_transition(struct drbd_conf *mdev,
            os.conn < C_CONNECTED)
                rv = SS_NEED_CONNECTION;
 
+       if ((ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)
+           && os.conn < C_WF_REPORT_PARAMS)
+               rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
+
        return rv;
 }
 
@@ -817,6 +814,7 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
                                       union drbd_state ns, const char **warn_sync_abort)
 {
        enum drbd_fencing_p fp;
+       enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max;
 
        fp = FP_DONT_CARE;
        if (get_ldev(mdev)) {
@@ -869,56 +867,6 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
                ns.conn = C_CONNECTED;
        }
 
-       if (ns.conn >= C_CONNECTED &&
-           ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) ||
-            (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T))) {
-               switch (ns.conn) {
-               case C_WF_BITMAP_T:
-               case C_PAUSED_SYNC_T:
-                       ns.disk = D_OUTDATED;
-                       break;
-               case C_CONNECTED:
-               case C_WF_BITMAP_S:
-               case C_SYNC_SOURCE:
-               case C_PAUSED_SYNC_S:
-                       ns.disk = D_UP_TO_DATE;
-                       break;
-               case C_SYNC_TARGET:
-                       ns.disk = D_INCONSISTENT;
-                       dev_warn(DEV, "Implicitly set disk state Inconsistent!\n");
-                       break;
-               }
-               if (os.disk == D_OUTDATED && ns.disk == D_UP_TO_DATE)
-                       dev_warn(DEV, "Implicitly set disk from Outdated to UpToDate\n");
-       }
-
-       if (ns.conn >= C_CONNECTED &&
-           (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)) {
-               switch (ns.conn) {
-               case C_CONNECTED:
-               case C_WF_BITMAP_T:
-               case C_PAUSED_SYNC_T:
-               case C_SYNC_TARGET:
-                       ns.pdsk = D_UP_TO_DATE;
-                       break;
-               case C_WF_BITMAP_S:
-               case C_PAUSED_SYNC_S:
-                       /* remap any consistent state to D_OUTDATED,
-                        * but disallow "upgrade" of not even consistent states.
-                        */
-                       ns.pdsk =
-                               (D_DISKLESS < os.pdsk && os.pdsk < D_OUTDATED)
-                               ? os.pdsk : D_OUTDATED;
-                       break;
-               case C_SYNC_SOURCE:
-                       ns.pdsk = D_INCONSISTENT;
-                       dev_warn(DEV, "Implicitly set pdsk Inconsistent!\n");
-                       break;
-               }
-               if (os.pdsk == D_OUTDATED && ns.pdsk == D_UP_TO_DATE)
-                       dev_warn(DEV, "Implicitly set pdsk from Outdated to UpToDate\n");
-       }
-
        /* Connection breaks down before we finished "Negotiating" */
        if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
            get_ldev_if_state(mdev, D_NEGOTIATING)) {
@@ -933,6 +881,94 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
                put_ldev(mdev);
        }
 
+       /* D_CONSISTENT and D_OUTDATED vanish when we get connected */
+       if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) {
+               if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED)
+                       ns.disk = D_UP_TO_DATE;
+               if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)
+                       ns.pdsk = D_UP_TO_DATE;
+       }
+
+       /* Implications of the connection stat on the disk states */
+       disk_min = D_DISKLESS;
+       disk_max = D_UP_TO_DATE;
+       pdsk_min = D_INCONSISTENT;
+       pdsk_max = D_UNKNOWN;
+       switch ((enum drbd_conns)ns.conn) {
+       case C_WF_BITMAP_T:
+       case C_PAUSED_SYNC_T:
+       case C_STARTING_SYNC_T:
+       case C_WF_SYNC_UUID:
+       case C_BEHIND:
+               disk_min = D_INCONSISTENT;
+               disk_max = D_OUTDATED;
+               pdsk_min = D_UP_TO_DATE;
+               pdsk_max = D_UP_TO_DATE;
+               break;
+       case C_VERIFY_S:
+       case C_VERIFY_T:
+               disk_min = D_UP_TO_DATE;
+               disk_max = D_UP_TO_DATE;
+               pdsk_min = D_UP_TO_DATE;
+               pdsk_max = D_UP_TO_DATE;
+               break;
+       case C_CONNECTED:
+               disk_min = D_DISKLESS;
+               disk_max = D_UP_TO_DATE;
+               pdsk_min = D_DISKLESS;
+               pdsk_max = D_UP_TO_DATE;
+               break;
+       case C_WF_BITMAP_S:
+       case C_PAUSED_SYNC_S:
+       case C_STARTING_SYNC_S:
+       case C_AHEAD:
+               disk_min = D_UP_TO_DATE;
+               disk_max = D_UP_TO_DATE;
+               pdsk_min = D_INCONSISTENT;
+               pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/
+               break;
+       case C_SYNC_TARGET:
+               disk_min = D_INCONSISTENT;
+               disk_max = D_INCONSISTENT;
+               pdsk_min = D_UP_TO_DATE;
+               pdsk_max = D_UP_TO_DATE;
+               break;
+       case C_SYNC_SOURCE:
+               disk_min = D_UP_TO_DATE;
+               disk_max = D_UP_TO_DATE;
+               pdsk_min = D_INCONSISTENT;
+               pdsk_max = D_INCONSISTENT;
+               break;
+       case C_STANDALONE:
+       case C_DISCONNECTING:
+       case C_UNCONNECTED:
+       case C_TIMEOUT:
+       case C_BROKEN_PIPE:
+       case C_NETWORK_FAILURE:
+       case C_PROTOCOL_ERROR:
+       case C_TEAR_DOWN:
+       case C_WF_CONNECTION:
+       case C_WF_REPORT_PARAMS:
+       case C_MASK:
+               break;
+       }
+       if (ns.disk > disk_max)
+               ns.disk = disk_max;
+
+       if (ns.disk < disk_min) {
+               dev_warn(DEV, "Implicitly set disk from %s to %s\n",
+                        drbd_disk_str(ns.disk), drbd_disk_str(disk_min));
+               ns.disk = disk_min;
+       }
+       if (ns.pdsk > pdsk_max)
+               ns.pdsk = pdsk_max;
+
+       if (ns.pdsk < pdsk_min) {
+               dev_warn(DEV, "Implicitly set pdsk from %s to %s\n",
+                        drbd_disk_str(ns.pdsk), drbd_disk_str(pdsk_min));
+               ns.pdsk = pdsk_min;
+       }
+
        if (fp == FP_STONITH &&
            (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
            !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
@@ -961,6 +997,10 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
 /* helper for __drbd_set_state */
 static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
 {
+       if (mdev->agreed_pro_version < 90)
+               mdev->ov_start_sector = 0;
+       mdev->rs_total = drbd_bm_bits(mdev);
+       mdev->ov_position = 0;
        if (cs == C_VERIFY_T) {
                /* starting online verify from an arbitrary position
                 * does not fit well into the existing protocol.
@@ -970,11 +1010,15 @@ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
                mdev->ov_start_sector = ~(sector_t)0;
        } else {
                unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector);
-               if (bit >= mdev->rs_total)
+               if (bit >= mdev->rs_total) {
                        mdev->ov_start_sector =
                                BM_BIT_TO_SECT(mdev->rs_total - 1);
+                       mdev->rs_total = 1;
+               } else
+                       mdev->rs_total -= bit;
                mdev->ov_position = mdev->ov_start_sector;
        }
+       mdev->ov_left = mdev->rs_total;
 }
 
 static void drbd_resume_al(struct drbd_conf *mdev)
@@ -992,12 +1036,12 @@ static void drbd_resume_al(struct drbd_conf *mdev)
  *
  * Caller needs to hold req_lock, and global_state_lock. Do not call directly.
  */
-int __drbd_set_state(struct drbd_conf *mdev,
-                   union drbd_state ns, enum chg_state_flags flags,
-                   struct completion *done)
+enum drbd_state_rv
+__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+                enum chg_state_flags flags, struct completion *done)
 {
        union drbd_state os;
-       int rv = SS_SUCCESS;
+       enum drbd_state_rv rv = SS_SUCCESS;
        const char *warn_sync_abort = NULL;
        struct after_state_chg_work *ascw;
 
@@ -1033,22 +1077,46 @@ int __drbd_set_state(struct drbd_conf *mdev,
                dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
 
        {
-               char *pbp, pb[300];
-               pbp = pb;
-               *pbp = 0;
-               PSC(role);
-               PSC(peer);
-               PSC(conn);
-               PSC(disk);
-               PSC(pdsk);
-               if (is_susp(ns) != is_susp(os))
-                       pbp += sprintf(pbp, "susp( %s -> %s ) ",
-                                      drbd_susp_str(is_susp(os)),
-                                      drbd_susp_str(is_susp(ns)));
-               PSC(aftr_isp);
-               PSC(peer_isp);
-               PSC(user_isp);
-               dev_info(DEV, "%s\n", pb);
+       char *pbp, pb[300];
+       pbp = pb;
+       *pbp = 0;
+       if (ns.role != os.role)
+               pbp += sprintf(pbp, "role( %s -> %s ) ",
+                              drbd_role_str(os.role),
+                              drbd_role_str(ns.role));
+       if (ns.peer != os.peer)
+               pbp += sprintf(pbp, "peer( %s -> %s ) ",
+                              drbd_role_str(os.peer),
+                              drbd_role_str(ns.peer));
+       if (ns.conn != os.conn)
+               pbp += sprintf(pbp, "conn( %s -> %s ) ",
+                              drbd_conn_str(os.conn),
+                              drbd_conn_str(ns.conn));
+       if (ns.disk != os.disk)
+               pbp += sprintf(pbp, "disk( %s -> %s ) ",
+                              drbd_disk_str(os.disk),
+                              drbd_disk_str(ns.disk));
+       if (ns.pdsk != os.pdsk)
+               pbp += sprintf(pbp, "pdsk( %s -> %s ) ",
+                              drbd_disk_str(os.pdsk),
+                              drbd_disk_str(ns.pdsk));
+       if (is_susp(ns) != is_susp(os))
+               pbp += sprintf(pbp, "susp( %d -> %d ) ",
+                              is_susp(os),
+                              is_susp(ns));
+       if (ns.aftr_isp != os.aftr_isp)
+               pbp += sprintf(pbp, "aftr_isp( %d -> %d ) ",
+                              os.aftr_isp,
+                              ns.aftr_isp);
+       if (ns.peer_isp != os.peer_isp)
+               pbp += sprintf(pbp, "peer_isp( %d -> %d ) ",
+                              os.peer_isp,
+                              ns.peer_isp);
+       if (ns.user_isp != os.user_isp)
+               pbp += sprintf(pbp, "user_isp( %d -> %d ) ",
+                              os.user_isp,
+                              ns.user_isp);
+       dev_info(DEV, "%s\n", pb);
        }
 
        /* solve the race between becoming unconfigured,
@@ -1074,6 +1142,10 @@ int __drbd_set_state(struct drbd_conf *mdev,
                atomic_inc(&mdev->local_cnt);
 
        mdev->state = ns;
+
+       if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
+               drbd_print_uuids(mdev, "attached to UUIDs");
+
        wake_up(&mdev->misc_wait);
        wake_up(&mdev->state_wait);
 
@@ -1081,7 +1153,7 @@ int __drbd_set_state(struct drbd_conf *mdev,
        if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
            ns.conn < C_CONNECTED) {
                mdev->ov_start_sector =
-                       BM_BIT_TO_SECT(mdev->rs_total - mdev->ov_left);
+                       BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left);
                dev_info(DEV, "Online Verify reached sector %llu\n",
                        (unsigned long long)mdev->ov_start_sector);
        }
@@ -1106,14 +1178,7 @@ int __drbd_set_state(struct drbd_conf *mdev,
                unsigned long now = jiffies;
                int i;
 
-               mdev->ov_position = 0;
-               mdev->rs_total = drbd_bm_bits(mdev);
-               if (mdev->agreed_pro_version >= 90)
-                       set_ov_position(mdev, ns.conn);
-               else
-                       mdev->ov_start_sector = 0;
-               mdev->ov_left = mdev->rs_total
-                             - BM_SECT_TO_BIT(mdev->ov_position);
+               set_ov_position(mdev, ns.conn);
                mdev->rs_start = now;
                mdev->rs_last_events = 0;
                mdev->rs_last_sect_ev = 0;
@@ -1121,10 +1186,12 @@ int __drbd_set_state(struct drbd_conf *mdev,
                mdev->ov_last_oos_start = 0;
 
                for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-                       mdev->rs_mark_left[i] = mdev->rs_total;
+                       mdev->rs_mark_left[i] = mdev->ov_left;
                        mdev->rs_mark_time[i] = now;
                }
 
+               drbd_rs_controller_reset(mdev);
+
                if (ns.conn == C_VERIFY_S) {
                        dev_info(DEV, "Starting Online Verify from sector %llu\n",
                                        (unsigned long long)mdev->ov_position);
@@ -1228,6 +1295,26 @@ static void abw_start_sync(struct drbd_conf *mdev, int rv)
        }
 }
 
+int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
+               int (*io_fn)(struct drbd_conf *),
+               char *why, enum bm_flag flags)
+{
+       int rv;
+
+       D_ASSERT(current == mdev->worker.task);
+
+       /* open coded non-blocking drbd_suspend_io(mdev); */
+       set_bit(SUSPEND_IO, &mdev->flags);
+
+       drbd_bm_lock(mdev, why, flags);
+       rv = io_fn(mdev);
+       drbd_bm_unlock(mdev);
+
+       drbd_resume_io(mdev);
+
+       return rv;
+}
+
 /**
  * after_state_ch() - Perform after state change actions that may sleep
  * @mdev:      DRBD device.
@@ -1266,16 +1353,14 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 
        nsm.i = -1;
        if (ns.susp_nod) {
-               if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
-                       if (ns.conn == C_CONNECTED)
-                               what = resend, nsm.susp_nod = 0;
-                       else /* ns.conn > C_CONNECTED */
-                               dev_err(DEV, "Unexpected Resynd going on!\n");
-               }
+               if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+                       what = resend;
 
                if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
-                       what = restart_frozen_disk_io, nsm.susp_nod = 0;
+                       what = restart_frozen_disk_io;
 
+               if (what != nothing)
+                       nsm.susp_nod = 0;
        }
 
        if (ns.susp_fen) {
@@ -1306,13 +1391,30 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
                spin_unlock_irq(&mdev->req_lock);
        }
 
+       /* Became sync source.  With protocol >= 96, we still need to send out
+        * the sync uuid now. Need to do that before any drbd_send_state, or
+        * the other side may go "paused sync" before receiving the sync uuids,
+        * which is unexpected. */
+       if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
+           (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
+           mdev->agreed_pro_version >= 96 && get_ldev(mdev)) {
+               drbd_gen_and_send_sync_uuid(mdev);
+               put_ldev(mdev);
+       }
+
        /* Do not change the order of the if above and the two below... */
        if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) {      /* attach on the peer */
                drbd_send_uuids(mdev);
                drbd_send_state(mdev);
        }
-       if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S)
-               drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL, "send_bitmap (WFBitMapS)");
+       /* No point in queuing send_bitmap if we don't have a connection
+        * anymore, so check also the _current_ state, not only the new state
+        * at the time this work was queued. */
+       if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S &&
+           mdev->state.conn == C_WF_BITMAP_S)
+               drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL,
+                               "send_bitmap (WFBitMapS)",
+                               BM_LOCKED_TEST_ALLOWED);
 
        /* Lost contact to peer's copy of the data */
        if ((os.pdsk >= D_INCONSISTENT &&
@@ -1343,7 +1445,23 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 
                /* D_DISKLESS Peer becomes secondary */
                if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
-                       drbd_al_to_on_disk_bm(mdev);
+                       /* We may still be Primary ourselves.
+                        * No harm done if the bitmap still changes,
+                        * redirtied pages will follow later. */
+                       drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+                               "demote diskless peer", BM_LOCKED_SET_ALLOWED);
+               put_ldev(mdev);
+       }
+
+       /* Write out all changed bits on demote.
+        * Though, no need to da that just yet
+        * if there is a resync going on still */
+       if (os.role == R_PRIMARY && ns.role == R_SECONDARY &&
+               mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) {
+               /* No changes to the bitmap expected this time, so assert that,
+                * even though no harm was done if it did change. */
+               drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+                               "demote", BM_LOCKED_TEST_ALLOWED);
                put_ldev(mdev);
        }
 
@@ -1371,15 +1489,23 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
                drbd_send_state(mdev);
 
+       if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
+               drbd_send_state(mdev);
+
        /* We are in the progress to start a full sync... */
        if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
            (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S))
-               drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, &abw_start_sync, "set_n_write from StartingSync");
+               /* no other bitmap changes expected during this phase */
+               drbd_queue_bitmap_io(mdev,
+                       &drbd_bmio_set_n_write, &abw_start_sync,
+                       "set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
 
        /* We are invalidating our self... */
        if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED &&
            os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
-               drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate");
+               /* other bitmap operation expected during this phase */
+               drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL,
+                       "set_n_write from invalidate", BM_LOCKED_MASK);
 
        /* first half of local IO error, failure to attach,
         * or administrative detach */
@@ -1434,8 +1560,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 
                if (drbd_send_state(mdev))
                        dev_warn(DEV, "Notified peer that I'm now diskless.\n");
-               else
-                       dev_err(DEV, "Sending state for being diskless failed\n");
                /* corresponding get_ldev in __drbd_set_state
                 * this may finaly trigger drbd_ldev_destroy. */
                put_ldev(mdev);
@@ -1459,6 +1583,19 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
                drbd_send_state(mdev);
 
+       /* This triggers bitmap writeout of potentially still unwritten pages
+        * if the resync finished cleanly, or aborted because of peer disk
+        * failure, or because of connection loss.
+        * For resync aborted because of local disk failure, we cannot do
+        * any bitmap writeout anymore.
+        * No harm done if some bits change during this phase.
+        */
+       if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
+               drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL,
+                       "write from resync_finished", BM_LOCKED_SET_ALLOWED);
+               put_ldev(mdev);
+       }
+
        /* free tl_hash if we Got thawed and are C_STANDALONE */
        if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
                drbd_free_tl_hash(mdev);
@@ -1559,7 +1696,7 @@ int drbd_thread_start(struct drbd_thread *thi)
                if (!try_module_get(THIS_MODULE)) {
                        dev_err(DEV, "Failed to get module reference in drbd_thread_start\n");
                        spin_unlock_irqrestore(&thi->t_lock, flags);
-                       return FALSE;
+                       return false;
                }
 
                init_completion(&thi->stop);
@@ -1576,7 +1713,7 @@ int drbd_thread_start(struct drbd_thread *thi)
                        dev_err(DEV, "Couldn't start thread\n");
 
                        module_put(THIS_MODULE);
-                       return FALSE;
+                       return false;
                }
                spin_lock_irqsave(&thi->t_lock, flags);
                thi->task = nt;
@@ -1596,7 +1733,7 @@ int drbd_thread_start(struct drbd_thread *thi)
                break;
        }
 
-       return TRUE;
+       return true;
 }
 
 
@@ -1694,8 +1831,8 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
 {
        int sent, ok;
 
-       ERR_IF(!h) return FALSE;
-       ERR_IF(!size) return FALSE;
+       ERR_IF(!h) return false;
+       ERR_IF(!size) return false;
 
        h->magic   = BE_DRBD_MAGIC;
        h->command = cpu_to_be16(cmd);
@@ -1704,8 +1841,8 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
        sent = drbd_send(mdev, sock, h, size, msg_flags);
 
        ok = (sent == size);
-       if (!ok)
-               dev_err(DEV, "short sent %s size=%d sent=%d\n",
+       if (!ok && !signal_pending(current))
+               dev_warn(DEV, "short sent %s size=%d sent=%d\n",
                    cmdname(cmd), (int)size, sent);
        return ok;
 }
@@ -1840,7 +1977,7 @@ int drbd_send_protocol(struct drbd_conf *mdev)
                else {
                        dev_err(DEV, "--dry-run is not supported by peer");
                        kfree(p);
-                       return 0;
+                       return -1;
                }
        }
        p->conn_flags    = cpu_to_be32(cf);
@@ -1888,12 +2025,36 @@ int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev)
        return _drbd_send_uuids(mdev, 8);
 }
 
+void drbd_print_uuids(struct drbd_conf *mdev, const char *text)
+{
+       if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
+               u64 *uuid = mdev->ldev->md.uuid;
+               dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX\n",
+                    text,
+                    (unsigned long long)uuid[UI_CURRENT],
+                    (unsigned long long)uuid[UI_BITMAP],
+                    (unsigned long long)uuid[UI_HISTORY_START],
+                    (unsigned long long)uuid[UI_HISTORY_END]);
+               put_ldev(mdev);
+       } else {
+               dev_info(DEV, "%s effective data uuid: %016llX\n",
+                               text,
+                               (unsigned long long)mdev->ed_uuid);
+       }
+}
 
-int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val)
+int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
 {
        struct p_rs_uuid p;
+       u64 uuid;
 
-       p.uuid = cpu_to_be64(val);
+       D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
+
+       uuid = mdev->ldev->md.uuid[UI_BITMAP] + UUID_NEW_BM_OFFSET;
+       drbd_uuid_set(mdev, UI_BITMAP, uuid);
+       drbd_print_uuids(mdev, "updated sync UUID");
+       drbd_md_sync(mdev);
+       p.uuid = cpu_to_be64(uuid);
 
        return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
                             (struct p_header80 *)&p, sizeof(p));
@@ -1921,7 +2082,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
        p.d_size = cpu_to_be64(d_size);
        p.u_size = cpu_to_be64(u_size);
        p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
-       p.max_segment_size = cpu_to_be32(queue_max_segment_size(mdev->rq_queue));
+       p.max_bio_size = cpu_to_be32(queue_max_hw_sectors(mdev->rq_queue) << 9);
        p.queue_order_type = cpu_to_be16(q_order_type);
        p.dds_flags = cpu_to_be16(flags);
 
@@ -1972,7 +2133,7 @@ int drbd_send_state_req(struct drbd_conf *mdev,
                             (struct p_header80 *)&p, sizeof(p));
 }
 
-int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
+int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode)
 {
        struct p_req_state_reply p;
 
@@ -2076,9 +2237,15 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
        return len;
 }
 
-enum { OK, FAILED, DONE }
+/**
+ * send_bitmap_rle_or_plain
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 send_bitmap_rle_or_plain(struct drbd_conf *mdev,
-       struct p_header80 *h, struct bm_xfer_ctx *c)
+                        struct p_header80 *h, struct bm_xfer_ctx *c)
 {
        struct p_compressed_bm *p = (void*)h;
        unsigned long num_words;
@@ -2088,7 +2255,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev,
        len = fill_bitmap_rle_bits(mdev, p, c);
 
        if (len < 0)
-               return FAILED;
+               return -EIO;
 
        if (len) {
                DCBP_set_code(p, RLE_VLI_Bits);
@@ -2118,11 +2285,14 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev,
                if (c->bit_offset > c->bm_bits)
                        c->bit_offset = c->bm_bits;
        }
-       ok = ok ? ((len == 0) ? DONE : OK) : FAILED;
-
-       if (ok == DONE)
-               INFO_bm_xfer_stats(mdev, "send", c);
-       return ok;
+       if (ok) {
+               if (len == 0) {
+                       INFO_bm_xfer_stats(mdev, "send", c);
+                       return 0;
+               } else
+                       return 1;
+       }
+       return -EIO;
 }
 
 /* See the comment at receive_bitmap() */
@@ -2130,16 +2300,16 @@ int _drbd_send_bitmap(struct drbd_conf *mdev)
 {
        struct bm_xfer_ctx c;
        struct p_header80 *p;
-       int ret;
+       int err;
 
-       ERR_IF(!mdev->bitmap) return FALSE;
+       ERR_IF(!mdev->bitmap) return false;
 
        /* maybe we should use some per thread scratch page,
         * and allocate that during initial device creation? */
        p = (struct p_header80 *) __get_free_page(GFP_NOIO);
        if (!p) {
                dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
-               return FALSE;
+               return false;
        }
 
        if (get_ldev(mdev)) {
@@ -2165,11 +2335,11 @@ int _drbd_send_bitmap(struct drbd_conf *mdev)
        };
 
        do {
-               ret = send_bitmap_rle_or_plain(mdev, p, &c);
-       } while (ret == OK);
+               err = send_bitmap_rle_or_plain(mdev, p, &c);
+       } while (err > 0);
 
        free_page((unsigned long) p);
-       return (ret == DONE);
+       return err == 0;
 }
 
 int drbd_send_bitmap(struct drbd_conf *mdev)
@@ -2192,7 +2362,7 @@ int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size)
        p.set_size = cpu_to_be32(set_size);
 
        if (mdev->state.conn < C_CONNECTED)
-               return FALSE;
+               return false;
        ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
                        (struct p_header80 *)&p, sizeof(p));
        return ok;
@@ -2220,7 +2390,7 @@ static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
        p.seq_num  = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq));
 
        if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
-               return FALSE;
+               return false;
        ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
                                (struct p_header80 *)&p, sizeof(p));
        return ok;
@@ -2326,8 +2496,8 @@ int drbd_send_ov_request(struct drbd_conf *mdev, sector_t sector, int size)
 }
 
 /* called on sndtimeo
- * returns FALSE if we should retry,
- * TRUE if we think connection is dead
+ * returns false if we should retry,
+ * true if we think connection is dead
  */
 static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *sock)
 {
@@ -2340,7 +2510,7 @@ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *
                || mdev->state.conn < C_CONNECTED;
 
        if (drop_it)
-               return TRUE;
+               return true;
 
        drop_it = !--mdev->ko_count;
        if (!drop_it) {
@@ -2531,13 +2701,39 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
        if (ok && dgs) {
                dgb = mdev->int_dig_out;
                drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
-               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
+               ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
        }
        if (ok) {
-               if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
+               /* For protocol A, we have to memcpy the payload into
+                * socket buffers, as we may complete right away
+                * as soon as we handed it over to tcp, at which point the data
+                * pages may become invalid.
+                *
+                * For data-integrity enabled, we copy it as well, so we can be
+                * sure that even if the bio pages may still be modified, it
+                * won't change the data on the wire, thus if the digest checks
+                * out ok after sending on this side, but does not fit on the
+                * receiving side, we sure have detected corruption elsewhere.
+                */
+               if (mdev->net_conf->wire_protocol == DRBD_PROT_A || dgs)
                        ok = _drbd_send_bio(mdev, req->master_bio);
                else
                        ok = _drbd_send_zc_bio(mdev, req->master_bio);
+
+               /* double check digest, sometimes buffers have been modified in flight. */
+               if (dgs > 0 && dgs <= 64) {
+                       /* 64 byte, 512 bit, is the larges digest size
+                        * currently supported in kernel crypto. */
+                       unsigned char digest[64];
+                       drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, digest);
+                       if (memcmp(mdev->int_dig_out, digest, dgs)) {
+                               dev_warn(DEV,
+                                       "Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
+                                       (unsigned long long)req->sector, req->size);
+                       }
+               } /* else if (dgs > 64) {
+                    ... Be noisy about digest too large ...
+               } */
        }
 
        drbd_put_data_sock(mdev);
@@ -2587,7 +2783,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
        if (ok && dgs) {
                dgb = mdev->int_dig_out;
                drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
-               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
+               ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
        }
        if (ok)
                ok = _drbd_send_zc_ee(mdev, e);
@@ -2597,6 +2793,16 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
        return ok;
 }
 
+int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req)
+{
+       struct p_block_desc p;
+
+       p.sector  = cpu_to_be64(req->sector);
+       p.blksize = cpu_to_be32(req->size);
+
+       return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p));
+}
+
 /*
   drbd_send distinguishes two cases:
 
@@ -2770,6 +2976,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        atomic_set(&mdev->pp_in_use_by_net, 0);
        atomic_set(&mdev->rs_sect_in, 0);
        atomic_set(&mdev->rs_sect_ev, 0);
+       atomic_set(&mdev->ap_in_flight, 0);
 
        mutex_init(&mdev->md_io_mutex);
        mutex_init(&mdev->data.mutex);
@@ -2798,19 +3005,27 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        INIT_LIST_HEAD(&mdev->unplug_work.list);
        INIT_LIST_HEAD(&mdev->go_diskless.list);
        INIT_LIST_HEAD(&mdev->md_sync_work.list);
+       INIT_LIST_HEAD(&mdev->start_resync_work.list);
        INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
 
-       mdev->resync_work.cb  = w_resync_inactive;
+       mdev->resync_work.cb  = w_resync_timer;
        mdev->unplug_work.cb  = w_send_write_hint;
        mdev->go_diskless.cb  = w_go_diskless;
        mdev->md_sync_work.cb = w_md_sync;
        mdev->bm_io_work.w.cb = w_bitmap_io;
+       mdev->start_resync_work.cb = w_start_resync;
        init_timer(&mdev->resync_timer);
        init_timer(&mdev->md_sync_timer);
+       init_timer(&mdev->start_resync_timer);
+       init_timer(&mdev->request_timer);
        mdev->resync_timer.function = resync_timer_fn;
        mdev->resync_timer.data = (unsigned long) mdev;
        mdev->md_sync_timer.function = md_sync_timer_fn;
        mdev->md_sync_timer.data = (unsigned long) mdev;
+       mdev->start_resync_timer.function = start_resync_timer_fn;
+       mdev->start_resync_timer.data = (unsigned long) mdev;
+       mdev->request_timer.function = request_timer_fn;
+       mdev->request_timer.data = (unsigned long) mdev;
 
        init_waitqueue_head(&mdev->misc_wait);
        init_waitqueue_head(&mdev->state_wait);
@@ -2881,6 +3096,8 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
        D_ASSERT(list_empty(&mdev->resync_work.list));
        D_ASSERT(list_empty(&mdev->unplug_work.list));
        D_ASSERT(list_empty(&mdev->go_diskless.list));
+
+       drbd_set_defaults(mdev);
 }
 
 
@@ -2923,7 +3140,7 @@ static void drbd_destroy_mempools(void)
 static int drbd_create_mempools(void)
 {
        struct page *page;
-       const int number = (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE) * minor_count;
+       const int number = (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * minor_count;
        int i;
 
        /* prepare our caches and mempools */
@@ -3087,11 +3304,20 @@ static void drbd_cleanup(void)
 
        unregister_reboot_notifier(&drbd_notifier);
 
+       /* first remove proc,
+        * drbdsetup uses it's presence to detect
+        * whether DRBD is loaded.
+        * If we would get stuck in proc removal,
+        * but have netlink already deregistered,
+        * some drbdsetup commands may wait forever
+        * for an answer.
+        */
+       if (drbd_proc)
+               remove_proc_entry("drbd", NULL);
+
        drbd_nl_cleanup();
 
        if (minor_table) {
-               if (drbd_proc)
-                       remove_proc_entry("drbd", NULL);
                i = minor_count;
                while (i--)
                        drbd_delete_device(i);
@@ -3119,7 +3345,7 @@ static int drbd_congested(void *congested_data, int bdi_bits)
        char reason = '-';
        int r = 0;
 
-       if (!__inc_ap_bio_cond(mdev)) {
+       if (!may_inc_ap_bio(mdev)) {
                /* DRBD has frozen IO */
                r = bdi_bits;
                reason = 'd';
@@ -3172,7 +3398,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
                goto out_no_disk;
        mdev->vdisk = disk;
 
-       set_disk_ro(disk, TRUE);
+       set_disk_ro(disk, true);
 
        disk->queue = q;
        disk->major = DRBD_MAJOR;
@@ -3188,8 +3414,8 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
        q->backing_dev_info.congested_fn = drbd_congested;
        q->backing_dev_info.congested_data = mdev;
 
-       blk_queue_make_request(q, drbd_make_request_26);
-       blk_queue_max_segment_size(q, DRBD_MAX_SEGMENT_SIZE);
+       blk_queue_make_request(q, drbd_make_request);
+       blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9);
        blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
        blk_queue_merge_bvec(q, drbd_merge_bvec);
        q->queue_lock = &mdev->req_lock;
@@ -3251,6 +3477,7 @@ void drbd_free_mdev(struct drbd_conf *mdev)
        put_disk(mdev->vdisk);
        blk_cleanup_queue(mdev->rq_queue);
        free_cpumask_var(mdev->cpu_mask);
+       drbd_free_tl_hash(mdev);
        kfree(mdev);
 }
 
@@ -3266,7 +3493,7 @@ int __init drbd_init(void)
                return -EINVAL;
        }
 
-       if (1 > minor_count || minor_count > 255) {
+       if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
                printk(KERN_ERR
                        "drbd: invalid minor_count (%d)\n", minor_count);
 #ifdef MODULE
@@ -3448,7 +3675,7 @@ void drbd_md_sync(struct drbd_conf *mdev)
        if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
                /* this was a try anyways ... */
                dev_err(DEV, "meta data update failed!\n");
-               drbd_chk_io_error(mdev, 1, TRUE);
+               drbd_chk_io_error(mdev, 1, true);
        }
 
        /* Update mdev->ldev->md.la_size_sect,
@@ -3464,7 +3691,7 @@ void drbd_md_sync(struct drbd_conf *mdev)
  * @mdev:      DRBD device.
  * @bdev:      Device from which the meta data should be read in.
  *
- * Return 0 (NO_ERROR) on success, and an enum drbd_ret_codes in case
+ * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case
  * something goes wrong.  Currently only: ERR_IO_MD_DISK, ERR_MD_INVALID.
  */
 int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
@@ -3534,28 +3761,6 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
        return rv;
 }
 
-static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
-{
-       static char *uuid_str[UI_EXTENDED_SIZE] = {
-               [UI_CURRENT] = "CURRENT",
-               [UI_BITMAP] = "BITMAP",
-               [UI_HISTORY_START] = "HISTORY_START",
-               [UI_HISTORY_END] = "HISTORY_END",
-               [UI_SIZE] = "SIZE",
-               [UI_FLAGS] = "FLAGS",
-       };
-
-       if (index >= UI_EXTENDED_SIZE) {
-               dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
-               return;
-       }
-
-       dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n",
-                uuid_str[index],
-                (unsigned long long)mdev->ldev->md.uuid[index]);
-}
-
-
 /**
  * drbd_md_mark_dirty() - Mark meta data super block as dirty
  * @mdev:      DRBD device.
@@ -3585,10 +3790,8 @@ static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
 {
        int i;
 
-       for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) {
+       for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
                mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
-               debug_drbd_uuid(mdev, i+1);
-       }
 }
 
 void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
@@ -3603,7 +3806,6 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
        }
 
        mdev->ldev->md.uuid[idx] = val;
-       debug_drbd_uuid(mdev, idx);
        drbd_md_mark_dirty(mdev);
 }
 
@@ -3613,7 +3815,6 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
        if (mdev->ldev->md.uuid[idx]) {
                drbd_uuid_move_history(mdev);
                mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
-               debug_drbd_uuid(mdev, UI_HISTORY_START);
        }
        _drbd_uuid_set(mdev, idx, val);
 }
@@ -3628,14 +3829,16 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
 void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
 {
        u64 val;
+       unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+
+       if (bm_uuid)
+               dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
 
-       dev_info(DEV, "Creating new current UUID\n");
-       D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0);
        mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
-       debug_drbd_uuid(mdev, UI_BITMAP);
 
        get_random_bytes(&val, sizeof(u64));
        _drbd_uuid_set(mdev, UI_CURRENT, val);
+       drbd_print_uuids(mdev, "new current UUID");
        /* get it to stable storage _now_ */
        drbd_md_sync(mdev);
 }
@@ -3649,16 +3852,12 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
                drbd_uuid_move_history(mdev);
                mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
                mdev->ldev->md.uuid[UI_BITMAP] = 0;
-               debug_drbd_uuid(mdev, UI_HISTORY_START);
-               debug_drbd_uuid(mdev, UI_BITMAP);
        } else {
-               if (mdev->ldev->md.uuid[UI_BITMAP])
-                       dev_warn(DEV, "bm UUID already set");
-
-               mdev->ldev->md.uuid[UI_BITMAP] = val;
-               mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1);
+               unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+               if (bm_uuid)
+                       dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
 
-               debug_drbd_uuid(mdev, UI_BITMAP);
+               mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
        }
        drbd_md_mark_dirty(mdev);
 }
@@ -3714,15 +3913,19 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev)
 static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
        struct bm_io_work *work = container_of(w, struct bm_io_work, w);
-       int rv;
+       int rv = -EIO;
 
        D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0);
 
-       drbd_bm_lock(mdev, work->why);
-       rv = work->io_fn(mdev);
-       drbd_bm_unlock(mdev);
+       if (get_ldev(mdev)) {
+               drbd_bm_lock(mdev, work->why, work->flags);
+               rv = work->io_fn(mdev);
+               drbd_bm_unlock(mdev);
+               put_ldev(mdev);
+       }
 
        clear_bit(BITMAP_IO, &mdev->flags);
+       smp_mb__after_clear_bit();
        wake_up(&mdev->misc_wait);
 
        if (work->done)
@@ -3730,6 +3933,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 
        clear_bit(BITMAP_IO_QUEUED, &mdev->flags);
        work->why = NULL;
+       work->flags = 0;
 
        return 1;
 }
@@ -3784,7 +3988,7 @@ void drbd_go_diskless(struct drbd_conf *mdev)
 void drbd_queue_bitmap_io(struct drbd_conf *mdev,
                          int (*io_fn)(struct drbd_conf *),
                          void (*done)(struct drbd_conf *, int),
-                         char *why)
+                         char *why, enum bm_flag flags)
 {
        D_ASSERT(current == mdev->worker.task);
 
@@ -3798,15 +4002,15 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev,
        mdev->bm_io_work.io_fn = io_fn;
        mdev->bm_io_work.done = done;
        mdev->bm_io_work.why = why;
+       mdev->bm_io_work.flags = flags;
 
+       spin_lock_irq(&mdev->req_lock);
        set_bit(BITMAP_IO, &mdev->flags);
        if (atomic_read(&mdev->ap_bio_cnt) == 0) {
-               if (list_empty(&mdev->bm_io_work.w.list)) {
-                       set_bit(BITMAP_IO_QUEUED, &mdev->flags);
+               if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
                        drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w);
-               } else
-                       dev_err(DEV, "FIXME avoided double queuing bm_io_work\n");
        }
+       spin_unlock_irq(&mdev->req_lock);
 }
 
 /**
@@ -3818,19 +4022,22 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev,
  * freezes application IO while that the actual IO operations runs. This
  * functions MAY NOT be called from worker context.
  */
-int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why)
+int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *),
+               char *why, enum bm_flag flags)
 {
        int rv;
 
        D_ASSERT(current != mdev->worker.task);
 
-       drbd_suspend_io(mdev);
+       if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
+               drbd_suspend_io(mdev);
 
-       drbd_bm_lock(mdev, why);
+       drbd_bm_lock(mdev, why, flags);
        rv = io_fn(mdev);
        drbd_bm_unlock(mdev);
 
-       drbd_resume_io(mdev);
+       if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
+               drbd_resume_io(mdev);
 
        return rv;
 }
index fe81c851ca8800fdce14bccc3c7be032b7263669..03b29f78a37d78ac8955db9ae43ca8609b963d91 100644 (file)
@@ -288,10 +288,11 @@ void drbd_try_outdate_peer_async(struct drbd_conf *mdev)
                dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
 }
 
-int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
+enum drbd_state_rv
+drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 {
        const int max_tries = 4;
-       int r = 0;
+       enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
        int try = 0;
        int forced = 0;
        union drbd_state mask, val;
@@ -306,17 +307,17 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
        val.i  = 0; val.role  = new_role;
 
        while (try++ < max_tries) {
-               r = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE);
+               rv = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE);
 
                /* in case we first succeeded to outdate,
                 * but now suddenly could establish a connection */
-               if (r == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) {
+               if (rv == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) {
                        val.pdsk = 0;
                        mask.pdsk = 0;
                        continue;
                }
 
-               if (r == SS_NO_UP_TO_DATE_DISK && force &&
+               if (rv == SS_NO_UP_TO_DATE_DISK && force &&
                    (mdev->state.disk < D_UP_TO_DATE &&
                     mdev->state.disk >= D_INCONSISTENT)) {
                        mask.disk = D_MASK;
@@ -325,7 +326,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
                        continue;
                }
 
-               if (r == SS_NO_UP_TO_DATE_DISK &&
+               if (rv == SS_NO_UP_TO_DATE_DISK &&
                    mdev->state.disk == D_CONSISTENT && mask.pdsk == 0) {
                        D_ASSERT(mdev->state.pdsk == D_UNKNOWN);
                        nps = drbd_try_outdate_peer(mdev);
@@ -341,9 +342,9 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
                        continue;
                }
 
-               if (r == SS_NOTHING_TO_DO)
+               if (rv == SS_NOTHING_TO_DO)
                        goto fail;
-               if (r == SS_PRIMARY_NOP && mask.pdsk == 0) {
+               if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
                        nps = drbd_try_outdate_peer(mdev);
 
                        if (force && nps > D_OUTDATED) {
@@ -356,25 +357,24 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 
                        continue;
                }
-               if (r == SS_TWO_PRIMARIES) {
+               if (rv == SS_TWO_PRIMARIES) {
                        /* Maybe the peer is detected as dead very soon...
                           retry at most once more in this case. */
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout((mdev->net_conf->ping_timeo+1)*HZ/10);
+                       schedule_timeout_interruptible((mdev->net_conf->ping_timeo+1)*HZ/10);
                        if (try < max_tries)
                                try = max_tries - 1;
                        continue;
                }
-               if (r < SS_SUCCESS) {
-                       r = _drbd_request_state(mdev, mask, val,
+               if (rv < SS_SUCCESS) {
+                       rv = _drbd_request_state(mdev, mask, val,
                                                CS_VERBOSE + CS_WAIT_COMPLETE);
-                       if (r < SS_SUCCESS)
+                       if (rv < SS_SUCCESS)
                                goto fail;
                }
                break;
        }
 
-       if (r < SS_SUCCESS)
+       if (rv < SS_SUCCESS)
                goto fail;
 
        if (forced)
@@ -384,7 +384,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
        wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0);
 
        if (new_role == R_SECONDARY) {
-               set_disk_ro(mdev->vdisk, TRUE);
+               set_disk_ro(mdev->vdisk, true);
                if (get_ldev(mdev)) {
                        mdev->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
                        put_ldev(mdev);
@@ -394,7 +394,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
                        mdev->net_conf->want_lose = 0;
                        put_net_conf(mdev);
                }
-               set_disk_ro(mdev->vdisk, FALSE);
+               set_disk_ro(mdev->vdisk, false);
                if (get_ldev(mdev)) {
                        if (((mdev->state.conn < C_CONNECTED ||
                               mdev->state.pdsk <= D_FAILED)
@@ -406,10 +406,8 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
                }
        }
 
-       if ((new_role == R_SECONDARY) && get_ldev(mdev)) {
-               drbd_al_to_on_disk_bm(mdev);
-               put_ldev(mdev);
-       }
+       /* writeout of activity log covered areas of the bitmap
+        * to stable storage done in after state change already */
 
        if (mdev->state.conn >= C_WF_REPORT_PARAMS) {
                /* if this was forced, we should consider sync */
@@ -423,7 +421,7 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
        kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
  fail:
        mutex_unlock(&mdev->state_mutex);
-       return r;
+       return rv;
 }
 
 static struct drbd_conf *ensure_mdev(int minor, int create)
@@ -528,17 +526,19 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
        }
 }
 
+/* input size is expected to be in KB */
 char *ppsize(char *buf, unsigned long long size)
 {
-       /* Needs 9 bytes at max. */
+       /* Needs 9 bytes at max including trailing NUL:
+        * -1ULL ==> "16384 EB" */
        static char units[] = { 'K', 'M', 'G', 'T', 'P', 'E' };
        int base = 0;
-       while (size >= 10000) {
+       while (size >= 10000 && base < sizeof(units)-1) {
                /* shift + round */
                size = (size >> 10) + !!(size & (1<<9));
                base++;
        }
-       sprintf(buf, "%lu %cB", (long)size, units[base]);
+       sprintf(buf, "%u %cB", (unsigned)size, units[base]);
 
        return buf;
 }
@@ -642,11 +642,19 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, enum dds_
                || prev_size       != mdev->ldev->md.md_size_sect;
 
        if (la_size_changed || md_moved) {
+               int err;
+
                drbd_al_shrink(mdev); /* All extents inactive. */
                dev_info(DEV, "Writing the whole bitmap, %s\n",
                         la_size_changed && md_moved ? "size changed and md moved" :
                         la_size_changed ? "size changed" : "md moved");
-               rv = drbd_bitmap_io(mdev, &drbd_bm_write, "size changed"); /* does drbd_resume_io() ! */
+               /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
+               err = drbd_bitmap_io(mdev, &drbd_bm_write,
+                               "size changed", BM_LOCKED_MASK);
+               if (err) {
+                       rv = dev_size_error;
+                       goto out;
+               }
                drbd_md_mark_dirty(mdev);
        }
 
@@ -765,22 +773,21 @@ static int drbd_check_al_size(struct drbd_conf *mdev)
        return 0;
 }
 
-void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __must_hold(local)
+void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) __must_hold(local)
 {
        struct request_queue * const q = mdev->rq_queue;
        struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
        int max_segments = mdev->ldev->dc.max_bio_bvecs;
+       int max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
 
-       max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s);
-
-       blk_queue_max_hw_sectors(q, max_seg_s >> 9);
-       blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
-       blk_queue_max_segment_size(q, max_seg_s);
        blk_queue_logical_block_size(q, 512);
-       blk_queue_segment_boundary(q, PAGE_SIZE-1);
-       blk_stack_limits(&q->limits, &b->limits, 0);
+       blk_queue_max_hw_sectors(q, max_hw_sectors);
+       /* This is the workaround for "bio would need to, but cannot, be split" */
+       blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
+       blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1);
+       blk_queue_stack_limits(q, b);
 
-       dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q));
+       dev_info(DEV, "max BIO size = %u\n", queue_max_hw_sectors(q) << 9);
 
        if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
                dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
@@ -850,7 +857,7 @@ static void drbd_suspend_al(struct drbd_conf *mdev)
 static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
                             struct drbd_nl_cfg_reply *reply)
 {
-       enum drbd_ret_codes retcode;
+       enum drbd_ret_code retcode;
        enum determine_dev_size dd;
        sector_t max_possible_sectors;
        sector_t min_md_device_sectors;
@@ -858,8 +865,8 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
        struct block_device *bdev;
        struct lru_cache *resync_lru = NULL;
        union drbd_state ns, os;
-       unsigned int max_seg_s;
-       int rv;
+       unsigned int max_bio_size;
+       enum drbd_state_rv rv;
        int cp_discovered = 0;
        int logical_block_size;
 
@@ -1005,9 +1012,10 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
        /* and for any other previously queued work */
        drbd_flush_workqueue(mdev);
 
-       retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
+       rv = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
+       retcode = rv;  /* FIXME: Type mismatch. */
        drbd_resume_io(mdev);
-       if (retcode < SS_SUCCESS)
+       if (rv < SS_SUCCESS)
                goto fail;
 
        if (!get_ldev_if_state(mdev, D_ATTACHING))
@@ -1109,20 +1117,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
        mdev->read_cnt = 0;
        mdev->writ_cnt = 0;
 
-       max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+       max_bio_size = DRBD_MAX_BIO_SIZE;
        if (mdev->state.conn == C_CONNECTED) {
                /* We are Primary, Connected, and now attach a new local
                 * backing store. We must not increase the user visible maximum
                 * bio size on this device to something the peer may not be
                 * able to handle. */
                if (mdev->agreed_pro_version < 94)
-                       max_seg_s = queue_max_segment_size(mdev->rq_queue);
+                       max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9;
                else if (mdev->agreed_pro_version == 94)
-                       max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+                       max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
                /* else: drbd 8.3.9 and later, stay with default */
        }
 
-       drbd_setup_queue_param(mdev, max_seg_s);
+       drbd_setup_queue_param(mdev, max_bio_size);
 
        /* If I am currently not R_PRIMARY,
         * but meta data primary indicator is set,
@@ -1154,12 +1162,14 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
        if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) {
                dev_info(DEV, "Assuming that all blocks are out of sync "
                     "(aka FullSync)\n");
-               if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from attaching")) {
+               if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
+                       "set_n_write from attaching", BM_LOCKED_MASK)) {
                        retcode = ERR_IO_MD_DISK;
                        goto force_diskless_dec;
                }
        } else {
-               if (drbd_bitmap_io(mdev, &drbd_bm_read, "read from attaching") < 0) {
+               if (drbd_bitmap_io(mdev, &drbd_bm_read,
+                       "read from attaching", BM_LOCKED_MASK) < 0) {
                        retcode = ERR_IO_MD_DISK;
                        goto force_diskless_dec;
                }
@@ -1167,7 +1177,11 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
        if (cp_discovered) {
                drbd_al_apply_to_bm(mdev);
-               drbd_al_to_on_disk_bm(mdev);
+               if (drbd_bitmap_io(mdev, &drbd_bm_write,
+                       "crashed primary apply AL", BM_LOCKED_MASK)) {
+                       retcode = ERR_IO_MD_DISK;
+                       goto force_diskless_dec;
+               }
        }
 
        if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
@@ -1279,7 +1293,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
                            struct drbd_nl_cfg_reply *reply)
 {
        int i, ns;
-       enum drbd_ret_codes retcode;
+       enum drbd_ret_code retcode;
        struct net_conf *new_conf = NULL;
        struct crypto_hash *tfm = NULL;
        struct crypto_hash *integrity_w_tfm = NULL;
@@ -1324,6 +1338,8 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
        new_conf->wire_protocol    = DRBD_PROT_C;
        new_conf->ping_timeo       = DRBD_PING_TIMEO_DEF;
        new_conf->rr_conflict      = DRBD_RR_CONFLICT_DEF;
+       new_conf->on_congestion    = DRBD_ON_CONGESTION_DEF;
+       new_conf->cong_extents     = DRBD_CONG_EXTENTS_DEF;
 
        if (!net_conf_from_tags(mdev, nlp->tag_list, new_conf)) {
                retcode = ERR_MANDATORY_TAG;
@@ -1345,6 +1361,11 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
                }
        }
 
+       if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) {
+               retcode = ERR_CONG_NOT_PROTO_A;
+               goto fail;
+       }
+
        if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
                retcode = ERR_DISCARD;
                goto fail;
@@ -1525,6 +1546,21 @@ static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
                              struct drbd_nl_cfg_reply *reply)
 {
        int retcode;
+       struct disconnect dc;
+
+       memset(&dc, 0, sizeof(struct disconnect));
+       if (!disconnect_from_tags(mdev, nlp->tag_list, &dc)) {
+               retcode = ERR_MANDATORY_TAG;
+               goto fail;
+       }
+
+       if (dc.force) {
+               spin_lock_irq(&mdev->req_lock);
+               if (mdev->state.conn >= C_WF_CONNECTION)
+                       _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), CS_HARD, NULL);
+               spin_unlock_irq(&mdev->req_lock);
+               goto done;
+       }
 
        retcode = _drbd_request_state(mdev, NS(conn, C_DISCONNECTING), CS_ORDERED);
 
@@ -1842,6 +1878,10 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 {
        int retcode;
 
+       /* If there is still bitmap IO pending, probably because of a previous
+        * resync just being finished, wait for it before requesting a new resync. */
+       wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
        retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED);
 
        if (retcode < SS_SUCCESS && retcode != SS_NEED_CONNECTION)
@@ -1877,6 +1917,10 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re
 {
        int retcode;
 
+       /* If there is still bitmap IO pending, probably because of a previous
+        * resync just being finished, wait for it before requesting a new resync. */
+       wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
        retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
 
        if (retcode < SS_SUCCESS) {
@@ -1885,9 +1929,9 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re
                           into a full resync. */
                        retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
                        if (retcode >= SS_SUCCESS) {
-                               /* open coded drbd_bitmap_io() */
                                if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
-                                                  "set_n_write from invalidate_peer"))
+                                       "set_n_write from invalidate_peer",
+                                       BM_LOCKED_SET_ALLOWED))
                                        retcode = ERR_IO_MD_DISK;
                        }
                } else
@@ -1914,9 +1958,17 @@ static int drbd_nl_resume_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
                               struct drbd_nl_cfg_reply *reply)
 {
        int retcode = NO_ERROR;
+       union drbd_state s;
 
-       if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO)
-               retcode = ERR_PAUSE_IS_CLEAR;
+       if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
+               s = mdev->state;
+               if (s.conn == C_PAUSED_SYNC_S || s.conn == C_PAUSED_SYNC_T) {
+                       retcode = s.aftr_isp ? ERR_PIC_AFTER_DEP :
+                                 s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR;
+               } else {
+                       retcode = ERR_PAUSE_IS_CLEAR;
+               }
+       }
 
        reply->ret_code = retcode;
        return 0;
@@ -2054,6 +2106,11 @@ static int drbd_nl_start_ov(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
                reply->ret_code = ERR_MANDATORY_TAG;
                return 0;
        }
+
+       /* If there is still bitmap IO pending, e.g. previous resync or verify
+        * just being finished, wait for it before requesting a new resync. */
+       wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
        /* w_make_ov_request expects position to be aligned */
        mdev->ov_start_sector = args.start_sector & ~BM_SECT_PER_BIT;
        reply->ret_code = drbd_request_state(mdev,NS(conn,C_VERIFY_S));
@@ -2097,7 +2154,8 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
        drbd_uuid_new_current(mdev); /* New current, previous to UI_BITMAP */
 
        if (args.clear_bm) {
-               err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write, "clear_n_write from new_c_uuid");
+               err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
+                       "clear_n_write from new_c_uuid", BM_LOCKED_MASK);
                if (err) {
                        dev_err(DEV, "Writing bitmap failed with %d\n",err);
                        retcode = ERR_IO_MD_DISK;
@@ -2105,6 +2163,7 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
                if (skip_initial_sync) {
                        drbd_send_uuids_skip_initial_sync(mdev);
                        _drbd_uuid_set(mdev, UI_BITMAP, 0);
+                       drbd_print_uuids(mdev, "cleared bitmap UUID");
                        spin_lock_irq(&mdev->req_lock);
                        _drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
                                        CS_VERBOSE, NULL);
@@ -2189,7 +2248,8 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
                goto fail;
        }
 
-       if (nlp->packet_type >= P_nl_after_last_packet) {
+       if (nlp->packet_type >= P_nl_after_last_packet ||
+           nlp->packet_type == P_return_code_only) {
                retcode = ERR_PACKET_NR;
                goto fail;
        }
@@ -2205,7 +2265,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
        reply_size += cm->reply_body_size;
 
        /* allocation not in the IO path, cqueue thread context */
-       cn_reply = kmalloc(reply_size, GFP_KERNEL);
+       cn_reply = kzalloc(reply_size, GFP_KERNEL);
        if (!cn_reply) {
                retcode = ERR_NOMEM;
                goto fail;
@@ -2213,7 +2273,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
        reply = (struct drbd_nl_cfg_reply *) cn_reply->data;
 
        reply->packet_type =
-               cm->reply_body_size ? nlp->packet_type : P_nl_after_last_packet;
+               cm->reply_body_size ? nlp->packet_type : P_return_code_only;
        reply->minor = nlp->drbd_minor;
        reply->ret_code = NO_ERROR; /* Might by modified by cm->function. */
        /* reply->tag_list; might be modified by cm->function. */
@@ -2376,7 +2436,7 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
        /* receiver thread context, which is not in the writeout path (of this node),
         * but may be in the writeout path of the _other_ node.
         * GFP_NOIO to avoid potential "distributed deadlock". */
-       cn_reply = kmalloc(
+       cn_reply = kzalloc(
                sizeof(struct cn_msg)+
                sizeof(struct drbd_nl_cfg_reply)+
                sizeof(struct dump_ee_tag_len_struct)+
@@ -2398,10 +2458,11 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
        tl = tl_add_int(tl, T_ee_sector, &e->sector);
        tl = tl_add_int(tl, T_ee_block_id, &e->block_id);
 
+       /* dump the first 32k */
+       len = min_t(unsigned, e->size, 32 << 10);
        put_unaligned(T_ee_data, tl++);
-       put_unaligned(e->size, tl++);
+       put_unaligned(len, tl++);
 
-       len = e->size;
        page = e->pages;
        page_chain_for_each(page) {
                void *d = kmap_atomic(page, KM_USER0);
@@ -2410,6 +2471,8 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
                kunmap_atomic(d, KM_USER0);
                tl = (unsigned short*)((char*)tl + l);
                len -= l;
+               if (len == 0)
+                       break;
        }
        put_unaligned(TT_END, tl++); /* Close the tag list */
 
@@ -2508,6 +2571,7 @@ void drbd_nl_send_reply(struct cn_msg *req, int ret_code)
                (struct drbd_nl_cfg_reply *)cn_reply->data;
        int rr;
 
+       memset(buffer, 0, sizeof(buffer));
        cn_reply->id = req->id;
 
        cn_reply->seq = req->seq;
@@ -2515,6 +2579,7 @@ void drbd_nl_send_reply(struct cn_msg *req, int ret_code)
        cn_reply->len = sizeof(struct drbd_nl_cfg_reply);
        cn_reply->flags = 0;
 
+       reply->packet_type = P_return_code_only;
        reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor;
        reply->ret_code = ret_code;
 
index 7e6ac307e2dec3ba1c9de2f825d0b1c9cbbbf9af..2959cdfb77f556e0bed2a8131eb69c69cbfed84f 100644 (file)
@@ -34,6 +34,7 @@
 #include "drbd_int.h"
 
 static int drbd_proc_open(struct inode *inode, struct file *file);
+static int drbd_proc_release(struct inode *inode, struct file *file);
 
 
 struct proc_dir_entry *drbd_proc;
@@ -42,9 +43,22 @@ const struct file_operations drbd_proc_fops = {
        .open           = drbd_proc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .release        = drbd_proc_release,
 };
 
+void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
+{
+       /* v is in kB/sec. We don't expect TiByte/sec yet. */
+       if (unlikely(v >= 1000000)) {
+               /* cool: > GiByte/s */
+               seq_printf(seq, "%ld,", v / 1000000);
+               v /= 1000000;
+               seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
+       } else if (likely(v >= 1000))
+               seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
+       else
+               seq_printf(seq, "%ld", v);
+}
 
 /*lge
  * progress bars shamelessly adapted from driver/md/md.c
@@ -71,10 +85,15 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
                seq_printf(seq, ".");
        seq_printf(seq, "] ");
 
-       seq_printf(seq, "sync'ed:%3u.%u%% ", res / 10, res % 10);
-       /* if more than 1 GB display in MB */
-       if (mdev->rs_total > 0x100000L)
-               seq_printf(seq, "(%lu/%lu)M\n\t",
+       if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+               seq_printf(seq, "verified:");
+       else
+               seq_printf(seq, "sync'ed:");
+       seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
+
+       /* if more than a few GB, display in MB */
+       if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
+               seq_printf(seq, "(%lu/%lu)M",
                            (unsigned long) Bit2KB(rs_left >> 10),
                            (unsigned long) Bit2KB(mdev->rs_total >> 10));
        else
@@ -94,6 +113,7 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
        /* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
         * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
         * least DRBD_SYNC_MARK_STEP time before it will be modified. */
+       /* ------------------------ ~18s average ------------------------ */
        i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
        dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
        if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
@@ -107,14 +127,24 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
        seq_printf(seq, "finish: %lu:%02lu:%02lu",
                rt / 3600, (rt % 3600) / 60, rt % 60);
 
-       /* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */
        dbdt = Bit2KB(db/dt);
-       if (dbdt > 1000)
-               seq_printf(seq, " speed: %ld,%03ld",
-                       dbdt/1000, dbdt % 1000);
-       else
-               seq_printf(seq, " speed: %ld", dbdt);
+       seq_printf(seq, " speed: ");
+       seq_printf_with_thousands_grouping(seq, dbdt);
+       seq_printf(seq, " (");
+       /* ------------------------- ~3s average ------------------------ */
+       if (proc_details >= 1) {
+               /* this is what drbd_rs_should_slow_down() uses */
+               i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+               dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+               if (!dt)
+                       dt++;
+               db = mdev->rs_mark_left[i] - rs_left;
+               dbdt = Bit2KB(db/dt);
+               seq_printf_with_thousands_grouping(seq, dbdt);
+               seq_printf(seq, " -- ");
+       }
 
+       /* --------------------- long term average ---------------------- */
        /* mean speed since syncer started
         * we do account for PausedSync periods */
        dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
@@ -122,20 +152,34 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
                dt = 1;
        db = mdev->rs_total - rs_left;
        dbdt = Bit2KB(db/dt);
-       if (dbdt > 1000)
-               seq_printf(seq, " (%ld,%03ld)",
-                       dbdt/1000, dbdt % 1000);
-       else
-               seq_printf(seq, " (%ld)", dbdt);
+       seq_printf_with_thousands_grouping(seq, dbdt);
+       seq_printf(seq, ")");
 
-       if (mdev->state.conn == C_SYNC_TARGET) {
-               if (mdev->c_sync_rate > 1000)
-                       seq_printf(seq, " want: %d,%03d",
-                                  mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
-               else
-                       seq_printf(seq, " want: %d", mdev->c_sync_rate);
+       if (mdev->state.conn == C_SYNC_TARGET ||
+           mdev->state.conn == C_VERIFY_S) {
+               seq_printf(seq, " want: ");
+               seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate);
        }
        seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
+
+       if (proc_details >= 1) {
+               /* 64 bit:
+                * we convert to sectors in the display below. */
+               unsigned long bm_bits = drbd_bm_bits(mdev);
+               unsigned long bit_pos;
+               if (mdev->state.conn == C_VERIFY_S ||
+                   mdev->state.conn == C_VERIFY_T)
+                       bit_pos = bm_bits - mdev->ov_left;
+               else
+                       bit_pos = mdev->bm_resync_fo;
+               /* Total sectors may be slightly off for oddly
+                * sized devices. So what. */
+               seq_printf(seq,
+                       "\t%3d%% sector pos: %llu/%llu\n",
+                       (int)(bit_pos / (bm_bits/100+1)),
+                       (unsigned long long)bit_pos * BM_SECT_PER_BIT,
+                       (unsigned long long)bm_bits * BM_SECT_PER_BIT);
+       }
 }
 
 static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
@@ -232,20 +276,16 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
                           mdev->epochs,
                           write_ordering_chars[mdev->write_ordering]
                        );
-                       seq_printf(seq, " oos:%lu\n",
-                                  Bit2KB(drbd_bm_total_weight(mdev)));
+                       seq_printf(seq, " oos:%llu\n",
+                                  Bit2KB((unsigned long long)
+                                          drbd_bm_total_weight(mdev)));
                }
                if (mdev->state.conn == C_SYNC_SOURCE ||
-                   mdev->state.conn == C_SYNC_TARGET)
+                   mdev->state.conn == C_SYNC_TARGET ||
+                   mdev->state.conn == C_VERIFY_S ||
+                   mdev->state.conn == C_VERIFY_T)
                        drbd_syncer_progress(mdev, seq);
 
-               if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
-                       seq_printf(seq, "\t%3d%%      %lu/%lu\n",
-                                  (int)((mdev->rs_total-mdev->ov_left) /
-                                        (mdev->rs_total/100+1)),
-                                  mdev->rs_total - mdev->ov_left,
-                                  mdev->rs_total);
-
                if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
                        lc_seq_printf_stats(seq, mdev->resync);
                        lc_seq_printf_stats(seq, mdev->act_log);
@@ -265,7 +305,15 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 
 static int drbd_proc_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, drbd_seq_show, PDE(inode)->data);
+       if (try_module_get(THIS_MODULE))
+               return single_open(file, drbd_seq_show, PDE(inode)->data);
+       return -ENODEV;
+}
+
+static int drbd_proc_release(struct inode *inode, struct file *file)
+{
+       module_put(THIS_MODULE);
+       return single_release(inode, file);
 }
 
 /* PROC FS stuff end */
index 8e68be939debefb6e5960ed38c2dd42d67c3a18d..fe1564c7d8b6e835643939d18f3aba2bc9e6b60d 100644 (file)
@@ -277,7 +277,7 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
        atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
        int i;
 
-       if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
+       if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count)
                i = page_chain_free(page);
        else {
                struct page *tmp;
@@ -319,7 +319,7 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
        struct page *page;
        unsigned nr_pages = (data_size + PAGE_SIZE -1) >> PAGE_SHIFT;
 
-       if (FAULT_ACTIVE(mdev, DRBD_FAULT_AL_EE))
+       if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE))
                return NULL;
 
        e = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM);
@@ -725,16 +725,16 @@ static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock)
        char tb[4];
 
        if (!*sock)
-               return FALSE;
+               return false;
 
        rr = drbd_recv_short(mdev, *sock, tb, 4, MSG_DONTWAIT | MSG_PEEK);
 
        if (rr > 0 || rr == -EAGAIN) {
-               return TRUE;
+               return true;
        } else {
                sock_release(*sock);
                *sock = NULL;
-               return FALSE;
+               return false;
        }
 }
 
@@ -768,8 +768,7 @@ static int drbd_connect(struct drbd_conf *mdev)
                        if (s || ++try >= 3)
                                break;
                        /* give the other side time to call bind() & listen() */
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ / 10);
+                       schedule_timeout_interruptible(HZ / 10);
                }
 
                if (s) {
@@ -788,8 +787,7 @@ static int drbd_connect(struct drbd_conf *mdev)
                }
 
                if (sock && msock) {
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ / 10);
+                       schedule_timeout_interruptible(HZ / 10);
                        ok = drbd_socket_okay(mdev, &sock);
                        ok = drbd_socket_okay(mdev, &msock) && ok;
                        if (ok)
@@ -906,7 +904,7 @@ retry:
                put_ldev(mdev);
        }
 
-       if (!drbd_send_protocol(mdev))
+       if (drbd_send_protocol(mdev) == -1)
                return -1;
        drbd_send_sync_param(mdev, &mdev->sync_conf);
        drbd_send_sizes(mdev, 0, 0);
@@ -914,6 +912,7 @@ retry:
        drbd_send_state(mdev);
        clear_bit(USE_DEGR_WFC_T, &mdev->flags);
        clear_bit(RESIZE_PENDING, &mdev->flags);
+       mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
 
        return 1;
 
@@ -932,8 +931,9 @@ static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsi
 
        r = drbd_recv(mdev, h, sizeof(*h));
        if (unlikely(r != sizeof(*h))) {
-               dev_err(DEV, "short read expecting header on sock: r=%d\n", r);
-               return FALSE;
+               if (!signal_pending(current))
+                       dev_warn(DEV, "short read expecting header on sock: r=%d\n", r);
+               return false;
        }
 
        if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
@@ -947,11 +947,11 @@ static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsi
                    be32_to_cpu(h->h80.magic),
                    be16_to_cpu(h->h80.command),
                    be16_to_cpu(h->h80.length));
-               return FALSE;
+               return false;
        }
        mdev->last_received = jiffies;
 
-       return TRUE;
+       return true;
 }
 
 static void drbd_flush(struct drbd_conf *mdev)
@@ -1074,6 +1074,16 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo)
  * @mdev:      DRBD device.
  * @e:         epoch entry
  * @rw:                flag field, see bio->bi_rw
+ *
+ * May spread the pages to multiple bios,
+ * depending on bio_add_page restrictions.
+ *
+ * Returns 0 if all bios have been submitted,
+ * -ENOMEM if we could not allocate enough bios,
+ * -ENOSPC (any better suggestion?) if we have not been able to bio_add_page a
+ *  single page to an empty bio (which should never happen and likely indicates
+ *  that the lower level IO stack is in some way broken). This has been observed
+ *  on certain Xen deployments.
  */
 /* TODO allocate from our own bio_set. */
 int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
@@ -1086,6 +1096,7 @@ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
        unsigned ds = e->size;
        unsigned n_bios = 0;
        unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
+       int err = -ENOMEM;
 
        /* In most cases, we will only need one bio.  But in case the lower
         * level restrictions happen to be different at this offset on this
@@ -1111,8 +1122,17 @@ next_bio:
        page_chain_for_each(page) {
                unsigned len = min_t(unsigned, ds, PAGE_SIZE);
                if (!bio_add_page(bio, page, len, 0)) {
-                       /* a single page must always be possible! */
-                       BUG_ON(bio->bi_vcnt == 0);
+                       /* A single page must always be possible!
+                        * But in case it fails anyways,
+                        * we deal with it, and complain (below). */
+                       if (bio->bi_vcnt == 0) {
+                               dev_err(DEV,
+                                       "bio_add_page failed for len=%u, "
+                                       "bi_vcnt=0 (bi_sector=%llu)\n",
+                                       len, (unsigned long long)bio->bi_sector);
+                               err = -ENOSPC;
+                               goto fail;
+                       }
                        goto next_bio;
                }
                ds -= len;
@@ -1138,7 +1158,7 @@ fail:
                bios = bios->bi_next;
                bio_put(bio);
        }
-       return -ENOMEM;
+       return err;
 }
 
 static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -1160,7 +1180,7 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign
        switch (mdev->write_ordering) {
        case WO_none:
                if (rv == FE_RECYCLED)
-                       return TRUE;
+                       return true;
 
                /* receiver context, in the writeout path of the other node.
                 * avoid potential distributed deadlock */
@@ -1188,10 +1208,10 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign
                D_ASSERT(atomic_read(&epoch->active) == 0);
                D_ASSERT(epoch->flags == 0);
 
-               return TRUE;
+               return true;
        default:
                dev_err(DEV, "Strangeness in mdev->write_ordering %d\n", mdev->write_ordering);
-               return FALSE;
+               return false;
        }
 
        epoch->flags = 0;
@@ -1209,7 +1229,7 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign
        }
        spin_unlock(&mdev->epoch_lock);
 
-       return TRUE;
+       return true;
 }
 
 /* used from receive_RSDataReply (recv_resync_read)
@@ -1231,21 +1251,25 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
        if (dgs) {
                rr = drbd_recv(mdev, dig_in, dgs);
                if (rr != dgs) {
-                       dev_warn(DEV, "short read receiving data digest: read %d expected %d\n",
-                            rr, dgs);
+                       if (!signal_pending(current))
+                               dev_warn(DEV,
+                                       "short read receiving data digest: read %d expected %d\n",
+                                       rr, dgs);
                        return NULL;
                }
        }
 
        data_size -= dgs;
 
+       ERR_IF(data_size == 0) return NULL;
        ERR_IF(data_size &  0x1ff) return NULL;
-       ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return NULL;
+       ERR_IF(data_size >  DRBD_MAX_BIO_SIZE) return NULL;
 
        /* even though we trust out peer,
         * we sometimes have to double check. */
        if (sector + (data_size>>9) > capacity) {
-               dev_err(DEV, "capacity: %llus < sector: %llus + size: %u\n",
+               dev_err(DEV, "request from peer beyond end of local disk: "
+                       "capacity: %llus < sector: %llus + size: %u\n",
                        (unsigned long long)capacity,
                        (unsigned long long)sector, data_size);
                return NULL;
@@ -1264,15 +1288,16 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
                unsigned len = min_t(int, ds, PAGE_SIZE);
                data = kmap(page);
                rr = drbd_recv(mdev, data, len);
-               if (FAULT_ACTIVE(mdev, DRBD_FAULT_RECEIVE)) {
+               if (drbd_insert_fault(mdev, DRBD_FAULT_RECEIVE)) {
                        dev_err(DEV, "Fault injection: Corrupting data on receive\n");
                        data[0] = data[0] ^ (unsigned long)-1;
                }
                kunmap(page);
                if (rr != len) {
                        drbd_free_ee(mdev, e);
-                       dev_warn(DEV, "short read receiving data: read %d expected %d\n",
-                            rr, len);
+                       if (!signal_pending(current))
+                               dev_warn(DEV, "short read receiving data: read %d expected %d\n",
+                               rr, len);
                        return NULL;
                }
                ds -= rr;
@@ -1281,7 +1306,8 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
        if (dgs) {
                drbd_csum_ee(mdev, mdev->integrity_r_tfm, e, dig_vv);
                if (memcmp(dig_in, dig_vv, dgs)) {
-                       dev_err(DEV, "Digest integrity check FAILED.\n");
+                       dev_err(DEV, "Digest integrity check FAILED: %llus +%u\n",
+                               (unsigned long long)sector, data_size);
                        drbd_bcast_ee(mdev, "digest failed",
                                        dgs, dig_in, dig_vv, e);
                        drbd_free_ee(mdev, e);
@@ -1302,7 +1328,7 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
        void *data;
 
        if (!data_size)
-               return TRUE;
+               return true;
 
        page = drbd_pp_alloc(mdev, 1, 1);
 
@@ -1311,8 +1337,10 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
                rr = drbd_recv(mdev, data, min_t(int, data_size, PAGE_SIZE));
                if (rr != min_t(int, data_size, PAGE_SIZE)) {
                        rv = 0;
-                       dev_warn(DEV, "short read receiving data: read %d expected %d\n",
-                            rr, min_t(int, data_size, PAGE_SIZE));
+                       if (!signal_pending(current))
+                               dev_warn(DEV,
+                                       "short read receiving data: read %d expected %d\n",
+                                       rr, min_t(int, data_size, PAGE_SIZE));
                        break;
                }
                data_size -= rr;
@@ -1337,8 +1365,10 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
        if (dgs) {
                rr = drbd_recv(mdev, dig_in, dgs);
                if (rr != dgs) {
-                       dev_warn(DEV, "short read receiving data reply digest: read %d expected %d\n",
-                            rr, dgs);
+                       if (!signal_pending(current))
+                               dev_warn(DEV,
+                                       "short read receiving data reply digest: read %d expected %d\n",
+                                       rr, dgs);
                        return 0;
                }
        }
@@ -1359,9 +1389,10 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
                             expect);
                kunmap(bvec->bv_page);
                if (rr != expect) {
-                       dev_warn(DEV, "short read receiving data reply: "
-                            "read %d expected %d\n",
-                            rr, expect);
+                       if (!signal_pending(current))
+                               dev_warn(DEV, "short read receiving data reply: "
+                                       "read %d expected %d\n",
+                                       rr, expect);
                        return 0;
                }
                data_size -= rr;
@@ -1425,11 +1456,10 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si
 
        atomic_add(data_size >> 9, &mdev->rs_sect_ev);
        if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
-               return TRUE;
+               return true;
 
-       /* drbd_submit_ee currently fails for one reason only:
-        * not being able to allocate enough bios.
-        * Is dropping the connection going to help? */
+       /* don't care for the reason here */
+       dev_err(DEV, "submit failed, triggering re-connect\n");
        spin_lock_irq(&mdev->req_lock);
        list_del(&e->w.list);
        spin_unlock_irq(&mdev->req_lock);
@@ -1437,7 +1467,7 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si
        drbd_free_ee(mdev, e);
 fail:
        put_ldev(mdev);
-       return FALSE;
+       return false;
 }
 
 static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -1454,7 +1484,7 @@ static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
        spin_unlock_irq(&mdev->req_lock);
        if (unlikely(!req)) {
                dev_err(DEV, "Got a corrupt block_id/sector pair(1).\n");
-               return FALSE;
+               return false;
        }
 
        /* hlist_del(&req->colision) is done in _req_may_be_done, to avoid
@@ -1611,15 +1641,15 @@ static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq)
        return ret;
 }
 
-static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+/* see also bio_flags_to_wire()
+ * DRBD_REQ_*, because we need to semantically map the flags to data packet
+ * flags and back. We may replicate to other kernel versions. */
+static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
 {
-       if (mdev->agreed_pro_version >= 95)
-               return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
-                       (dpf & DP_FUA ? REQ_FUA : 0) |
-                       (dpf & DP_FLUSH ? REQ_FUA : 0) |
-                       (dpf & DP_DISCARD ? REQ_DISCARD : 0);
-       else
-               return dpf & DP_RW_SYNC ? REQ_SYNC : 0;
+       return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+               (dpf & DP_FUA ? REQ_FUA : 0) |
+               (dpf & DP_FLUSH ? REQ_FLUSH : 0) |
+               (dpf & DP_DISCARD ? REQ_DISCARD : 0);
 }
 
 /* mirrored write */
@@ -1632,9 +1662,6 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
        u32 dp_flags;
 
        if (!get_ldev(mdev)) {
-               if (__ratelimit(&drbd_ratelimit_state))
-                       dev_err(DEV, "Can not write mirrored data block "
-                           "to local disk.\n");
                spin_lock(&mdev->peer_seq_lock);
                if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num))
                        mdev->peer_seq++;
@@ -1654,23 +1681,23 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
        e = read_in_block(mdev, p->block_id, sector, data_size);
        if (!e) {
                put_ldev(mdev);
-               return FALSE;
+               return false;
        }
 
        e->w.cb = e_end_block;
 
+       dp_flags = be32_to_cpu(p->dp_flags);
+       rw |= wire_flags_to_bio(mdev, dp_flags);
+
+       if (dp_flags & DP_MAY_SET_IN_SYNC)
+               e->flags |= EE_MAY_SET_IN_SYNC;
+
        spin_lock(&mdev->epoch_lock);
        e->epoch = mdev->current_epoch;
        atomic_inc(&e->epoch->epoch_size);
        atomic_inc(&e->epoch->active);
        spin_unlock(&mdev->epoch_lock);
 
-       dp_flags = be32_to_cpu(p->dp_flags);
-       rw |= write_flags_to_bio(mdev, dp_flags);
-
-       if (dp_flags & DP_MAY_SET_IN_SYNC)
-               e->flags |= EE_MAY_SET_IN_SYNC;
-
        /* I'm the receiver, I do hold a net_cnt reference. */
        if (!mdev->net_conf->two_primaries) {
                spin_lock_irq(&mdev->req_lock);
@@ -1773,7 +1800,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                                put_ldev(mdev);
                                wake_asender(mdev);
                                finish_wait(&mdev->misc_wait, &wait);
-                               return TRUE;
+                               return true;
                        }
 
                        if (signal_pending(current)) {
@@ -1829,11 +1856,10 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
        }
 
        if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
-               return TRUE;
+               return true;
 
-       /* drbd_submit_ee currently fails for one reason only:
-        * not being able to allocate enough bios.
-        * Is dropping the connection going to help? */
+       /* don't care for the reason here */
+       dev_err(DEV, "submit failed, triggering re-connect\n");
        spin_lock_irq(&mdev->req_lock);
        list_del(&e->w.list);
        hlist_del_init(&e->colision);
@@ -1842,12 +1868,10 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                drbd_al_complete_io(mdev, e->sector);
 
 out_interrupted:
-       /* yes, the epoch_size now is imbalanced.
-        * but we drop the connection anyways, so we don't have a chance to
-        * receive a barrier... atomic_inc(&mdev->epoch_size); */
+       drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + EV_CLEANUP);
        put_ldev(mdev);
        drbd_free_ee(mdev, e);
-       return FALSE;
+       return false;
 }
 
 /* We may throttle resync, if the lower device seems to be busy,
@@ -1861,10 +1885,11 @@ out_interrupted:
  * The current sync rate used here uses only the most recent two step marks,
  * to have a short time average so we can react faster.
  */
-int drbd_rs_should_slow_down(struct drbd_conf *mdev)
+int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 {
        struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
        unsigned long db, dt, dbdt;
+       struct lc_element *tmp;
        int curr_events;
        int throttle = 0;
 
@@ -1872,9 +1897,22 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev)
        if (mdev->sync_conf.c_min_rate == 0)
                return 0;
 
+       spin_lock_irq(&mdev->al_lock);
+       tmp = lc_find(mdev->resync, BM_SECT_TO_EXT(sector));
+       if (tmp) {
+               struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce);
+               if (test_bit(BME_PRIORITY, &bm_ext->flags)) {
+                       spin_unlock_irq(&mdev->al_lock);
+                       return 0;
+               }
+               /* Do not slow down if app IO is already waiting for this extent */
+       }
+       spin_unlock_irq(&mdev->al_lock);
+
        curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
                      (int)part_stat_read(&disk->part0, sectors[1]) -
                        atomic_read(&mdev->rs_sect_ev);
+
        if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
                unsigned long rs_left;
                int i;
@@ -1883,8 +1921,12 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev)
 
                /* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
                 * approx. */
-               i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS;
-               rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+               i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+
+               if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+                       rs_left = mdev->ov_left;
+               else
+                       rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
 
                dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
                if (!dt)
@@ -1912,15 +1954,15 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
        sector = be64_to_cpu(p->sector);
        size   = be32_to_cpu(p->blksize);
 
-       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
                dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
                                (unsigned long long)sector, size);
-               return FALSE;
+               return false;
        }
        if (sector + (size>>9) > capacity) {
                dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
                                (unsigned long long)sector, size);
-               return FALSE;
+               return false;
        }
 
        if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
@@ -1957,7 +1999,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
        e = drbd_alloc_ee(mdev, p->block_id, sector, size, GFP_NOIO);
        if (!e) {
                put_ldev(mdev);
-               return FALSE;
+               return false;
        }
 
        switch (cmd) {
@@ -1970,6 +2012,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
        case P_RS_DATA_REQUEST:
                e->w.cb = w_e_end_rsdata_req;
                fault_type = DRBD_FAULT_RS_RD;
+               /* used in the sector offset progress display */
+               mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
                break;
 
        case P_OV_REPLY:
@@ -1991,7 +2035,11 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
                if (cmd == P_CSUM_RS_REQUEST) {
                        D_ASSERT(mdev->agreed_pro_version >= 89);
                        e->w.cb = w_e_end_csum_rs_req;
+                       /* used in the sector offset progress display */
+                       mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
                } else if (cmd == P_OV_REPLY) {
+                       /* track progress, we may need to throttle */
+                       atomic_add(size >> 9, &mdev->rs_sect_in);
                        e->w.cb = w_e_end_ov_reply;
                        dec_rs_pending(mdev);
                        /* drbd_rs_begin_io done when we sent this request,
@@ -2003,9 +2051,16 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
        case P_OV_REQUEST:
                if (mdev->ov_start_sector == ~(sector_t)0 &&
                    mdev->agreed_pro_version >= 90) {
+                       unsigned long now = jiffies;
+                       int i;
                        mdev->ov_start_sector = sector;
                        mdev->ov_position = sector;
-                       mdev->ov_left = mdev->rs_total - BM_SECT_TO_BIT(sector);
+                       mdev->ov_left = drbd_bm_bits(mdev) - BM_SECT_TO_BIT(sector);
+                       mdev->rs_total = mdev->ov_left;
+                       for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+                               mdev->rs_mark_left[i] = mdev->ov_left;
+                               mdev->rs_mark_time[i] = now;
+                       }
                        dev_info(DEV, "Online Verify start sector: %llu\n",
                                        (unsigned long long)sector);
                }
@@ -2042,9 +2097,9 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
         * we would also throttle its application reads.
         * In that case, throttling is done on the SyncTarget only.
         */
-       if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev))
-               msleep(100);
-       if (drbd_rs_begin_io(mdev, e->sector))
+       if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev, sector))
+               schedule_timeout_uninterruptible(HZ/10);
+       if (drbd_rs_begin_io(mdev, sector))
                goto out_free_e;
 
 submit_for_resync:
@@ -2057,11 +2112,10 @@ submit:
        spin_unlock_irq(&mdev->req_lock);
 
        if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
-               return TRUE;
+               return true;
 
-       /* drbd_submit_ee currently fails for one reason only:
-        * not being able to allocate enough bios.
-        * Is dropping the connection going to help? */
+       /* don't care for the reason here */
+       dev_err(DEV, "submit failed, triggering re-connect\n");
        spin_lock_irq(&mdev->req_lock);
        list_del(&e->w.list);
        spin_unlock_irq(&mdev->req_lock);
@@ -2070,7 +2124,7 @@ submit:
 out_free_e:
        put_ldev(mdev);
        drbd_free_ee(mdev, e);
-       return FALSE;
+       return false;
 }
 
 static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
@@ -2147,10 +2201,7 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 
 static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 {
-       int self, peer, hg, rv = -100;
-
-       self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
-       peer = mdev->p_uuid[UI_BITMAP] & 1;
+       int hg, rv = -100;
 
        switch (mdev->net_conf->after_sb_1p) {
        case ASB_DISCARD_YOUNGER_PRI:
@@ -2177,12 +2228,14 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
        case ASB_CALL_HELPER:
                hg = drbd_asb_recover_0p(mdev);
                if (hg == -1 && mdev->state.role == R_PRIMARY) {
-                       self = drbd_set_role(mdev, R_SECONDARY, 0);
+                       enum drbd_state_rv rv2;
+
+                       drbd_set_role(mdev, R_SECONDARY, 0);
                         /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
                          * we might be here in C_WF_REPORT_PARAMS which is transient.
                          * we do not need to wait for the after state change work either. */
-                       self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
-                       if (self != SS_SUCCESS) {
+                       rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+                       if (rv2 != SS_SUCCESS) {
                                drbd_khelper(mdev, "pri-lost-after-sb");
                        } else {
                                dev_warn(DEV, "Successfully gave up primary role.\n");
@@ -2197,10 +2250,7 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 
 static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 {
-       int self, peer, hg, rv = -100;
-
-       self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
-       peer = mdev->p_uuid[UI_BITMAP] & 1;
+       int hg, rv = -100;
 
        switch (mdev->net_conf->after_sb_2p) {
        case ASB_DISCARD_YOUNGER_PRI:
@@ -2220,11 +2270,13 @@ static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
        case ASB_CALL_HELPER:
                hg = drbd_asb_recover_0p(mdev);
                if (hg == -1) {
+                       enum drbd_state_rv rv2;
+
                         /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
                          * we might be here in C_WF_REPORT_PARAMS which is transient.
                          * we do not need to wait for the after state change work either. */
-                       self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
-                       if (self != SS_SUCCESS) {
+                       rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+                       if (rv2 != SS_SUCCESS) {
                                drbd_khelper(mdev, "pri-lost-after-sb");
                        } else {
                                dev_warn(DEV, "Successfully gave up primary role.\n");
@@ -2263,6 +2315,8 @@ static void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid,
    -2  C_SYNC_TARGET set BitMap
  -100  after split brain, disconnect
 -1000  unrelated data
+-1091   requires proto 91
+-1096   requires proto 96
  */
 static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local)
 {
@@ -2292,7 +2346,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
                if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) {
 
                        if (mdev->agreed_pro_version < 91)
-                               return -1001;
+                               return -1091;
 
                        if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
                            (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
@@ -2313,7 +2367,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
                if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) {
 
                        if (mdev->agreed_pro_version < 91)
-                               return -1001;
+                               return -1091;
 
                        if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) &&
                            (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) {
@@ -2358,17 +2412,22 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
        *rule_nr = 51;
        peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
        if (self == peer) {
-               self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
-               peer = mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1);
-               if (self == peer) {
+               if (mdev->agreed_pro_version < 96 ?
+                   (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
+                   (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
+                   peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) {
                        /* The last P_SYNC_UUID did not get though. Undo the last start of
                           resync as sync source modifications of the peer's UUIDs. */
 
                        if (mdev->agreed_pro_version < 91)
-                               return -1001;
+                               return -1091;
 
                        mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START];
                        mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1];
+
+                       dev_info(DEV, "Did not got last syncUUID packet, corrected:\n");
+                       drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
+
                        return -1;
                }
        }
@@ -2390,20 +2449,20 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
        *rule_nr = 71;
        self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
        if (self == peer) {
-               self = mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1);
-               peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
-               if (self == peer) {
+               if (mdev->agreed_pro_version < 96 ?
+                   (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
+                   (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
+                   self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
                        /* The last P_SYNC_UUID did not get though. Undo the last start of
                           resync as sync source modifications of our UUIDs. */
 
                        if (mdev->agreed_pro_version < 91)
-                               return -1001;
+                               return -1091;
 
                        _drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
                        _drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
 
-                       dev_info(DEV, "Undid last start of resync:\n");
-
+                       dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
                        drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
                                       mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
 
@@ -2466,8 +2525,8 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
                dev_alert(DEV, "Unrelated data, aborting!\n");
                return C_MASK;
        }
-       if (hg == -1001) {
-               dev_alert(DEV, "To resolve this both sides have to support at least protocol\n");
+       if (hg < -1000) {
+               dev_alert(DEV, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000);
                return C_MASK;
        }
 
@@ -2566,7 +2625,8 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 
        if (abs(hg) >= 2) {
                dev_info(DEV, "Writing the whole bitmap, full sync required after drbd_sync_handshake.\n");
-               if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake"))
+               if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake",
+                                       BM_LOCKED_SET_ALLOWED))
                        return C_MASK;
        }
 
@@ -2660,7 +2720,7 @@ static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsig
                unsigned char *my_alg = mdev->net_conf->integrity_alg;
 
                if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size)
-                       return FALSE;
+                       return false;
 
                p_integrity_alg[SHARED_SECRET_MAX-1] = 0;
                if (strcmp(p_integrity_alg, my_alg)) {
@@ -2671,11 +2731,11 @@ static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsig
                     my_alg[0] ? my_alg : (unsigned char *)"<not-used>");
        }
 
-       return TRUE;
+       return true;
 
 disconnect:
        drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-       return FALSE;
+       return false;
 }
 
 /* helper function
@@ -2707,7 +2767,7 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev,
 
 static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
 {
-       int ok = TRUE;
+       int ok = true;
        struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
        unsigned int header_size, data_size, exp_max_sz;
        struct crypto_hash *verify_tfm = NULL;
@@ -2725,7 +2785,7 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
        if (packet_size > exp_max_sz) {
                dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
                    packet_size, exp_max_sz);
-               return FALSE;
+               return false;
        }
 
        if (apv <= 88) {
@@ -2745,7 +2805,7 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
        memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
        if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
-               return FALSE;
+               return false;
 
        mdev->sync_conf.rate      = be32_to_cpu(p->rate);
 
@@ -2755,11 +2815,11 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
                                dev_err(DEV, "verify-alg too long, "
                                    "peer wants %u, accepting only %u byte\n",
                                                data_size, SHARED_SECRET_MAX);
-                               return FALSE;
+                               return false;
                        }
 
                        if (drbd_recv(mdev, p->verify_alg, data_size) != data_size)
-                               return FALSE;
+                               return false;
 
                        /* we expect NUL terminated string */
                        /* but just in case someone tries to be evil */
@@ -2853,7 +2913,7 @@ disconnect:
        /* but free the verify_tfm again, if csums_tfm did not work out */
        crypto_free_hash(verify_tfm);
        drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-       return FALSE;
+       return false;
 }
 
 static void drbd_setup_order_type(struct drbd_conf *mdev, int peer)
@@ -2879,7 +2939,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 {
        struct p_sizes *p = &mdev->data.rbuf.sizes;
        enum determine_dev_size dd = unchanged;
-       unsigned int max_seg_s;
+       unsigned int max_bio_size;
        sector_t p_size, p_usize, my_usize;
        int ldsc = 0; /* local disk size changed */
        enum dds_flags ddsf;
@@ -2890,7 +2950,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
        if (p_size == 0 && mdev->state.disk == D_DISKLESS) {
                dev_err(DEV, "some backing storage is needed\n");
                drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-               return FALSE;
+               return false;
        }
 
        /* just store the peer's disk size for now.
@@ -2927,18 +2987,17 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                        drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
                        mdev->ldev->dc.disk_size = my_usize;
                        put_ldev(mdev);
-                       return FALSE;
+                       return false;
                }
                put_ldev(mdev);
        }
-#undef min_not_zero
 
        ddsf = be16_to_cpu(p->dds_flags);
        if (get_ldev(mdev)) {
                dd = drbd_determin_dev_size(mdev, ddsf);
                put_ldev(mdev);
                if (dd == dev_size_error)
-                       return FALSE;
+                       return false;
                drbd_md_sync(mdev);
        } else {
                /* I am diskless, need to accept the peer's size. */
@@ -2952,14 +3011,14 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                }
 
                if (mdev->agreed_pro_version < 94)
-                       max_seg_s = be32_to_cpu(p->max_segment_size);
+                       max_bio_size = be32_to_cpu(p->max_bio_size);
                else if (mdev->agreed_pro_version == 94)
-                       max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+                       max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
                else /* drbd 8.3.8 onwards */
-                       max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+                       max_bio_size = DRBD_MAX_BIO_SIZE;
 
-               if (max_seg_s != queue_max_segment_size(mdev->rq_queue))
-                       drbd_setup_queue_param(mdev, max_seg_s);
+               if (max_bio_size != queue_max_hw_sectors(mdev->rq_queue) << 9)
+                       drbd_setup_queue_param(mdev, max_bio_size);
 
                drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type));
                put_ldev(mdev);
@@ -2985,14 +3044,14 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                }
        }
 
-       return TRUE;
+       return true;
 }
 
 static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
        struct p_uuids *p = &mdev->data.rbuf.uuids;
        u64 *p_uuid;
-       int i;
+       int i, updated_uuids = 0;
 
        p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
 
@@ -3009,7 +3068,7 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                dev_err(DEV, "Can only connect to data with current UUID=%016llX\n",
                    (unsigned long long)mdev->ed_uuid);
                drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-               return FALSE;
+               return false;
        }
 
        if (get_ldev(mdev)) {
@@ -3021,19 +3080,21 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                if (skip_initial_sync) {
                        dev_info(DEV, "Accepted new current UUID, preparing to skip initial sync\n");
                        drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
-                                       "clear_n_write from receive_uuids");
+                                       "clear_n_write from receive_uuids",
+                                       BM_LOCKED_TEST_ALLOWED);
                        _drbd_uuid_set(mdev, UI_CURRENT, p_uuid[UI_CURRENT]);
                        _drbd_uuid_set(mdev, UI_BITMAP, 0);
                        _drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
                                        CS_VERBOSE, NULL);
                        drbd_md_sync(mdev);
+                       updated_uuids = 1;
                }
                put_ldev(mdev);
        } else if (mdev->state.disk < D_INCONSISTENT &&
                   mdev->state.role == R_PRIMARY) {
                /* I am a diskless primary, the peer just created a new current UUID
                   for me. */
-               drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+               updated_uuids = drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
        }
 
        /* Before we test for the disk state, we should wait until an eventually
@@ -3042,9 +3103,12 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
           new disk state... */
        wait_event(mdev->misc_wait, !test_bit(CLUSTER_ST_CHANGE, &mdev->flags));
        if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT)
-               drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+               updated_uuids |= drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 
-       return TRUE;
+       if (updated_uuids)
+               drbd_print_uuids(mdev, "receiver updated UUIDs to");
+
+       return true;
 }
 
 /**
@@ -3081,7 +3145,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 {
        struct p_req_state *p = &mdev->data.rbuf.req_state;
        union drbd_state mask, val;
-       int rv;
+       enum drbd_state_rv rv;
 
        mask.i = be32_to_cpu(p->mask);
        val.i = be32_to_cpu(p->val);
@@ -3089,7 +3153,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
        if (test_bit(DISCARD_CONCURRENT, &mdev->flags) &&
            test_bit(CLUSTER_ST_CHANGE, &mdev->flags)) {
                drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG);
-               return TRUE;
+               return true;
        }
 
        mask = convert_state(mask);
@@ -3100,7 +3164,7 @@ static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
        drbd_send_sr_reply(mdev, rv);
        drbd_md_sync(mdev);
 
-       return TRUE;
+       return true;
 }
 
 static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -3145,7 +3209,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                         peer_state.conn == C_CONNECTED) {
                        if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
                                drbd_resync_finished(mdev);
-                       return TRUE;
+                       return true;
                }
        }
 
@@ -3161,6 +3225,9 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
        if (ns.conn == C_WF_REPORT_PARAMS)
                ns.conn = C_CONNECTED;
 
+       if (peer_state.conn == C_AHEAD)
+               ns.conn = C_BEHIND;
+
        if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
            get_ldev_if_state(mdev, D_NEGOTIATING)) {
                int cr; /* consider resync */
@@ -3195,10 +3262,10 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                                real_peer_disk = D_DISKLESS;
                        } else {
                                if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
-                                       return FALSE;
+                                       return false;
                                D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
                                drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-                               return FALSE;
+                               return false;
                        }
                }
        }
@@ -3223,7 +3290,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                drbd_uuid_new_current(mdev);
                clear_bit(NEW_CUR_UUID, &mdev->flags);
                drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
-               return FALSE;
+               return false;
        }
        rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
        ns = mdev->state;
@@ -3231,7 +3298,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 
        if (rv < SS_SUCCESS) {
                drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-               return FALSE;
+               return false;
        }
 
        if (os.conn > C_WF_REPORT_PARAMS) {
@@ -3249,7 +3316,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 
        drbd_md_sync(mdev); /* update connected indicator, la_size, ... */
 
-       return TRUE;
+       return true;
 }
 
 static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -3258,6 +3325,7 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 
        wait_event(mdev->misc_wait,
                   mdev->state.conn == C_WF_SYNC_UUID ||
+                  mdev->state.conn == C_BEHIND ||
                   mdev->state.conn < C_CONNECTED ||
                   mdev->state.disk < D_NEGOTIATING);
 
@@ -3269,32 +3337,42 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
                _drbd_uuid_set(mdev, UI_CURRENT, be64_to_cpu(p->uuid));
                _drbd_uuid_set(mdev, UI_BITMAP, 0UL);
 
+               drbd_print_uuids(mdev, "updated sync uuid");
                drbd_start_resync(mdev, C_SYNC_TARGET);
 
                put_ldev(mdev);
        } else
                dev_err(DEV, "Ignoring SyncUUID packet!\n");
 
-       return TRUE;
+       return true;
 }
 
-enum receive_bitmap_ret { OK, DONE, FAILED };
-
-static enum receive_bitmap_ret
+/**
+ * receive_bitmap_plain
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
                     unsigned long *buffer, struct bm_xfer_ctx *c)
 {
        unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
        unsigned want = num_words * sizeof(long);
+       int err;
 
        if (want != data_size) {
                dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
-               return FAILED;
+               return -EIO;
        }
        if (want == 0)
-               return DONE;
-       if (drbd_recv(mdev, buffer, want) != want)
-               return FAILED;
+               return 0;
+       err = drbd_recv(mdev, buffer, want);
+       if (err != want) {
+               if (err >= 0)
+                       err = -EIO;
+               return err;
+       }
 
        drbd_bm_merge_lel(mdev, c->word_offset, num_words, buffer);
 
@@ -3303,10 +3381,16 @@ receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
        if (c->bit_offset > c->bm_bits)
                c->bit_offset = c->bm_bits;
 
-       return OK;
+       return 1;
 }
 
-static enum receive_bitmap_ret
+/**
+ * recv_bm_rle_bits
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 recv_bm_rle_bits(struct drbd_conf *mdev,
                struct p_compressed_bm *p,
                struct bm_xfer_ctx *c)
@@ -3326,18 +3410,18 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
 
        bits = bitstream_get_bits(&bs, &look_ahead, 64);
        if (bits < 0)
-               return FAILED;
+               return -EIO;
 
        for (have = bits; have > 0; s += rl, toggle = !toggle) {
                bits = vli_decode_bits(&rl, look_ahead);
                if (bits <= 0)
-                       return FAILED;
+                       return -EIO;
 
                if (toggle) {
                        e = s + rl -1;
                        if (e >= c->bm_bits) {
                                dev_err(DEV, "bitmap overflow (e:%lu) while decoding bm RLE packet\n", e);
-                               return FAILED;
+                               return -EIO;
                        }
                        _drbd_bm_set_bits(mdev, s, e);
                }
@@ -3347,14 +3431,14 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
                                have, bits, look_ahead,
                                (unsigned int)(bs.cur.b - p->code),
                                (unsigned int)bs.buf_len);
-                       return FAILED;
+                       return -EIO;
                }
                look_ahead >>= bits;
                have -= bits;
 
                bits = bitstream_get_bits(&bs, &tmp, 64 - have);
                if (bits < 0)
-                       return FAILED;
+                       return -EIO;
                look_ahead |= tmp << have;
                have += bits;
        }
@@ -3362,10 +3446,16 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
        c->bit_offset = s;
        bm_xfer_ctx_bit_to_word_offset(c);
 
-       return (s == c->bm_bits) ? DONE : OK;
+       return (s != c->bm_bits);
 }
 
-static enum receive_bitmap_ret
+/**
+ * decode_bitmap_c
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 decode_bitmap_c(struct drbd_conf *mdev,
                struct p_compressed_bm *p,
                struct bm_xfer_ctx *c)
@@ -3379,7 +3469,7 @@ decode_bitmap_c(struct drbd_conf *mdev,
 
        dev_err(DEV, "receive_bitmap_c: unknown encoding %u\n", p->encoding);
        drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-       return FAILED;
+       return -EIO;
 }
 
 void INFO_bm_xfer_stats(struct drbd_conf *mdev,
@@ -3428,13 +3518,13 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
 {
        struct bm_xfer_ctx c;
        void *buffer;
-       enum receive_bitmap_ret ret;
-       int ok = FALSE;
+       int err;
+       int ok = false;
        struct p_header80 *h = &mdev->data.rbuf.header.h80;
 
-       wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
-
-       drbd_bm_lock(mdev, "receive bitmap");
+       drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED);
+       /* you are supposed to send additional out-of-sync information
+        * if you actually set bits during this phase */
 
        /* maybe we should use some per thread scratch page,
         * and allocate that during initial device creation? */
@@ -3449,9 +3539,9 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
                .bm_words = drbd_bm_words(mdev),
        };
 
-       do {
+       for(;;) {
                if (cmd == P_BITMAP) {
-                       ret = receive_bitmap_plain(mdev, data_size, buffer, &c);
+                       err = receive_bitmap_plain(mdev, data_size, buffer, &c);
                } else if (cmd == P_COMPRESSED_BITMAP) {
                        /* MAYBE: sanity check that we speak proto >= 90,
                         * and the feature is enabled! */
@@ -3468,9 +3558,9 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
                                goto out;
                        if (data_size <= (sizeof(*p) - sizeof(p->head))) {
                                dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
-                               return FAILED;
+                               goto out;
                        }
-                       ret = decode_bitmap_c(mdev, p, &c);
+                       err = decode_bitmap_c(mdev, p, &c);
                } else {
                        dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
                        goto out;
@@ -3479,24 +3569,26 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
                c.packets[cmd == P_BITMAP]++;
                c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
 
-               if (ret != OK)
+               if (err <= 0) {
+                       if (err < 0)
+                               goto out;
                        break;
-
+               }
                if (!drbd_recv_header(mdev, &cmd, &data_size))
                        goto out;
-       } while (ret == OK);
-       if (ret == FAILED)
-               goto out;
+       }
 
        INFO_bm_xfer_stats(mdev, "receive", &c);
 
        if (mdev->state.conn == C_WF_BITMAP_T) {
+               enum drbd_state_rv rv;
+
                ok = !drbd_send_bitmap(mdev);
                if (!ok)
                        goto out;
                /* Omit CS_ORDERED with this state transition to avoid deadlocks. */
-               ok = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
-               D_ASSERT(ok == SS_SUCCESS);
+               rv = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
+               D_ASSERT(rv == SS_SUCCESS);
        } else if (mdev->state.conn != C_WF_BITMAP_S) {
                /* admin may have requested C_DISCONNECTING,
                 * other threads may have noticed network errors */
@@ -3504,7 +3596,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
                    drbd_conn_str(mdev->state.conn));
        }
 
-       ok = TRUE;
+       ok = true;
  out:
        drbd_bm_unlock(mdev);
        if (ok && mdev->state.conn == C_WF_BITMAP_S)
@@ -3538,7 +3630,26 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u
         * with the data requests being unplugged */
        drbd_tcp_quickack(mdev->data.socket);
 
-       return TRUE;
+       return true;
+}
+
+static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+{
+       struct p_block_desc *p = &mdev->data.rbuf.block_desc;
+
+       switch (mdev->state.conn) {
+       case C_WF_SYNC_UUID:
+       case C_WF_BITMAP_T:
+       case C_BEHIND:
+                       break;
+       default:
+               dev_err(DEV, "ASSERT FAILED cstate = %s, expected: WFSyncUUID|WFBitMapT|Behind\n",
+                               drbd_conn_str(mdev->state.conn));
+       }
+
+       drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize));
+
+       return true;
 }
 
 typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
@@ -3571,6 +3682,7 @@ static struct data_cmd drbd_cmd_handler[] = {
        [P_OV_REPLY]        = { 1, sizeof(struct p_block_req), receive_DataRequest },
        [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
        [P_DELAY_PROBE]     = { 0, sizeof(struct p_delay_probe93), receive_skip },
+       [P_OUT_OF_SYNC]     = { 0, sizeof(struct p_block_desc), receive_out_of_sync },
        /* anything missing from this table is in
         * the asender_tbl, see get_asender_cmd */
        [P_MAX_CMD]         = { 0, 0, NULL },
@@ -3610,7 +3722,8 @@ static void drbdd(struct drbd_conf *mdev)
                if (shs) {
                        rv = drbd_recv(mdev, &header->h80.payload, shs);
                        if (unlikely(rv != shs)) {
-                               dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+                               if (!signal_pending(current))
+                                       dev_warn(DEV, "short read while reading sub header: rv=%d\n", rv);
                                goto err_out;
                        }
                }
@@ -3682,9 +3795,6 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 
        if (mdev->state.conn == C_STANDALONE)
                return;
-       if (mdev->state.conn >= C_WF_CONNECTION)
-               dev_err(DEV, "ASSERT FAILED cstate = %s, expected < WFConnection\n",
-                               drbd_conn_str(mdev->state.conn));
 
        /* asender does not clean up anything. it must not interfere, either */
        drbd_thread_stop(&mdev->asender);
@@ -3713,6 +3823,8 @@ static void drbd_disconnect(struct drbd_conf *mdev)
        atomic_set(&mdev->rs_pending_cnt, 0);
        wake_up(&mdev->misc_wait);
 
+       del_timer(&mdev->request_timer);
+
        /* make sure syncer is stopped and w_resume_next_sg queued */
        del_timer_sync(&mdev->resync_timer);
        resync_timer_fn((unsigned long)mdev);
@@ -3758,13 +3870,6 @@ static void drbd_disconnect(struct drbd_conf *mdev)
        if (os.conn == C_DISCONNECTING) {
                wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
 
-               if (!is_susp(mdev->state)) {
-                       /* we must not free the tl_hash
-                        * while application io is still on the fly */
-                       wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
-                       drbd_free_tl_hash(mdev);
-               }
-
                crypto_free_hash(mdev->cram_hmac_tfm);
                mdev->cram_hmac_tfm = NULL;
 
@@ -3773,6 +3878,10 @@ static void drbd_disconnect(struct drbd_conf *mdev)
                drbd_request_state(mdev, NS(conn, C_STANDALONE));
        }
 
+       /* serialize with bitmap writeout triggered by the state change,
+        * if any. */
+       wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
        /* tcp_close and release of sendpage pages can be deferred.  I don't
         * want to use SO_LINGER, because apparently it can be deferred for
         * more than 20 seconds (longest time I checked).
@@ -3873,7 +3982,8 @@ static int drbd_do_handshake(struct drbd_conf *mdev)
        rv = drbd_recv(mdev, &p->head.payload, expect);
 
        if (rv != expect) {
-               dev_err(DEV, "short read receiving handshake packet: l=%u\n", rv);
+               if (!signal_pending(current))
+                       dev_warn(DEV, "short read receiving handshake packet: l=%u\n", rv);
                return 0;
        }
 
@@ -3975,7 +4085,8 @@ static int drbd_do_auth(struct drbd_conf *mdev)
        rv = drbd_recv(mdev, peers_ch, length);
 
        if (rv != length) {
-               dev_err(DEV, "short read AuthChallenge: l=%u\n", rv);
+               if (!signal_pending(current))
+                       dev_warn(DEV, "short read AuthChallenge: l=%u\n", rv);
                rv = 0;
                goto fail;
        }
@@ -4022,7 +4133,8 @@ static int drbd_do_auth(struct drbd_conf *mdev)
        rv = drbd_recv(mdev, response , resp_size);
 
        if (rv != resp_size) {
-               dev_err(DEV, "short read receiving AuthResponse: l=%u\n", rv);
+               if (!signal_pending(current))
+                       dev_warn(DEV, "short read receiving AuthResponse: l=%u\n", rv);
                rv = 0;
                goto fail;
        }
@@ -4074,8 +4186,7 @@ int drbdd_init(struct drbd_thread *thi)
                h = drbd_connect(mdev);
                if (h == 0) {
                        drbd_disconnect(mdev);
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ);
+                       schedule_timeout_interruptible(HZ);
                }
                if (h == -1) {
                        dev_warn(DEV, "Discarding network configuration.\n");
@@ -4113,7 +4224,7 @@ static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
        }
        wake_up(&mdev->state_wait);
 
-       return TRUE;
+       return true;
 }
 
 static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4129,7 +4240,7 @@ static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
        if (!test_and_set_bit(GOT_PING_ACK, &mdev->flags))
                wake_up(&mdev->misc_wait);
 
-       return TRUE;
+       return true;
 }
 
 static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4152,7 +4263,7 @@ static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
        dec_rs_pending(mdev);
        atomic_add(blksize >> 9, &mdev->rs_sect_in);
 
-       return TRUE;
+       return true;
 }
 
 /* when we receive the ACK for a write request,
@@ -4176,8 +4287,6 @@ static struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev,
                        return req;
                }
        }
-       dev_err(DEV, "_ack_id_to_req: failed to find req %p, sector %llus in list\n",
-               (void *)(unsigned long)id, (unsigned long long)sector);
        return NULL;
 }
 
@@ -4195,15 +4304,17 @@ static int validate_req_change_req_state(struct drbd_conf *mdev,
        req = validator(mdev, id, sector);
        if (unlikely(!req)) {
                spin_unlock_irq(&mdev->req_lock);
-               dev_err(DEV, "%s: got a corrupt block_id/sector pair\n", func);
-               return FALSE;
+
+               dev_err(DEV, "%s: failed to find req %p, sector %llus\n", func,
+                       (void *)(unsigned long)id, (unsigned long long)sector);
+               return false;
        }
        __req_mod(req, what, &m);
        spin_unlock_irq(&mdev->req_lock);
 
        if (m.bio)
                complete_master_bio(mdev, &m);
-       return TRUE;
+       return true;
 }
 
 static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4218,7 +4329,7 @@ static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
        if (is_syncer_block_id(p->block_id)) {
                drbd_set_in_sync(mdev, sector, blksize);
                dec_rs_pending(mdev);
-               return TRUE;
+               return true;
        }
        switch (be16_to_cpu(h->command)) {
        case P_RS_WRITE_ACK:
@@ -4239,7 +4350,7 @@ static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
                break;
        default:
                D_ASSERT(0);
-               return FALSE;
+               return false;
        }
 
        return validate_req_change_req_state(mdev, p->block_id, sector,
@@ -4250,20 +4361,44 @@ static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
        struct p_block_ack *p = (struct p_block_ack *)h;
        sector_t sector = be64_to_cpu(p->sector);
-
-       if (__ratelimit(&drbd_ratelimit_state))
-               dev_warn(DEV, "Got NegAck packet. Peer is in troubles?\n");
+       int size = be32_to_cpu(p->blksize);
+       struct drbd_request *req;
+       struct bio_and_error m;
 
        update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
        if (is_syncer_block_id(p->block_id)) {
-               int size = be32_to_cpu(p->blksize);
                dec_rs_pending(mdev);
                drbd_rs_failed_io(mdev, sector, size);
-               return TRUE;
+               return true;
        }
-       return validate_req_change_req_state(mdev, p->block_id, sector,
-               _ack_id_to_req, __func__ , neg_acked);
+
+       spin_lock_irq(&mdev->req_lock);
+       req = _ack_id_to_req(mdev, p->block_id, sector);
+       if (!req) {
+               spin_unlock_irq(&mdev->req_lock);
+               if (mdev->net_conf->wire_protocol == DRBD_PROT_A ||
+                   mdev->net_conf->wire_protocol == DRBD_PROT_B) {
+                       /* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
+                          The master bio might already be completed, therefore the
+                          request is no longer in the collision hash.
+                          => Do not try to validate block_id as request. */
+                       /* In Protocol B we might already have got a P_RECV_ACK
+                          but then get a P_NEG_ACK after wards. */
+                       drbd_set_out_of_sync(mdev, sector, size);
+                       return true;
+               } else {
+                       dev_err(DEV, "%s: failed to find req %p, sector %llus\n", __func__,
+                               (void *)(unsigned long)p->block_id, (unsigned long long)sector);
+                       return false;
+               }
+       }
+       __req_mod(req, neg_acked, &m);
+       spin_unlock_irq(&mdev->req_lock);
+
+       if (m.bio)
+               complete_master_bio(mdev, &m);
+       return true;
 }
 
 static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4294,11 +4429,20 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
 
        if (get_ldev_if_state(mdev, D_FAILED)) {
                drbd_rs_complete_io(mdev, sector);
-               drbd_rs_failed_io(mdev, sector, size);
+               switch (be16_to_cpu(h->command)) {
+               case P_NEG_RS_DREPLY:
+                       drbd_rs_failed_io(mdev, sector, size);
+               case P_RS_CANCEL:
+                       break;
+               default:
+                       D_ASSERT(0);
+                       put_ldev(mdev);
+                       return false;
+               }
                put_ldev(mdev);
        }
 
-       return TRUE;
+       return true;
 }
 
 static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4307,7 +4451,14 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
 
        tl_release(mdev, p->barrier, be32_to_cpu(p->set_size));
 
-       return TRUE;
+       if (mdev->state.conn == C_AHEAD &&
+           atomic_read(&mdev->ap_in_flight) == 0 &&
+           !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags)) {
+               mdev->start_resync_timer.expires = jiffies + HZ;
+               add_timer(&mdev->start_resync_timer);
+       }
+
+       return true;
 }
 
 static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4328,12 +4479,18 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
                ov_oos_print(mdev);
 
        if (!get_ldev(mdev))
-               return TRUE;
+               return true;
 
        drbd_rs_complete_io(mdev, sector);
        dec_rs_pending(mdev);
 
-       if (--mdev->ov_left == 0) {
+       --mdev->ov_left;
+
+       /* let's advance progress step marks only for every other megabyte */
+       if ((mdev->ov_left & 0x200) == 0x200)
+               drbd_advance_rs_marks(mdev, mdev->ov_left);
+
+       if (mdev->ov_left == 0) {
                w = kmalloc(sizeof(*w), GFP_NOIO);
                if (w) {
                        w->cb = w_ov_finished;
@@ -4345,12 +4502,12 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
                }
        }
        put_ldev(mdev);
-       return TRUE;
+       return true;
 }
 
 static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
 {
-       return TRUE;
+       return true;
 }
 
 struct asender_cmd {
@@ -4378,6 +4535,7 @@ static struct asender_cmd *get_asender_cmd(int cmd)
        [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
        [P_RS_IS_IN_SYNC]   = { sizeof(struct p_block_ack), got_IsInSync },
        [P_DELAY_PROBE]     = { sizeof(struct p_delay_probe93), got_skip },
+       [P_RS_CANCEL]       = { sizeof(struct p_block_ack), got_NegRSDReply},
        [P_MAX_CMD]         = { 0, NULL },
        };
        if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
index ad3fc6228f27924d3523976fd3a5a4486c3a5b4a..5c0c8be1bb0ae144e4d82ef9d3da257ca06af99d 100644 (file)
@@ -140,9 +140,14 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev,
        struct hlist_node *n;
        struct hlist_head *slot;
 
-       /* before we can signal completion to the upper layers,
-        * we may need to close the current epoch */
+       /* Before we can signal completion to the upper layers,
+        * we may need to close the current epoch.
+        * We can skip this, if this request has not even been sent, because we
+        * did not have a fully established connection yet/anymore, during
+        * bitmap exchange, or while we are C_AHEAD due to congestion policy.
+        */
        if (mdev->state.conn >= C_CONNECTED &&
+           (s & RQ_NET_SENT) != 0 &&
            req->epoch == mdev->newest_tle->br_number)
                queue_barrier(mdev);
 
@@ -440,7 +445,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                req->rq_state |= RQ_LOCAL_COMPLETED;
                req->rq_state &= ~RQ_LOCAL_PENDING;
 
-               __drbd_chk_io_error(mdev, FALSE);
+               __drbd_chk_io_error(mdev, false);
                _req_may_be_done_not_susp(req, m);
                put_ldev(mdev);
                break;
@@ -461,7 +466,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
                D_ASSERT(!(req->rq_state & RQ_NET_MASK));
 
-               __drbd_chk_io_error(mdev, FALSE);
+               __drbd_chk_io_error(mdev, false);
                put_ldev(mdev);
 
                /* no point in retrying if there is no good remote data,
@@ -545,6 +550,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
                break;
 
+       case queue_for_send_oos:
+               req->rq_state |= RQ_NET_QUEUED;
+               req->w.cb =  w_send_oos;
+               drbd_queue_work(&mdev->data.work, &req->w);
+               break;
+
+       case oos_handed_to_network:
+               /* actually the same */
        case send_canceled:
                /* treat it the same */
        case send_failed:
@@ -558,6 +571,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
        case handed_over_to_network:
                /* assert something? */
+               if (bio_data_dir(req->master_bio) == WRITE)
+                       atomic_add(req->size>>9, &mdev->ap_in_flight);
+
                if (bio_data_dir(req->master_bio) == WRITE &&
                    mdev->net_conf->wire_protocol == DRBD_PROT_A) {
                        /* this is what is dangerous about protocol A:
@@ -591,6 +607,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                        dec_ap_pending(mdev);
                req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
                req->rq_state |= RQ_NET_DONE;
+               if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE)
+                       atomic_sub(req->size>>9, &mdev->ap_in_flight);
+
                /* if it is still queued, we may not complete it here.
                 * it will be canceled soon. */
                if (!(req->rq_state & RQ_NET_QUEUED))
@@ -628,14 +647,17 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                req->rq_state |= RQ_NET_OK;
                D_ASSERT(req->rq_state & RQ_NET_PENDING);
                dec_ap_pending(mdev);
+               atomic_sub(req->size>>9, &mdev->ap_in_flight);
                req->rq_state &= ~RQ_NET_PENDING;
                _req_may_be_done_not_susp(req, m);
                break;
 
        case neg_acked:
                /* assert something? */
-               if (req->rq_state & RQ_NET_PENDING)
+               if (req->rq_state & RQ_NET_PENDING) {
                        dec_ap_pending(mdev);
+                       atomic_sub(req->size>>9, &mdev->ap_in_flight);
+               }
                req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
 
                req->rq_state |= RQ_NET_DONE;
@@ -690,8 +712,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                        dev_err(DEV, "FIXME (barrier_acked but pending)\n");
                        list_move(&req->tl_requests, &mdev->out_of_sequence_requests);
                }
-               D_ASSERT(req->rq_state & RQ_NET_SENT);
-               req->rq_state |= RQ_NET_DONE;
+               if ((req->rq_state & RQ_NET_MASK) != 0) {
+                       req->rq_state |= RQ_NET_DONE;
+                       if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
+                               atomic_sub(req->size>>9, &mdev->ap_in_flight);
+               }
                _req_may_be_done(req, m); /* Allowed while state.susp */
                break;
 
@@ -738,14 +763,14 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s
        return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr);
 }
 
-static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
+static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
 {
        const int rw = bio_rw(bio);
        const int size = bio->bi_size;
        const sector_t sector = bio->bi_sector;
        struct drbd_tl_epoch *b = NULL;
        struct drbd_request *req;
-       int local, remote;
+       int local, remote, send_oos = 0;
        int err = -EIO;
        int ret = 0;
 
@@ -759,6 +784,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
                bio_endio(bio, -ENOMEM);
                return 0;
        }
+       req->start_time = start_time;
 
        local = get_ldev(mdev);
        if (!local) {
@@ -808,9 +834,9 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
                drbd_al_begin_io(mdev, sector);
        }
 
-       remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
-                           (mdev->state.pdsk == D_INCONSISTENT &&
-                            mdev->state.conn >= C_CONNECTED));
+       remote = remote && drbd_should_do_remote(mdev->state);
+       send_oos = rw == WRITE && drbd_should_send_oos(mdev->state);
+       D_ASSERT(!(remote && send_oos));
 
        if (!(local || remote) && !is_susp(mdev->state)) {
                if (__ratelimit(&drbd_ratelimit_state))
@@ -824,7 +850,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
         * but there is a race between testing the bit and pointer outside the
         * spinlock, and grabbing the spinlock.
         * if we lost that race, we retry.  */
-       if (rw == WRITE && remote &&
+       if (rw == WRITE && (remote || send_oos) &&
            mdev->unused_spare_tle == NULL &&
            test_bit(CREATE_BARRIER, &mdev->flags)) {
 allocate_barrier:
@@ -842,18 +868,19 @@ allocate_barrier:
        if (is_susp(mdev->state)) {
                /* If we got suspended, use the retry mechanism of
                   generic_make_request() to restart processing of this
-                  bio. In the next call to drbd_make_request_26
+                  bio. In the next call to drbd_make_request
                   we sleep in inc_ap_bio() */
                ret = 1;
                spin_unlock_irq(&mdev->req_lock);
                goto fail_free_complete;
        }
 
-       if (remote) {
-               remote = (mdev->state.pdsk == D_UP_TO_DATE ||
-                           (mdev->state.pdsk == D_INCONSISTENT &&
-                            mdev->state.conn >= C_CONNECTED));
-               if (!remote)
+       if (remote || send_oos) {
+               remote = drbd_should_do_remote(mdev->state);
+               send_oos = rw == WRITE && drbd_should_send_oos(mdev->state);
+               D_ASSERT(!(remote && send_oos));
+
+               if (!(remote || send_oos))
                        dev_warn(DEV, "lost connection while grabbing the req_lock!\n");
                if (!(local || remote)) {
                        dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
@@ -866,7 +893,7 @@ allocate_barrier:
                mdev->unused_spare_tle = b;
                b = NULL;
        }
-       if (rw == WRITE && remote &&
+       if (rw == WRITE && (remote || send_oos) &&
            mdev->unused_spare_tle == NULL &&
            test_bit(CREATE_BARRIER, &mdev->flags)) {
                /* someone closed the current epoch
@@ -889,7 +916,7 @@ allocate_barrier:
         * barrier packet.  To get the write ordering right, we only have to
         * make sure that, if this is a write request and it triggered a
         * barrier packet, this request is queued within the same spinlock. */
-       if (remote && mdev->unused_spare_tle &&
+       if ((remote || send_oos) && mdev->unused_spare_tle &&
            test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) {
                _tl_add_barrier(mdev, mdev->unused_spare_tle);
                mdev->unused_spare_tle = NULL;
@@ -937,6 +964,34 @@ allocate_barrier:
                                ? queue_for_net_write
                                : queue_for_net_read);
        }
+       if (send_oos && drbd_set_out_of_sync(mdev, sector, size))
+               _req_mod(req, queue_for_send_oos);
+
+       if (remote &&
+           mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) {
+               int congested = 0;
+
+               if (mdev->net_conf->cong_fill &&
+                   atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) {
+                       dev_info(DEV, "Congestion-fill threshold reached\n");
+                       congested = 1;
+               }
+
+               if (mdev->act_log->used >= mdev->net_conf->cong_extents) {
+                       dev_info(DEV, "Congestion-extents threshold reached\n");
+                       congested = 1;
+               }
+
+               if (congested) {
+                       queue_barrier(mdev); /* last barrier, after mirrored writes */
+
+                       if (mdev->net_conf->on_congestion == OC_PULL_AHEAD)
+                               _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
+                       else  /*mdev->net_conf->on_congestion == OC_DISCONNECT */
+                               _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
+               }
+       }
+
        spin_unlock_irq(&mdev->req_lock);
        kfree(b); /* if someone else has beaten us to it... */
 
@@ -949,9 +1004,9 @@ allocate_barrier:
                 * stable storage, and this is a WRITE, we may not even submit
                 * this bio. */
                if (get_ldev(mdev)) {
-                       if (FAULT_ACTIVE(mdev, rw == WRITE ? DRBD_FAULT_DT_WR
-                                            : rw == READ  ? DRBD_FAULT_DT_RD
-                                            :               DRBD_FAULT_DT_RA))
+                       if (drbd_insert_fault(mdev,   rw == WRITE ? DRBD_FAULT_DT_WR
+                                                   : rw == READ  ? DRBD_FAULT_DT_RD
+                                                   :               DRBD_FAULT_DT_RA))
                                bio_endio(req->private_bio, -EIO);
                        else
                                generic_make_request(req->private_bio);
@@ -1018,16 +1073,19 @@ static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write)
        return 0;
 }
 
-int drbd_make_request_26(struct request_queue *q, struct bio *bio)
+int drbd_make_request(struct request_queue *q, struct bio *bio)
 {
        unsigned int s_enr, e_enr;
        struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
+       unsigned long start_time;
 
        if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
                bio_endio(bio, -EPERM);
                return 0;
        }
 
+       start_time = jiffies;
+
        /*
         * what we "blindly" assume:
         */
@@ -1042,12 +1100,12 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
 
        if (likely(s_enr == e_enr)) {
                inc_ap_bio(mdev, 1);
-               return drbd_make_request_common(mdev, bio);
+               return drbd_make_request_common(mdev, bio, start_time);
        }
 
        /* can this bio be split generically?
         * Maybe add our own split-arbitrary-bios function. */
-       if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_SEGMENT_SIZE) {
+       if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) {
                /* rather error out here than BUG in bio_split */
                dev_err(DEV, "bio would need to, but cannot, be split: "
                    "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n",
@@ -1069,11 +1127,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
                const int sps = 1 << HT_SHIFT; /* sectors per slot */
                const int mask = sps - 1;
                const sector_t first_sectors = sps - (sect & mask);
-               bp = bio_split(bio,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-                               bio_split_pool,
-#endif
-                               first_sectors);
+               bp = bio_split(bio, first_sectors);
 
                /* we need to get a "reference count" (ap_bio_cnt)
                 * to avoid races with the disconnect/reconnect/suspend code.
@@ -1084,10 +1138,10 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
 
                D_ASSERT(e_enr == s_enr + 1);
 
-               while (drbd_make_request_common(mdev, &bp->bio1))
+               while (drbd_make_request_common(mdev, &bp->bio1, start_time))
                        inc_ap_bio(mdev, 1);
 
-               while (drbd_make_request_common(mdev, &bp->bio2))
+               while (drbd_make_request_common(mdev, &bp->bio2, start_time))
                        inc_ap_bio(mdev, 1);
 
                dec_ap_bio(mdev);
@@ -1098,7 +1152,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
 }
 
 /* This is called by bio_add_page().  With this function we reduce
- * the number of BIOs that span over multiple DRBD_MAX_SEGMENT_SIZEs
+ * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs
  * units (was AL_EXTENTs).
  *
  * we do the calculation within the lower 32bit of the byte offsets,
@@ -1108,7 +1162,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
  * As long as the BIO is empty we have to allow at least one bvec,
  * regardless of size and offset.  so the resulting bio may still
  * cross extent boundaries.  those are dealt with (bio_split) in
- * drbd_make_request_26.
+ * drbd_make_request.
  */
 int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
 {
@@ -1118,8 +1172,8 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
        unsigned int bio_size = bvm->bi_size;
        int limit, backing_limit;
 
-       limit = DRBD_MAX_SEGMENT_SIZE
-             - ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size);
+       limit = DRBD_MAX_BIO_SIZE
+             - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size);
        if (limit < 0)
                limit = 0;
        if (bio_size == 0) {
@@ -1136,3 +1190,42 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
        }
        return limit;
 }
+
+void request_timer_fn(unsigned long data)
+{
+       struct drbd_conf *mdev = (struct drbd_conf *) data;
+       struct drbd_request *req; /* oldest request */
+       struct list_head *le;
+       unsigned long et = 0; /* effective timeout = ko_count * timeout */
+
+       if (get_net_conf(mdev)) {
+               et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count;
+               put_net_conf(mdev);
+       }
+       if (!et || mdev->state.conn < C_WF_REPORT_PARAMS)
+               return; /* Recurring timer stopped */
+
+       spin_lock_irq(&mdev->req_lock);
+       le = &mdev->oldest_tle->requests;
+       if (list_empty(le)) {
+               spin_unlock_irq(&mdev->req_lock);
+               mod_timer(&mdev->request_timer, jiffies + et);
+               return;
+       }
+
+       le = le->prev;
+       req = list_entry(le, struct drbd_request, tl_requests);
+       if (time_is_before_eq_jiffies(req->start_time + et)) {
+               if (req->rq_state & RQ_NET_PENDING) {
+                       dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
+                       _drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL);
+               } else {
+                       dev_warn(DEV, "Local backing block device frozen?\n");
+                       mod_timer(&mdev->request_timer, jiffies + et);
+               }
+       } else {
+               mod_timer(&mdev->request_timer, req->start_time + et);
+       }
+
+       spin_unlock_irq(&mdev->req_lock);
+}
index ab2bd09d54b4bfc9fbf7bf74c2e46dbbeb389db5..32e2c3e6a8134220943873c671cb7ac6adf83a10 100644 (file)
@@ -82,14 +82,16 @@ enum drbd_req_event {
        to_be_submitted,
 
        /* XXX yes, now I am inconsistent...
-        * these two are not "events" but "actions"
+        * these are not "events" but "actions"
         * oh, well... */
        queue_for_net_write,
        queue_for_net_read,
+       queue_for_send_oos,
 
        send_canceled,
        send_failed,
        handed_over_to_network,
+       oos_handed_to_network,
        connection_lost_while_pending,
        read_retry_remote_canceled,
        recv_acked_by_peer,
@@ -289,7 +291,6 @@ static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
                req->epoch       = 0;
                req->sector      = bio_src->bi_sector;
                req->size        = bio_src->bi_size;
-               req->start_time  = jiffies;
                INIT_HLIST_NODE(&req->colision);
                INIT_LIST_HEAD(&req->tl_requests);
                INIT_LIST_HEAD(&req->w.list);
@@ -321,6 +322,7 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                struct bio_and_error *m);
 extern void complete_master_bio(struct drbd_conf *mdev,
                struct bio_and_error *m);
+extern void request_timer_fn(unsigned long data);
 
 /* use this if you don't want to deal with calling complete_master_bio()
  * outside the spinlock, e.g. when walking some list on cleanup. */
@@ -338,23 +340,43 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
        return rv;
 }
 
-/* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self!
- * Which means: don't use from bio endio callback. */
+/* completion of master bio is outside of our spinlock.
+ * We still may or may not be inside some irqs disabled section
+ * of the lower level driver completion callback, so we need to
+ * spin_lock_irqsave here. */
 static inline int req_mod(struct drbd_request *req,
                enum drbd_req_event what)
 {
+       unsigned long flags;
        struct drbd_conf *mdev = req->mdev;
        struct bio_and_error m;
        int rv;
 
-       spin_lock_irq(&mdev->req_lock);
+       spin_lock_irqsave(&mdev->req_lock, flags);
        rv = __req_mod(req, what, &m);
-       spin_unlock_irq(&mdev->req_lock);
+       spin_unlock_irqrestore(&mdev->req_lock, flags);
 
        if (m.bio)
                complete_master_bio(mdev, &m);
 
        return rv;
 }
+
+static inline bool drbd_should_do_remote(union drbd_state s)
+{
+       return s.pdsk == D_UP_TO_DATE ||
+               (s.pdsk >= D_INCONSISTENT &&
+                s.conn >= C_WF_BITMAP_T &&
+                s.conn < C_AHEAD);
+       /* Before proto 96 that was >= CONNECTED instead of >= C_WF_BITMAP_T.
+          That is equivalent since before 96 IO was frozen in the C_WF_BITMAP*
+          states. */
+}
+static inline bool drbd_should_send_oos(union drbd_state s)
+{
+       return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S;
+       /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary
+          since we enter state C_AHEAD only if proto >= 96 */
+}
+
 #endif
index 85179e1fb50a62ff6d7593e3204a4d19d835e6b3..c44a2a6027724ddaf373664728bf6b2b592b68b7 100644 (file)
@@ -48,6 +48,8 @@ static const char *drbd_conn_s_names[] = {
        [C_PAUSED_SYNC_T]    = "PausedSyncT",
        [C_VERIFY_S]         = "VerifyS",
        [C_VERIFY_T]         = "VerifyT",
+       [C_AHEAD]            = "Ahead",
+       [C_BEHIND]           = "Behind",
 };
 
 static const char *drbd_role_s_names[] = {
@@ -92,7 +94,7 @@ static const char *drbd_state_sw_errors[] = {
 const char *drbd_conn_str(enum drbd_conns s)
 {
        /* enums are unsigned... */
-       return s > C_PAUSED_SYNC_T ? "TOO_LARGE" : drbd_conn_s_names[s];
+       return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s];
 }
 
 const char *drbd_role_str(enum drbd_role s)
@@ -105,7 +107,7 @@ const char *drbd_disk_str(enum drbd_disk_state s)
        return s > D_UP_TO_DATE    ? "TOO_LARGE" : drbd_disk_s_names[s];
 }
 
-const char *drbd_set_st_err_str(enum drbd_state_ret_codes err)
+const char *drbd_set_st_err_str(enum drbd_state_rv err)
 {
        return err <= SS_AFTER_LAST_ERROR ? "TOO_SMALL" :
               err > SS_TWO_PRIMARIES ? "TOO_LARGE"
index e027446590d3752d63d2301c7d65e17d749f7b13..f7e6c92f8d03d001c1a452fe92b0c605c450bd38 100644 (file)
 #include "drbd_req.h"
 
 static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
+static int w_make_resync_request(struct drbd_conf *mdev,
+                                struct drbd_work *w, int cancel);
 
 
 
-/* defined here:
-   drbd_md_io_complete
-   drbd_endio_sec
-   drbd_endio_pri
-
- * more endio handlers:
-   atodb_endio in drbd_actlog.c
-   drbd_bm_async_io_complete in drbd_bitmap.c
-
+/* endio handlers:
+ *   drbd_md_io_complete (defined here)
+ *   drbd_endio_pri (defined here)
+ *   drbd_endio_sec (defined here)
+ *   bm_async_io_complete (defined in drbd_bitmap.c)
+ *
  * For all these callbacks, note the following:
  * The callbacks will be called in irq context by the IDE drivers,
  * and in Softirqs/Tasklets/BH context by the SCSI drivers.
@@ -94,7 +93,7 @@ void drbd_endio_read_sec_final(struct drbd_epoch_entry *e) __releases(local)
        if (list_empty(&mdev->read_ee))
                wake_up(&mdev->ee_wait);
        if (test_bit(__EE_WAS_ERROR, &e->flags))
-               __drbd_chk_io_error(mdev, FALSE);
+               __drbd_chk_io_error(mdev, false);
        spin_unlock_irqrestore(&mdev->req_lock, flags);
 
        drbd_queue_work(&mdev->data.work, &e->w);
@@ -137,7 +136,7 @@ static void drbd_endio_write_sec_final(struct drbd_epoch_entry *e) __releases(lo
                : list_empty(&mdev->active_ee);
 
        if (test_bit(__EE_WAS_ERROR, &e->flags))
-               __drbd_chk_io_error(mdev, FALSE);
+               __drbd_chk_io_error(mdev, false);
        spin_unlock_irqrestore(&mdev->req_lock, flags);
 
        if (is_syncer_req)
@@ -163,14 +162,15 @@ void drbd_endio_sec(struct bio *bio, int error)
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
        int is_write = bio_data_dir(bio) == WRITE;
 
-       if (error)
+       if (error && __ratelimit(&drbd_ratelimit_state))
                dev_warn(DEV, "%s: error=%d s=%llus\n",
                                is_write ? "write" : "read", error,
                                (unsigned long long)e->sector);
        if (!error && !uptodate) {
-               dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
-                               is_write ? "write" : "read",
-                               (unsigned long long)e->sector);
+               if (__ratelimit(&drbd_ratelimit_state))
+                       dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
+                                       is_write ? "write" : "read",
+                                       (unsigned long long)e->sector);
                /* strange behavior of some lower level drivers...
                 * fail the request by clearing the uptodate flag,
                 * but do not return any error?! */
@@ -250,13 +250,6 @@ int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
        return w_send_read_req(mdev, w, 0);
 }
 
-int w_resync_inactive(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-       ERR_IF(cancel) return 1;
-       dev_err(DEV, "resync inactive, but callback triggered??\n");
-       return 1; /* Simply ignore this! */
-}
-
 void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, struct drbd_epoch_entry *e, void *digest)
 {
        struct hash_desc desc;
@@ -355,7 +348,7 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
        if (!get_ldev(mdev))
                return -EIO;
 
-       if (drbd_rs_should_slow_down(mdev))
+       if (drbd_rs_should_slow_down(mdev, sector))
                goto defer;
 
        /* GFP_TRY, because if there is no memory available right now, this may
@@ -373,9 +366,10 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
        if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
                return 0;
 
-       /* drbd_submit_ee currently fails for one reason only:
-        * not being able to allocate enough bios.
-        * Is dropping the connection going to help? */
+       /* If it failed because of ENOMEM, retry should help.  If it failed
+        * because bio_add_page failed (probably broken lower level driver),
+        * retry may or may not help.
+        * If it does not, you may need to force disconnect. */
        spin_lock_irq(&mdev->req_lock);
        list_del(&e->w.list);
        spin_unlock_irq(&mdev->req_lock);
@@ -386,26 +380,25 @@ defer:
        return -EAGAIN;
 }
 
-void resync_timer_fn(unsigned long data)
+int w_resync_timer(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 {
-       struct drbd_conf *mdev = (struct drbd_conf *) data;
-       int queue;
-
-       queue = 1;
        switch (mdev->state.conn) {
        case C_VERIFY_S:
-               mdev->resync_work.cb = w_make_ov_request;
+               w_make_ov_request(mdev, w, cancel);
                break;
        case C_SYNC_TARGET:
-               mdev->resync_work.cb = w_make_resync_request;
+               w_make_resync_request(mdev, w, cancel);
                break;
-       default:
-               queue = 0;
-               mdev->resync_work.cb = w_resync_inactive;
        }
 
-       /* harmless race: list_empty outside data.work.q_lock */
-       if (list_empty(&mdev->resync_work.list) && queue)
+       return 1;
+}
+
+void resync_timer_fn(unsigned long data)
+{
+       struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+       if (list_empty(&mdev->resync_work.list))
                drbd_queue_work(&mdev->data.work, &mdev->resync_work);
 }
 
@@ -438,7 +431,7 @@ static void fifo_add_val(struct fifo_buffer *fb, int value)
                fb->values[i] += value;
 }
 
-int drbd_rs_controller(struct drbd_conf *mdev)
+static int drbd_rs_controller(struct drbd_conf *mdev)
 {
        unsigned int sect_in;  /* Number of sectors that came in since the last turn */
        unsigned int want;     /* The number of sectors we want in the proxy */
@@ -492,29 +485,36 @@ int drbd_rs_controller(struct drbd_conf *mdev)
        return req_sect;
 }
 
-int w_make_resync_request(struct drbd_conf *mdev,
-               struct drbd_work *w, int cancel)
+static int drbd_rs_number_requests(struct drbd_conf *mdev)
+{
+       int number;
+       if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+               number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
+               mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+       } else {
+               mdev->c_sync_rate = mdev->sync_conf.rate;
+               number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
+       }
+
+       /* ignore the amount of pending requests, the resync controller should
+        * throttle down to incoming reply rate soon enough anyways. */
+       return number;
+}
+
+static int w_make_resync_request(struct drbd_conf *mdev,
+                                struct drbd_work *w, int cancel)
 {
        unsigned long bit;
        sector_t sector;
        const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
-       int max_segment_size;
-       int number, rollback_i, size, pe, mx;
+       int max_bio_size;
+       int number, rollback_i, size;
        int align, queued, sndbuf;
        int i = 0;
 
        if (unlikely(cancel))
                return 1;
 
-       if (unlikely(mdev->state.conn < C_CONNECTED)) {
-               dev_err(DEV, "Confused in w_make_resync_request()! cstate < Connected");
-               return 0;
-       }
-
-       if (mdev->state.conn != C_SYNC_TARGET)
-               dev_err(DEV, "%s in w_make_resync_request\n",
-                       drbd_conn_str(mdev->state.conn));
-
        if (mdev->rs_total == 0) {
                /* empty resync? */
                drbd_resync_finished(mdev);
@@ -527,49 +527,19 @@ int w_make_resync_request(struct drbd_conf *mdev,
                   to continue resync with a broken disk makes no sense at
                   all */
                dev_err(DEV, "Disk broke down during resync!\n");
-               mdev->resync_work.cb = w_resync_inactive;
                return 1;
        }
 
        /* starting with drbd 8.3.8, we can handle multi-bio EEs,
         * if it should be necessary */
-       max_segment_size =
-               mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) :
-               mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE;
+       max_bio_size =
+               mdev->agreed_pro_version < 94 ? queue_max_hw_sectors(mdev->rq_queue) << 9 :
+               mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_BIO_SIZE;
 
-       if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
-               number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
-               mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
-       } else {
-               mdev->c_sync_rate = mdev->sync_conf.rate;
-               number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
-       }
-
-       /* Throttle resync on lower level disk activity, which may also be
-        * caused by application IO on Primary/SyncTarget.
-        * Keep this after the call to drbd_rs_controller, as that assumes
-        * to be called as precisely as possible every SLEEP_TIME,
-        * and would be confused otherwise. */
-       if (drbd_rs_should_slow_down(mdev))
+       number = drbd_rs_number_requests(mdev);
+       if (number == 0)
                goto requeue;
 
-       mutex_lock(&mdev->data.mutex);
-       if (mdev->data.socket)
-               mx = mdev->data.socket->sk->sk_rcvbuf / sizeof(struct p_block_req);
-       else
-               mx = 1;
-       mutex_unlock(&mdev->data.mutex);
-
-       /* For resync rates >160MB/sec, allow more pending RS requests */
-       if (number > mx)
-               mx = number;
-
-       /* Limit the number of pending RS requests to no more than the peer's receive buffer */
-       pe = atomic_read(&mdev->rs_pending_cnt);
-       if ((pe + number) > mx) {
-               number = mx - pe;
-       }
-
        for (i = 0; i < number; i++) {
                /* Stop generating RS requests, when half of the send buffer is filled */
                mutex_lock(&mdev->data.mutex);
@@ -588,16 +558,16 @@ next_sector:
                size = BM_BLOCK_SIZE;
                bit  = drbd_bm_find_next(mdev, mdev->bm_resync_fo);
 
-               if (bit == -1UL) {
+               if (bit == DRBD_END_OF_BITMAP) {
                        mdev->bm_resync_fo = drbd_bm_bits(mdev);
-                       mdev->resync_work.cb = w_resync_inactive;
                        put_ldev(mdev);
                        return 1;
                }
 
                sector = BM_BIT_TO_SECT(bit);
 
-               if (drbd_try_rs_begin_io(mdev, sector)) {
+               if (drbd_rs_should_slow_down(mdev, sector) ||
+                   drbd_try_rs_begin_io(mdev, sector)) {
                        mdev->bm_resync_fo = bit;
                        goto requeue;
                }
@@ -608,7 +578,7 @@ next_sector:
                        goto next_sector;
                }
 
-#if DRBD_MAX_SEGMENT_SIZE > BM_BLOCK_SIZE
+#if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE
                /* try to find some adjacent bits.
                 * we stop if we have already the maximum req size.
                 *
@@ -618,7 +588,7 @@ next_sector:
                align = 1;
                rollback_i = i;
                for (;;) {
-                       if (size + BM_BLOCK_SIZE > max_segment_size)
+                       if (size + BM_BLOCK_SIZE > max_bio_size)
                                break;
 
                        /* Be always aligned */
@@ -685,7 +655,6 @@ next_sector:
                 * resync data block, and the last bit is cleared.
                 * until then resync "work" is "inactive" ...
                 */
-               mdev->resync_work.cb = w_resync_inactive;
                put_ldev(mdev);
                return 1;
        }
@@ -706,27 +675,18 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca
        if (unlikely(cancel))
                return 1;
 
-       if (unlikely(mdev->state.conn < C_CONNECTED)) {
-               dev_err(DEV, "Confused in w_make_ov_request()! cstate < Connected");
-               return 0;
-       }
-
-       number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ);
-       if (atomic_read(&mdev->rs_pending_cnt) > number)
-               goto requeue;
-
-       number -= atomic_read(&mdev->rs_pending_cnt);
+       number = drbd_rs_number_requests(mdev);
 
        sector = mdev->ov_position;
        for (i = 0; i < number; i++) {
                if (sector >= capacity) {
-                       mdev->resync_work.cb = w_resync_inactive;
                        return 1;
                }
 
                size = BM_BLOCK_SIZE;
 
-               if (drbd_try_rs_begin_io(mdev, sector)) {
+               if (drbd_rs_should_slow_down(mdev, sector) ||
+                   drbd_try_rs_begin_io(mdev, sector)) {
                        mdev->ov_position = sector;
                        goto requeue;
                }
@@ -744,11 +704,33 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca
        mdev->ov_position = sector;
 
  requeue:
+       mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
        mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
        return 1;
 }
 
 
+void start_resync_timer_fn(unsigned long data)
+{
+       struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+       drbd_queue_work(&mdev->data.work, &mdev->start_resync_work);
+}
+
+int w_start_resync(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+       if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) {
+               dev_warn(DEV, "w_start_resync later...\n");
+               mdev->start_resync_timer.expires = jiffies + HZ/10;
+               add_timer(&mdev->start_resync_timer);
+               return 1;
+       }
+
+       drbd_start_resync(mdev, C_SYNC_SOURCE);
+       clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags);
+       return 1;
+}
+
 int w_ov_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 {
        kfree(w);
@@ -782,6 +764,7 @@ int drbd_resync_finished(struct drbd_conf *mdev)
        union drbd_state os, ns;
        struct drbd_work *w;
        char *khelper_cmd = NULL;
+       int verify_done = 0;
 
        /* Remove all elements from the resync LRU. Since future actions
         * might set bits in the (main) bitmap, then the entries in the
@@ -792,8 +775,7 @@ int drbd_resync_finished(struct drbd_conf *mdev)
                 * queue (or even the read operations for those packets
                 * is not finished by now).   Retry in 100ms. */
 
-               __set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ / 10);
+               schedule_timeout_interruptible(HZ / 10);
                w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC);
                if (w) {
                        w->cb = w_resync_finished;
@@ -818,6 +800,8 @@ int drbd_resync_finished(struct drbd_conf *mdev)
        spin_lock_irq(&mdev->req_lock);
        os = mdev->state;
 
+       verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
+
        /* This protects us against multiple calls (that can happen in the presence
           of application IO), and against connectivity loss just before we arrive here. */
        if (os.conn <= C_CONNECTED)
@@ -827,8 +811,7 @@ int drbd_resync_finished(struct drbd_conf *mdev)
        ns.conn = C_CONNECTED;
 
        dev_info(DEV, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
-            (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) ?
-            "Online verify " : "Resync",
+            verify_done ? "Online verify " : "Resync",
             dt + mdev->rs_paused, mdev->rs_paused, dbdt);
 
        n_oos = drbd_bm_total_weight(mdev);
@@ -886,14 +869,18 @@ int drbd_resync_finished(struct drbd_conf *mdev)
                        }
                }
 
-               drbd_uuid_set_bm(mdev, 0UL);
-
-               if (mdev->p_uuid) {
-                       /* Now the two UUID sets are equal, update what we
-                        * know of the peer. */
-                       int i;
-                       for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
-                               mdev->p_uuid[i] = mdev->ldev->md.uuid[i];
+               if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) {
+                       /* for verify runs, we don't update uuids here,
+                        * so there would be nothing to report. */
+                       drbd_uuid_set_bm(mdev, 0UL);
+                       drbd_print_uuids(mdev, "updated UUIDs");
+                       if (mdev->p_uuid) {
+                               /* Now the two UUID sets are equal, update what we
+                                * know of the peer. */
+                               int i;
+                               for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
+                                       mdev->p_uuid[i] = mdev->ldev->md.uuid[i];
+                       }
                }
        }
 
@@ -905,15 +892,11 @@ out:
        mdev->rs_total  = 0;
        mdev->rs_failed = 0;
        mdev->rs_paused = 0;
-       mdev->ov_start_sector = 0;
+       if (verify_done)
+               mdev->ov_start_sector = 0;
 
        drbd_md_sync(mdev);
 
-       if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) {
-               dev_info(DEV, "Writing the whole bitmap\n");
-               drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished");
-       }
-
        if (khelper_cmd)
                drbd_khelper(mdev, khelper_cmd);
 
@@ -994,7 +977,9 @@ int w_e_end_rsdata_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
                put_ldev(mdev);
        }
 
-       if (likely((e->flags & EE_WAS_ERROR) == 0)) {
+       if (mdev->state.conn == C_AHEAD) {
+               ok = drbd_send_ack(mdev, P_RS_CANCEL, e);
+       } else if (likely((e->flags & EE_WAS_ERROR) == 0)) {
                if (likely(mdev->state.pdsk >= D_INCONSISTENT)) {
                        inc_rs_pending(mdev);
                        ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
@@ -1096,25 +1081,27 @@ int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
        if (unlikely(cancel))
                goto out;
 
-       if (unlikely((e->flags & EE_WAS_ERROR) != 0))
-               goto out;
-
        digest_size = crypto_hash_digestsize(mdev->verify_tfm);
-       /* FIXME if this allocation fails, online verify will not terminate! */
        digest = kmalloc(digest_size, GFP_NOIO);
-       if (digest) {
-               drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
-               inc_rs_pending(mdev);
-               ok = drbd_send_drequest_csum(mdev, e->sector, e->size,
-                                            digest, digest_size, P_OV_REPLY);
-               if (!ok)
-                       dec_rs_pending(mdev);
-               kfree(digest);
+       if (!digest) {
+               ok = 0; /* terminate the connection in case the allocation failed */
+               goto out;
        }
 
+       if (likely(!(e->flags & EE_WAS_ERROR)))
+               drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
+       else
+               memset(digest, 0, digest_size);
+
+       inc_rs_pending(mdev);
+       ok = drbd_send_drequest_csum(mdev, e->sector, e->size,
+                                    digest, digest_size, P_OV_REPLY);
+       if (!ok)
+               dec_rs_pending(mdev);
+       kfree(digest);
+
 out:
        drbd_free_ee(mdev, e);
-
        dec_unacked(mdev);
 
        return ok;
@@ -1129,7 +1116,6 @@ void drbd_ov_oos_found(struct drbd_conf *mdev, sector_t sector, int size)
                mdev->ov_last_oos_size = size>>9;
        }
        drbd_set_out_of_sync(mdev, sector, size);
-       set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
 }
 
 int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
@@ -1165,10 +1151,6 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
                        eq = !memcmp(digest, di->digest, digest_size);
                        kfree(digest);
                }
-       } else {
-               ok = drbd_send_ack(mdev, P_NEG_RS_DREPLY, e);
-               if (__ratelimit(&drbd_ratelimit_state))
-                       dev_err(DEV, "Sending NegDReply. I guess it gets messy.\n");
        }
 
        dec_unacked(mdev);
@@ -1182,7 +1164,13 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 
        drbd_free_ee(mdev, e);
 
-       if (--mdev->ov_left == 0) {
+       --mdev->ov_left;
+
+       /* let's advance progress step marks only for every other megabyte */
+       if ((mdev->ov_left & 0x200) == 0x200)
+               drbd_advance_rs_marks(mdev, mdev->ov_left);
+
+       if (mdev->ov_left == 0) {
                ov_oos_print(mdev);
                drbd_resync_finished(mdev);
        }
@@ -1235,6 +1223,22 @@ int w_send_write_hint(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
        return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE);
 }
 
+int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+       struct drbd_request *req = container_of(w, struct drbd_request, w);
+       int ok;
+
+       if (unlikely(cancel)) {
+               req_mod(req, send_canceled);
+               return 1;
+       }
+
+       ok = drbd_send_oos(mdev, req);
+       req_mod(req, oos_handed_to_network);
+
+       return ok;
+}
+
 /**
  * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request
  * @mdev:      DRBD device.
@@ -1430,6 +1434,17 @@ int drbd_alter_sa(struct drbd_conf *mdev, int na)
        return retcode;
 }
 
+void drbd_rs_controller_reset(struct drbd_conf *mdev)
+{
+       atomic_set(&mdev->rs_sect_in, 0);
+       atomic_set(&mdev->rs_sect_ev, 0);
+       mdev->rs_in_flight = 0;
+       mdev->rs_planed = 0;
+       spin_lock(&mdev->peer_seq_lock);
+       fifo_set(&mdev->rs_plan_s, 0);
+       spin_unlock(&mdev->peer_seq_lock);
+}
+
 /**
  * drbd_start_resync() - Start the resync process
  * @mdev:      DRBD device.
@@ -1443,13 +1458,18 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
        union drbd_state ns;
        int r;
 
-       if (mdev->state.conn >= C_SYNC_SOURCE) {
+       if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn < C_AHEAD) {
                dev_err(DEV, "Resync already running!\n");
                return;
        }
 
-       /* In case a previous resync run was aborted by an IO error/detach on the peer. */
-       drbd_rs_cancel_all(mdev);
+       if (mdev->state.conn < C_AHEAD) {
+               /* In case a previous resync run was aborted by an IO error/detach on the peer. */
+               drbd_rs_cancel_all(mdev);
+               /* This should be done when we abort the resync. We definitely do not
+                  want to have this for connections going back and forth between
+                  Ahead/Behind and SyncSource/SyncTarget */
+       }
 
        if (side == C_SYNC_TARGET) {
                /* Since application IO was locked out during C_WF_BITMAP_T and
@@ -1463,6 +1483,20 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
                        drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
                        return;
                }
+       } else /* C_SYNC_SOURCE */ {
+               r = drbd_khelper(mdev, "before-resync-source");
+               r = (r >> 8) & 0xff;
+               if (r > 0) {
+                       if (r == 3) {
+                               dev_info(DEV, "before-resync-source handler returned %d, "
+                                        "ignoring. Old userland tools?", r);
+                       } else {
+                               dev_info(DEV, "before-resync-source handler returned %d, "
+                                        "dropping connection.\n", r);
+                               drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+                               return;
+                       }
+               }
        }
 
        drbd_state_lock(mdev);
@@ -1472,18 +1506,6 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
                return;
        }
 
-       if (side == C_SYNC_TARGET) {
-               mdev->bm_resync_fo = 0;
-       } else /* side == C_SYNC_SOURCE */ {
-               u64 uuid;
-
-               get_random_bytes(&uuid, sizeof(u64));
-               drbd_uuid_set(mdev, UI_BITMAP, uuid);
-               drbd_send_sync_uuid(mdev, uuid);
-
-               D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
-       }
-
        write_lock_irq(&global_state_lock);
        ns = mdev->state;
 
@@ -1521,13 +1543,24 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
                _drbd_pause_after(mdev);
        }
        write_unlock_irq(&global_state_lock);
-       put_ldev(mdev);
 
        if (r == SS_SUCCESS) {
                dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
                     drbd_conn_str(ns.conn),
                     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
                     (unsigned long) mdev->rs_total);
+               if (side == C_SYNC_TARGET)
+                       mdev->bm_resync_fo = 0;
+
+               /* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
+                * with w_send_oos, or the sync target will get confused as to
+                * how much bits to resync.  We cannot do that always, because for an
+                * empty resync and protocol < 95, we need to do it here, as we call
+                * drbd_resync_finished from here in that case.
+                * We drbd_gen_and_send_sync_uuid here for protocol < 96,
+                * and from after_state_ch otherwise. */
+               if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96)
+                       drbd_gen_and_send_sync_uuid(mdev);
 
                if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
                        /* This still has a race (about when exactly the peers
@@ -1547,13 +1580,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
                        drbd_resync_finished(mdev);
                }
 
-               atomic_set(&mdev->rs_sect_in, 0);
-               atomic_set(&mdev->rs_sect_ev, 0);
-               mdev->rs_in_flight = 0;
-               mdev->rs_planed = 0;
-               spin_lock(&mdev->peer_seq_lock);
-               fifo_set(&mdev->rs_plan_s, 0);
-               spin_unlock(&mdev->peer_seq_lock);
+               drbd_rs_controller_reset(mdev);
                /* ns.conn may already be != mdev->state.conn,
                 * we may have been paused in between, or become paused until
                 * the timer triggers.
@@ -1563,6 +1590,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 
                drbd_md_sync(mdev);
        }
+       put_ldev(mdev);
        drbd_state_unlock(mdev);
 }
 
index 53586fa5ae1b098686e6171ea821fa21dc1bdb1f..151f1a37478f954360cd4fe91767922acf9ec1e7 100644 (file)
@@ -39,7 +39,7 @@ static inline void drbd_generic_make_request(struct drbd_conf *mdev,
                return;
        }
 
-       if (FAULT_ACTIVE(mdev, fault_type))
+       if (drbd_insert_fault(mdev, fault_type))
                bio_endio(bio, -EIO);
        else
                generic_make_request(bio);
index 1f46f1cd9225c3c0d2a894bc80d3d1e74fe012e7..7beb0e25f1e1e2ca192ae563eb43f6dc0147f8f8 100644 (file)
@@ -980,7 +980,7 @@ int tpm_open(struct inode *inode, struct file *file)
                return -EBUSY;
        }
 
-       chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+       chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
        if (chip->data_buffer == NULL) {
                clear_bit(0, &chip->is_open);
                put_device(chip->dev);
index dd8ebc75b667ad0089a1152fe7dd416a8ad786f6..ab8a4eff072ae1d06559c8590b1f87641880cfb0 100644 (file)
@@ -94,9 +94,9 @@ static struct ipu_irq_map *src2map(unsigned int src)
        return NULL;
 }
 
-static void ipu_irq_unmask(unsigned int irq)
+static void ipu_irq_unmask(struct irq_data *d)
 {
-       struct ipu_irq_map *map = get_irq_chip_data(irq);
+       struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
        struct ipu_irq_bank *bank;
        uint32_t reg;
        unsigned long lock_flags;
@@ -106,7 +106,7 @@ static void ipu_irq_unmask(unsigned int irq)
        bank = map->bank;
        if (!bank) {
                spin_unlock_irqrestore(&bank_lock, lock_flags);
-               pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+               pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
                return;
        }
 
@@ -117,9 +117,9 @@ static void ipu_irq_unmask(unsigned int irq)
        spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
-static void ipu_irq_mask(unsigned int irq)
+static void ipu_irq_mask(struct irq_data *d)
 {
-       struct ipu_irq_map *map = get_irq_chip_data(irq);
+       struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
        struct ipu_irq_bank *bank;
        uint32_t reg;
        unsigned long lock_flags;
@@ -129,7 +129,7 @@ static void ipu_irq_mask(unsigned int irq)
        bank = map->bank;
        if (!bank) {
                spin_unlock_irqrestore(&bank_lock, lock_flags);
-               pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+               pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
                return;
        }
 
@@ -140,9 +140,9 @@ static void ipu_irq_mask(unsigned int irq)
        spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
-static void ipu_irq_ack(unsigned int irq)
+static void ipu_irq_ack(struct irq_data *d)
 {
-       struct ipu_irq_map *map = get_irq_chip_data(irq);
+       struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
        struct ipu_irq_bank *bank;
        unsigned long lock_flags;
 
@@ -151,7 +151,7 @@ static void ipu_irq_ack(unsigned int irq)
        bank = map->bank;
        if (!bank) {
                spin_unlock_irqrestore(&bank_lock, lock_flags);
-               pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+               pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
                return;
        }
 
@@ -167,7 +167,7 @@ static void ipu_irq_ack(unsigned int irq)
  */
 bool ipu_irq_status(unsigned int irq)
 {
-       struct ipu_irq_map *map = get_irq_chip_data(irq);
+       struct ipu_irq_map *map = irq_get_chip_data(irq);
        struct ipu_irq_bank *bank;
        unsigned long lock_flags;
        bool ret;
@@ -269,7 +269,7 @@ int ipu_irq_unmap(unsigned int source)
 /* Chained IRQ handler for IPU error interrupt */
 static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
 {
-       struct ipu *ipu = get_irq_data(irq);
+       struct ipu *ipu = irq_get_handler_data(irq);
        u32 status;
        int i, line;
 
@@ -310,7 +310,7 @@ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
 /* Chained IRQ handler for IPU function interrupt */
 static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
 {
-       struct ipu *ipu = get_irq_data(irq);
+       struct ipu *ipu = irq_desc_get_handler_data(desc);
        u32 status;
        int i, line;
 
@@ -345,10 +345,10 @@ static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
 }
 
 static struct irq_chip ipu_irq_chip = {
-       .name   = "ipu_irq",
-       .ack    = ipu_irq_ack,
-       .mask   = ipu_irq_mask,
-       .unmask = ipu_irq_unmask,
+       .name           = "ipu_irq",
+       .irq_ack        = ipu_irq_ack,
+       .irq_mask       = ipu_irq_mask,
+       .irq_unmask     = ipu_irq_unmask,
 };
 
 /* Install the IRQ handler */
@@ -366,26 +366,26 @@ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
                int ret;
 
                irq = irq_base + i;
-               ret = set_irq_chip(irq, &ipu_irq_chip);
+               ret = irq_set_chip(irq, &ipu_irq_chip);
                if (ret < 0)
                        return ret;
-               ret = set_irq_chip_data(irq, irq_map + i);
+               ret = irq_set_chip_data(irq, irq_map + i);
                if (ret < 0)
                        return ret;
                irq_map[i].ipu = ipu;
                irq_map[i].irq = irq;
                irq_map[i].source = -EINVAL;
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_handler(irq, handle_level_irq);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #endif
        }
 
-       set_irq_data(ipu->irq_fn, ipu);
-       set_irq_chained_handler(ipu->irq_fn, ipu_irq_fn);
+       irq_set_handler_data(ipu->irq_fn, ipu);
+       irq_set_chained_handler(ipu->irq_fn, ipu_irq_fn);
 
-       set_irq_data(ipu->irq_err, ipu);
-       set_irq_chained_handler(ipu->irq_err, ipu_irq_err);
+       irq_set_handler_data(ipu->irq_err, ipu);
+       irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
 
        return 0;
 }
@@ -397,17 +397,17 @@ void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
 
        irq_base = pdata->irq_base;
 
-       set_irq_chained_handler(ipu->irq_fn, NULL);
-       set_irq_data(ipu->irq_fn, NULL);
+       irq_set_chained_handler(ipu->irq_fn, NULL);
+       irq_set_handler_data(ipu->irq_fn, NULL);
 
-       set_irq_chained_handler(ipu->irq_err, NULL);
-       set_irq_data(ipu->irq_err, NULL);
+       irq_set_chained_handler(ipu->irq_err, NULL);
+       irq_set_handler_data(ipu->irq_err, NULL);
 
        for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) {
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
-               set_irq_chip(irq, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip(irq, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
index 0be30e978c859c46a3c576b92a49e750453b390f..31e71c4fc83171e7da846740533f63131189327b 100644 (file)
@@ -2679,7 +2679,7 @@ static int __init amd64_edac_init(void)
        mcis      = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
        ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
        if (!(mcis && ecc_stngs))
-               goto err_ret;
+               goto err_free;
 
        msrs = msrs_alloc();
        if (!msrs)
index d8d0cda2641da2a9c1f43a20cf14d248588b9f6a..d3b295305542a2b71e00f5cc97d7682557cef0c4 100644 (file)
@@ -414,4 +414,9 @@ config GPIO_JANZ_TTL
          This driver provides support for driving the pins in output
          mode only. Input mode is not supported.
 
+config AB8500_GPIO
+       bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
+       depends on AB8500_CORE && BROKEN
+       help
+         Select this to enable the AB8500 IC GPIO driver
 endif
index 3351cf87b0ed9fb720cd46c1210133cd4355b333..becef5954356bdc6b126a5c8a1bbb208f1e6ee1f 100644 (file)
@@ -42,3 +42,4 @@ obj-$(CONFIG_GPIO_JANZ_TTL)   += janz-ttl.o
 obj-$(CONFIG_GPIO_SX150X)      += sx150x.o
 obj-$(CONFIG_GPIO_VX855)       += vx855_gpio.o
 obj-$(CONFIG_GPIO_ML_IOH)      += ml_ioh_gpio.o
+obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
diff --git a/drivers/gpio/ab8500-gpio.c b/drivers/gpio/ab8500-gpio.c
new file mode 100644 (file)
index 0000000..e7b834d
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: BIBEK BASU <bibek.basu@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * 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/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/gpio.h>
+
+/*
+ * GPIO registers offset
+ * Bank: 0x10
+ */
+#define AB8500_GPIO_SEL1_REG   0x00
+#define AB8500_GPIO_SEL2_REG   0x01
+#define AB8500_GPIO_SEL3_REG   0x02
+#define AB8500_GPIO_SEL4_REG   0x03
+#define AB8500_GPIO_SEL5_REG   0x04
+#define AB8500_GPIO_SEL6_REG   0x05
+
+#define AB8500_GPIO_DIR1_REG   0x10
+#define AB8500_GPIO_DIR2_REG   0x11
+#define AB8500_GPIO_DIR3_REG   0x12
+#define AB8500_GPIO_DIR4_REG   0x13
+#define AB8500_GPIO_DIR5_REG   0x14
+#define AB8500_GPIO_DIR6_REG   0x15
+
+#define AB8500_GPIO_OUT1_REG   0x20
+#define AB8500_GPIO_OUT2_REG   0x21
+#define AB8500_GPIO_OUT3_REG   0x22
+#define AB8500_GPIO_OUT4_REG   0x23
+#define AB8500_GPIO_OUT5_REG   0x24
+#define AB8500_GPIO_OUT6_REG   0x25
+
+#define AB8500_GPIO_PUD1_REG   0x30
+#define AB8500_GPIO_PUD2_REG   0x31
+#define AB8500_GPIO_PUD3_REG   0x32
+#define AB8500_GPIO_PUD4_REG   0x33
+#define AB8500_GPIO_PUD5_REG   0x34
+#define AB8500_GPIO_PUD6_REG   0x35
+
+#define AB8500_GPIO_IN1_REG    0x40
+#define AB8500_GPIO_IN2_REG    0x41
+#define AB8500_GPIO_IN3_REG    0x42
+#define AB8500_GPIO_IN4_REG    0x43
+#define AB8500_GPIO_IN5_REG    0x44
+#define AB8500_GPIO_IN6_REG    0x45
+#define AB8500_GPIO_ALTFUN_REG 0x45
+#define ALTFUN_REG_INDEX       6
+#define AB8500_NUM_GPIO                42
+#define AB8500_NUM_VIR_GPIO_IRQ        16
+
+enum ab8500_gpio_action {
+       NONE,
+       STARTUP,
+       SHUTDOWN,
+       MASK,
+       UNMASK
+};
+
+struct ab8500_gpio {
+       struct gpio_chip chip;
+       struct ab8500 *parent;
+       struct device *dev;
+       struct mutex lock;
+       u32 irq_base;
+       enum ab8500_gpio_action irq_action;
+       u16 rising;
+       u16 falling;
+};
+/**
+ * to_ab8500_gpio() - get the pointer to ab8500_gpio
+ * @chip:      Member of the structure ab8500_gpio
+ */
+static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct ab8500_gpio, chip);
+}
+
+static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
+                                       unsigned offset, int val)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       u8 pos = offset % 8;
+       int ret;
+
+       reg = reg + (offset / 8);
+       ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
+                               AB8500_MISC, reg, 1 << pos, val << pos);
+       if (ret < 0)
+               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+       return ret;
+}
+/**
+ * ab8500_gpio_get() - Get the particular GPIO value
+ * @chip: Gpio device
+ * @offset: GPIO number to read
+ */
+static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       u8 mask = 1 << (offset % 8);
+       u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
+       int ret;
+       u8 data;
+       ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+                                               reg, &data);
+       if (ret < 0) {
+               dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
+               return ret;
+       }
+       return (data & mask) >> (offset % 8);
+}
+
+static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       int ret;
+       /* Write the data */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
+       if (ret < 0)
+               dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+}
+
+static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int val)
+{
+       int ret;
+       /* set direction as output */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
+       if (ret < 0)
+               return ret;
+       /* disable pull down */
+       ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
+       if (ret < 0)
+               return ret;
+       /* set the output as 1 or 0 */
+       return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+
+}
+
+static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       /* set the register as input */
+       return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
+}
+
+static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       /*
+        * Only some GPIOs are interrupt capable, and they are
+        * organized in discontiguous clusters:
+        *
+        *      GPIO6 to GPIO13
+        *      GPIO24 and GPIO25
+        *      GPIO36 to GPIO41
+        */
+       static struct ab8500_gpio_irq_cluster {
+               int start;
+               int end;
+       } clusters[] = {
+               {.start = 6,  .end = 13},
+               {.start = 24, .end = 25},
+               {.start = 36, .end = 41},
+       };
+       struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+       int base = ab8500_gpio->irq_base;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(clusters); i++) {
+               struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
+
+               if (offset >= cluster->start && offset <= cluster->end)
+                       return base + offset - cluster->start;
+
+               /* Advance by the number of gpios in this cluster */
+               base += cluster->end - cluster->start + 1;
+       }
+
+       return -EINVAL;
+}
+
+static struct gpio_chip ab8500gpio_chip = {
+       .label                  = "ab8500_gpio",
+       .owner                  = THIS_MODULE,
+       .direction_input        = ab8500_gpio_direction_input,
+       .get                    = ab8500_gpio_get,
+       .direction_output       = ab8500_gpio_direction_output,
+       .set                    = ab8500_gpio_set,
+       .to_irq                 = ab8500_gpio_to_irq,
+};
+
+static unsigned int irq_to_rising(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       int new_irq = offset +  AB8500_INT_GPIO6R
+                       + ab8500_gpio->parent->irq_base;
+       return new_irq;
+}
+
+static unsigned int irq_to_falling(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       int new_irq = offset +  AB8500_INT_GPIO6F
+                       +  ab8500_gpio->parent->irq_base;
+       return new_irq;
+
+}
+
+static unsigned int rising_to_irq(unsigned int irq, void *dev)
+{
+       struct ab8500_gpio *ab8500_gpio = dev;
+       int offset = irq - AB8500_INT_GPIO6R
+                       - ab8500_gpio->parent->irq_base ;
+       int new_irq = offset + ab8500_gpio->irq_base;
+       return new_irq;
+}
+
+static unsigned int falling_to_irq(unsigned int irq, void *dev)
+{
+       struct ab8500_gpio *ab8500_gpio = dev;
+       int offset = irq - AB8500_INT_GPIO6F
+                       - ab8500_gpio->parent->irq_base ;
+       int new_irq = offset + ab8500_gpio->irq_base;
+       return new_irq;
+
+}
+
+/*
+ * IRQ handler
+ */
+
+static irqreturn_t handle_rising(int irq, void *dev)
+{
+
+       handle_nested_irq(rising_to_irq(irq , dev));
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_falling(int irq, void *dev)
+{
+
+       handle_nested_irq(falling_to_irq(irq, dev));
+       return IRQ_HANDLED;
+}
+
+static void ab8500_gpio_irq_lock(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       mutex_lock(&ab8500_gpio->lock);
+}
+
+static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+       bool rising = ab8500_gpio->rising & BIT(offset);
+       bool falling = ab8500_gpio->falling & BIT(offset);
+       int ret;
+
+       switch (ab8500_gpio->irq_action)        {
+       case STARTUP:
+               if (rising)
+                       ret = request_threaded_irq(irq_to_rising(irq),
+                                       NULL, handle_rising,
+                                       IRQF_TRIGGER_RISING,
+                                       "ab8500-gpio-r", ab8500_gpio);
+               if (falling)
+                       ret = request_threaded_irq(irq_to_falling(irq),
+                                      NULL, handle_falling,
+                                      IRQF_TRIGGER_FALLING,
+                                      "ab8500-gpio-f", ab8500_gpio);
+               break;
+       case SHUTDOWN:
+               if (rising)
+                       free_irq(irq_to_rising(irq), ab8500_gpio);
+               if (falling)
+                       free_irq(irq_to_falling(irq), ab8500_gpio);
+               break;
+       case MASK:
+               if (rising)
+                       disable_irq(irq_to_rising(irq));
+               if (falling)
+                       disable_irq(irq_to_falling(irq));
+               break;
+       case UNMASK:
+               if (rising)
+                       enable_irq(irq_to_rising(irq));
+               if (falling)
+                       enable_irq(irq_to_falling(irq));
+               break;
+       case NONE:
+               break;
+       }
+       ab8500_gpio->irq_action = NONE;
+       ab8500_gpio->rising &= ~(BIT(offset));
+       ab8500_gpio->falling &= ~(BIT(offset));
+       mutex_unlock(&ab8500_gpio->lock);
+}
+
+
+static void ab8500_gpio_irq_mask(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = MASK;
+}
+
+static void ab8500_gpio_irq_unmask(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = UNMASK;
+}
+
+static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       int offset = irq - ab8500_gpio->irq_base;
+
+       if (type == IRQ_TYPE_EDGE_BOTH) {
+               ab8500_gpio->rising =  BIT(offset);
+               ab8500_gpio->falling = BIT(offset);
+       } else if (type == IRQ_TYPE_EDGE_RISING) {
+               ab8500_gpio->rising =  BIT(offset);
+       } else  {
+               ab8500_gpio->falling = BIT(offset);
+       }
+       return 0;
+}
+
+unsigned int ab8500_gpio_irq_startup(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = STARTUP;
+       return 0;
+}
+
+void ab8500_gpio_irq_shutdown(unsigned int irq)
+{
+       struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+       ab8500_gpio->irq_action = SHUTDOWN;
+}
+
+static struct irq_chip ab8500_gpio_irq_chip = {
+       .name                   = "ab8500-gpio",
+       .startup                = ab8500_gpio_irq_startup,
+       .shutdown               = ab8500_gpio_irq_shutdown,
+       .bus_lock               = ab8500_gpio_irq_lock,
+       .bus_sync_unlock        = ab8500_gpio_irq_sync_unlock,
+       .mask                   = ab8500_gpio_irq_mask,
+       .unmask                 = ab8500_gpio_irq_unmask,
+       .set_type               = ab8500_gpio_irq_set_type,
+};
+
+static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
+{
+       u32 base = ab8500_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
+               set_irq_chip_data(irq, ab8500_gpio);
+               set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
+                               handle_simple_irq);
+               set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               set_irq_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
+{
+       int base = ab8500_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               set_irq_chip_and_handler(irq, NULL, NULL);
+               set_irq_chip_data(irq, NULL);
+       }
+}
+
+static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+{
+       struct ab8500_platform_data *ab8500_pdata =
+                               dev_get_platdata(pdev->dev.parent);
+       struct ab8500_gpio_platform_data *pdata;
+       struct ab8500_gpio *ab8500_gpio;
+       int ret;
+       int i;
+
+       pdata = ab8500_pdata->gpio;
+       if (!pdata)     {
+               dev_err(&pdev->dev, "gpio platform data missing\n");
+               return -ENODEV;
+       }
+
+       ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
+       if (ab8500_gpio == NULL) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+       ab8500_gpio->dev = &pdev->dev;
+       ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
+       ab8500_gpio->chip = ab8500gpio_chip;
+       ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
+       ab8500_gpio->chip.dev = &pdev->dev;
+       ab8500_gpio->chip.base = pdata->gpio_base;
+       ab8500_gpio->irq_base = pdata->irq_base;
+       /* initialize the lock */
+       mutex_init(&ab8500_gpio->lock);
+       /*
+        * AB8500 core will handle and clear the IRQ
+        * configre GPIO based on config-reg value.
+        * These values are for selecting the PINs as
+        * GPIO or alternate function
+        */
+       for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)  {
+               ret = abx500_set_register_interruptible(ab8500_gpio->dev,
+                               AB8500_MISC, i,
+                               pdata->config_reg[i]);
+               if (ret < 0)
+                       goto out_free;
+       }
+       ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+                               AB8500_GPIO_ALTFUN_REG,
+                               pdata->config_reg[ALTFUN_REG_INDEX]);
+       if (ret < 0)
+               goto out_free;
+
+       ret = ab8500_gpio_irq_init(ab8500_gpio);
+       if (ret)
+               goto out_free;
+       ret = gpiochip_add(&ab8500_gpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
+                               ret);
+               goto out_rem_irq;
+       }
+       platform_set_drvdata(pdev, ab8500_gpio);
+       return 0;
+
+out_rem_irq:
+       ab8500_gpio_irq_remove(ab8500_gpio);
+out_free:
+       mutex_destroy(&ab8500_gpio->lock);
+       kfree(ab8500_gpio);
+       return ret;
+}
+
+/*
+ * ab8500_gpio_remove() - remove Ab8500-gpio driver
+ * @pdev :     Platform device registered
+ */
+static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+{
+       struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&ab8500_gpio->chip);
+       if (ret < 0) {
+               dev_err(ab8500_gpio->dev, "unable to remove gpiochip:\
+                               %d\n", ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, NULL);
+       mutex_destroy(&ab8500_gpio->lock);
+       kfree(ab8500_gpio);
+
+       return 0;
+}
+
+static struct platform_driver ab8500_gpio_driver = {
+       .driver = {
+               .name = "ab8500-gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe = ab8500_gpio_probe,
+       .remove = __devexit_p(ab8500_gpio_remove),
+};
+
+static int __init ab8500_gpio_init(void)
+{
+       return platform_driver_register(&ab8500_gpio_driver);
+}
+arch_initcall(ab8500_gpio_init);
+
+static void __exit ab8500_gpio_exit(void)
+{
+       platform_driver_unregister(&ab8500_gpio_driver);
+}
+module_exit(ab8500_gpio_exit);
+
+MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
+MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins\
+                       to be used as GPIO");
+MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_LICENSE("GPL v2");
index 81131eda5544a6715a0d71e4e8902537a951b4fa..060ef63278763f2a96da76365f6a2a617f84f191 100644 (file)
@@ -315,11 +315,22 @@ config SENSORS_F71805F
          will be called f71805f.
 
 config SENSORS_F71882FG
-       tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
+       tristate "Fintek F71882FG and compatibles"
        help
          If you say yes here you get support for hardware monitoring
-         features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
-         F71889FG and F8000 Super-I/O chips.
+         features of many Fintek Super-I/O (LPC) chips. The currently
+         supported chips are:
+           F71808E
+           F71858FG
+           F71862FG
+           F71863FG
+           F71869F/E
+           F71882FG
+           F71883FG
+           F71889FG/ED/A
+           F8000
+           F81801U
+           F81865F
 
          This driver can also be built as a module.  If so, the module
          will be called f71882fg.
index a4d430ee7e20e8696f75700664f572f211ffe5b3..ca07a32447c23406ef8e39523eb1830d42d56286 100644 (file)
@@ -54,7 +54,9 @@
 #define SIO_F71882_ID          0x0541  /* Chipset ID */
 #define SIO_F71889_ID          0x0723  /* Chipset ID */
 #define SIO_F71889E_ID         0x0909  /* Chipset ID */
+#define SIO_F71889A_ID         0x1005  /* Chipset ID */
 #define SIO_F8000_ID           0x0581  /* Chipset ID */
+#define SIO_F81865_ID          0x0704  /* Chipset ID */
 
 #define REGION_LENGTH          8
 #define ADDR_REG_OFFSET                5
@@ -106,7 +108,7 @@ module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
 enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
-            f71889ed, f8000 };
+            f71889ed, f71889a, f8000, f81865f };
 
 static const char *f71882fg_names[] = {
        "f71808e",
@@ -114,42 +116,76 @@ static const char *f71882fg_names[] = {
        "f71862fg",
        "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
        "f71882fg",
-       "f71889fg",
+       "f71889fg", /* f81801u too, same id */
        "f71889ed",
+       "f71889a",
        "f8000",
+       "f81865f",
 };
 
-static const char f71882fg_has_in[8][F71882FG_MAX_INS] = {
-       { 1, 1, 1, 1, 1, 1, 0, 1, 1 }, /* f71808e */
-       { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f71858fg */
-       { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71862fg */
-       { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71869 */
-       { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71882fg */
-       { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889fg */
-       { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889ed */
-       { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f8000 */
+static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
+       [f71808e]       = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
+       [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
+       [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71889a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f8000]         = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
+       [f81865f]       = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
 };
 
-static const char f71882fg_has_in1_alarm[8] = {
-       0, /* f71808e */
-       0, /* f71858fg */
-       0, /* f71862fg */
-       0, /* f71869 */
-       1, /* f71882fg */
-       1, /* f71889fg */
-       1, /* f71889ed */
-       0, /* f8000 */
+static const char f71882fg_has_in1_alarm[] = {
+       [f71808e]       = 0,
+       [f71858fg]      = 0,
+       [f71862fg]      = 0,
+       [f71869]        = 0,
+       [f71882fg]      = 1,
+       [f71889fg]      = 1,
+       [f71889ed]      = 1,
+       [f71889a]       = 1,
+       [f8000]         = 0,
+       [f81865f]       = 1,
 };
 
-static const char f71882fg_has_beep[8] = {
-       0, /* f71808e */
-       0, /* f71858fg */
-       1, /* f71862fg */
-       1, /* f71869 */
-       1, /* f71882fg */
-       1, /* f71889fg */
-       1, /* f71889ed */
-       0, /* f8000 */
+static const char f71882fg_has_beep[] = {
+       [f71808e]       = 0,
+       [f71858fg]      = 0,
+       [f71862fg]      = 1,
+       [f71869]        = 1,
+       [f71882fg]      = 1,
+       [f71889fg]      = 1,
+       [f71889ed]      = 1,
+       [f71889a]       = 1,
+       [f8000]         = 0,
+       [f81865f]       = 1,
+};
+
+static const char f71882fg_nr_fans[] = {
+       [f71808e]       = 3,
+       [f71858fg]      = 3,
+       [f71862fg]      = 3,
+       [f71869]        = 3,
+       [f71882fg]      = 4,
+       [f71889fg]      = 3,
+       [f71889ed]      = 3,
+       [f71889a]       = 3,
+       [f8000]         = 3,
+       [f81865f]       = 2,
+};
+
+static const char f71882fg_nr_temps[] = {
+       [f71808e]       = 2,
+       [f71858fg]      = 3,
+       [f71862fg]      = 3,
+       [f71869]        = 3,
+       [f71882fg]      = 3,
+       [f71889fg]      = 3,
+       [f71889ed]      = 3,
+       [f71889a]       = 3,
+       [f8000]         = 3,
+       [f81865f]       = 2,
 };
 
 static struct platform_device *f71882fg_pdev;
@@ -1071,9 +1107,9 @@ static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
 static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 {
        struct f71882fg_data *data = dev_get_drvdata(dev);
+       int nr_fans = f71882fg_nr_fans[data->type];
+       int nr_temps = f71882fg_nr_temps[data->type];
        int nr, reg, point;
-       int nr_fans = (data->type == f71882fg) ? 4 : 3;
-       int nr_temps = (data->type == f71808e) ? 2 : 3;
 
        mutex_lock(&data->update_lock);
 
@@ -2042,8 +2078,9 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 {
        struct f71882fg_data *data;
        struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
-       int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
-       int nr_temps = (sio_data->type == f71808e) ? 2 : 3;
+       int nr_fans = f71882fg_nr_fans[sio_data->type];
+       int nr_temps = f71882fg_nr_temps[sio_data->type];
+       int err, i;
        u8 start_reg, reg;
 
        data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
@@ -2138,6 +2175,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                        /* Fall through to select correct fan/pwm reg bank! */
                case f71889fg:
                case f71889ed:
+               case f71889a:
                        reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
                        if (reg & F71882FG_FAN_NEG_TEMP_EN)
                                data->auto_point_temp_signed = 1;
@@ -2163,16 +2201,12 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                case f71862fg:
                        err = (data->pwm_enable & 0x15) != 0x15;
                        break;
-               case f71808e:
-               case f71869:
-               case f71882fg:
-               case f71889fg:
-               case f71889ed:
-                       err = 0;
-                       break;
                case f8000:
                        err = data->pwm_enable & 0x20;
                        break;
+               default:
+                       err = 0;
+                       break;
                }
                if (err) {
                        dev_err(&pdev->dev,
@@ -2199,6 +2233,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                case f71869:
                case f71889fg:
                case f71889ed:
+               case f71889a:
                        for (i = 0; i < nr_fans; i++) {
                                data->pwm_auto_point_mapping[i] =
                                        f71882fg_read8(data,
@@ -2276,8 +2311,9 @@ exit_free:
 static int f71882fg_remove(struct platform_device *pdev)
 {
        struct f71882fg_data *data = platform_get_drvdata(pdev);
-       int i, nr_fans = (data->type == f71882fg) ? 4 : 3;
-       int nr_temps = (data->type == f71808e) ? 2 : 3;
+       int nr_fans = f71882fg_nr_fans[data->type];
+       int nr_temps = f71882fg_nr_temps[data->type];
+       int i;
        u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
 
        if (data->hwmon_dev)
@@ -2406,9 +2442,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
        case SIO_F71889E_ID:
                sio_data->type = f71889ed;
                break;
+       case SIO_F71889A_ID:
+               sio_data->type = f71889a;
+               break;
        case SIO_F8000_ID:
                sio_data->type = f8000;
                break;
+       case SIO_F81865_ID:
+               sio_data->type = f81865f;
+               break;
        default:
                pr_info("Unsupported Fintek device: %04x\n",
                        (unsigned int)devid);
index f141a1de519cb2af822deef686229734c6d94249..89aa9fb743af07260c8deadbc8956eb4c1ada2de 100644 (file)
@@ -116,7 +116,7 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data,
                return 0;
 
        INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
-       set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
        err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
                          "GPIO fan alarm", fan_data);
        if (err)
index 6474512f49b08c13cd5ec92a3f686b3fdaa2224c..edfb92e41735df7f713a2283a12a299e764423ca 100644 (file)
@@ -752,7 +752,7 @@ static void pmbus_add_boolean_cmp(struct pmbus_data *data,
 static void pmbus_add_sensor(struct pmbus_data *data,
                             const char *name, const char *type, int seq,
                             int page, int reg, enum pmbus_sensor_classes class,
-                            bool update)
+                            bool update, bool readonly)
 {
        struct pmbus_sensor *sensor;
 
@@ -765,7 +765,7 @@ static void pmbus_add_sensor(struct pmbus_data *data,
        sensor->reg = reg;
        sensor->class = class;
        sensor->update = update;
-       if (update)
+       if (readonly)
                PMBUS_ADD_GET_ATTR(data, sensor->name, sensor,
                                   data->num_sensors);
        else
@@ -916,14 +916,14 @@ static void pmbus_find_attributes(struct i2c_client *client,
 
                i0 = data->num_sensors;
                pmbus_add_label(data, "in", in_index, "vin", 0);
-               pmbus_add_sensor(data, "in", "input", in_index,
-                                0, PMBUS_READ_VIN, PSC_VOLTAGE_IN, true);
+               pmbus_add_sensor(data, "in", "input", in_index, 0,
+                                PMBUS_READ_VIN, PSC_VOLTAGE_IN, true, true);
                if (pmbus_check_word_register(client, 0,
                                              PMBUS_VIN_UV_WARN_LIMIT)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "min", in_index,
                                         0, PMBUS_VIN_UV_WARN_LIMIT,
-                                        PSC_VOLTAGE_IN, false);
+                                        PSC_VOLTAGE_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
                                pmbus_add_boolean_reg(data, "in", "min_alarm",
                                                      in_index,
@@ -937,7 +937,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "lcrit", in_index,
                                         0, PMBUS_VIN_UV_FAULT_LIMIT,
-                                        PSC_VOLTAGE_IN, false);
+                                        PSC_VOLTAGE_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
                                pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
                                                      in_index,
@@ -951,7 +951,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "max", in_index,
                                         0, PMBUS_VIN_OV_WARN_LIMIT,
-                                        PSC_VOLTAGE_IN, false);
+                                        PSC_VOLTAGE_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
                                pmbus_add_boolean_reg(data, "in", "max_alarm",
                                                      in_index,
@@ -965,7 +965,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "crit", in_index,
                                         0, PMBUS_VIN_OV_FAULT_LIMIT,
-                                        PSC_VOLTAGE_IN, false);
+                                        PSC_VOLTAGE_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
                                pmbus_add_boolean_reg(data, "in", "crit_alarm",
                                                      in_index,
@@ -988,7 +988,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
        if (info->func[0] & PMBUS_HAVE_VCAP) {
                pmbus_add_label(data, "in", in_index, "vcap", 0);
                pmbus_add_sensor(data, "in", "input", in_index, 0,
-                                PMBUS_READ_VCAP, PSC_VOLTAGE_IN, true);
+                                PMBUS_READ_VCAP, PSC_VOLTAGE_IN, true, true);
                in_index++;
        }
 
@@ -1004,13 +1004,13 @@ static void pmbus_find_attributes(struct i2c_client *client,
                i0 = data->num_sensors;
                pmbus_add_label(data, "in", in_index, "vout", page + 1);
                pmbus_add_sensor(data, "in", "input", in_index, page,
-                                PMBUS_READ_VOUT, PSC_VOLTAGE_OUT, true);
+                                PMBUS_READ_VOUT, PSC_VOLTAGE_OUT, true, true);
                if (pmbus_check_word_register(client, page,
                                              PMBUS_VOUT_UV_WARN_LIMIT)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "min", in_index, page,
                                         PMBUS_VOUT_UV_WARN_LIMIT,
-                                        PSC_VOLTAGE_OUT, false);
+                                        PSC_VOLTAGE_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
                                pmbus_add_boolean_reg(data, "in", "min_alarm",
                                                      in_index,
@@ -1025,7 +1025,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "lcrit", in_index, page,
                                         PMBUS_VOUT_UV_FAULT_LIMIT,
-                                        PSC_VOLTAGE_OUT, false);
+                                        PSC_VOLTAGE_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
                                pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
                                                      in_index,
@@ -1040,7 +1040,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "max", in_index, page,
                                         PMBUS_VOUT_OV_WARN_LIMIT,
-                                        PSC_VOLTAGE_OUT, false);
+                                        PSC_VOLTAGE_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
                                pmbus_add_boolean_reg(data, "in", "max_alarm",
                                                      in_index,
@@ -1055,7 +1055,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "in", "crit", in_index, page,
                                         PMBUS_VOUT_OV_FAULT_LIMIT,
-                                        PSC_VOLTAGE_OUT, false);
+                                        PSC_VOLTAGE_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
                                pmbus_add_boolean_reg(data, "in", "crit_alarm",
                                                      in_index,
@@ -1088,14 +1088,14 @@ static void pmbus_find_attributes(struct i2c_client *client,
        if (info->func[0] & PMBUS_HAVE_IIN) {
                i0 = data->num_sensors;
                pmbus_add_label(data, "curr", in_index, "iin", 0);
-               pmbus_add_sensor(data, "curr", "input", in_index,
-                                0, PMBUS_READ_IIN, PSC_CURRENT_IN, true);
+               pmbus_add_sensor(data, "curr", "input", in_index, 0,
+                                PMBUS_READ_IIN, PSC_CURRENT_IN, true, true);
                if (pmbus_check_word_register(client, 0,
                                              PMBUS_IIN_OC_WARN_LIMIT)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "curr", "max", in_index,
                                         0, PMBUS_IIN_OC_WARN_LIMIT,
-                                        PSC_CURRENT_IN, false);
+                                        PSC_CURRENT_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
                                pmbus_add_boolean_reg(data, "curr", "max_alarm",
                                                      in_index,
@@ -1108,7 +1108,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "curr", "crit", in_index,
                                         0, PMBUS_IIN_OC_FAULT_LIMIT,
-                                        PSC_CURRENT_IN, false);
+                                        PSC_CURRENT_IN, false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
                                pmbus_add_boolean_reg(data, "curr",
                                                      "crit_alarm",
@@ -1131,13 +1131,13 @@ static void pmbus_find_attributes(struct i2c_client *client,
                i0 = data->num_sensors;
                pmbus_add_label(data, "curr", in_index, "iout", page + 1);
                pmbus_add_sensor(data, "curr", "input", in_index, page,
-                                PMBUS_READ_IOUT, PSC_CURRENT_OUT, true);
+                                PMBUS_READ_IOUT, PSC_CURRENT_OUT, true, true);
                if (pmbus_check_word_register(client, page,
                                              PMBUS_IOUT_OC_WARN_LIMIT)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "curr", "max", in_index, page,
                                         PMBUS_IOUT_OC_WARN_LIMIT,
-                                        PSC_CURRENT_OUT, false);
+                                        PSC_CURRENT_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
                                pmbus_add_boolean_reg(data, "curr", "max_alarm",
                                                      in_index,
@@ -1151,7 +1151,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "curr", "lcrit", in_index, page,
                                         PMBUS_IOUT_UC_FAULT_LIMIT,
-                                        PSC_CURRENT_OUT, false);
+                                        PSC_CURRENT_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
                                pmbus_add_boolean_reg(data, "curr",
                                                      "lcrit_alarm",
@@ -1166,7 +1166,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "curr", "crit", in_index, page,
                                         PMBUS_IOUT_OC_FAULT_LIMIT,
-                                        PSC_CURRENT_OUT, false);
+                                        PSC_CURRENT_OUT, false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
                                pmbus_add_boolean_reg(data, "curr",
                                                      "crit_alarm",
@@ -1199,13 +1199,13 @@ static void pmbus_find_attributes(struct i2c_client *client,
                i0 = data->num_sensors;
                pmbus_add_label(data, "power", in_index, "pin", 0);
                pmbus_add_sensor(data, "power", "input", in_index,
-                                0, PMBUS_READ_PIN, PSC_POWER, true);
+                                0, PMBUS_READ_PIN, PSC_POWER, true, true);
                if (pmbus_check_word_register(client, 0,
                                              PMBUS_PIN_OP_WARN_LIMIT)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "power", "max", in_index,
                                         0, PMBUS_PIN_OP_WARN_LIMIT, PSC_POWER,
-                                        false);
+                                        false, false);
                        if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
                                pmbus_add_boolean_reg(data, "power",
                                                      "alarm",
@@ -1228,7 +1228,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                i0 = data->num_sensors;
                pmbus_add_label(data, "power", in_index, "pout", page + 1);
                pmbus_add_sensor(data, "power", "input", in_index, page,
-                                PMBUS_READ_POUT, PSC_POWER, true);
+                                PMBUS_READ_POUT, PSC_POWER, true, true);
                /*
                 * Per hwmon sysfs API, power_cap is to be used to limit output
                 * power.
@@ -1241,7 +1241,8 @@ static void pmbus_find_attributes(struct i2c_client *client,
                if (pmbus_check_word_register(client, page, PMBUS_POUT_MAX)) {
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "power", "cap", in_index, page,
-                                        PMBUS_POUT_MAX, PSC_POWER, false);
+                                        PMBUS_POUT_MAX, PSC_POWER,
+                                        false, false);
                        need_alarm = true;
                }
                if (pmbus_check_word_register(client, page,
@@ -1249,7 +1250,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "power", "max", in_index, page,
                                         PMBUS_POUT_OP_WARN_LIMIT, PSC_POWER,
-                                        false);
+                                        false, false);
                        need_alarm = true;
                }
                if (need_alarm && (info->func[page] & PMBUS_HAVE_STATUS_IOUT))
@@ -1264,7 +1265,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i1 = data->num_sensors;
                        pmbus_add_sensor(data, "power", "crit", in_index, page,
                                         PMBUS_POUT_OP_FAULT_LIMIT, PSC_POWER,
-                                        false);
+                                        false, false);
                        if (info->func[page] & PMBUS_HAVE_STATUS_IOUT)
                                pmbus_add_boolean_reg(data, "power",
                                                      "crit_alarm",
@@ -1302,7 +1303,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                        i0 = data->num_sensors;
                        pmbus_add_sensor(data, "temp", "input", in_index, page,
                                         pmbus_temp_registers[t],
-                                        PSC_TEMPERATURE, true);
+                                        PSC_TEMPERATURE, true, true);
 
                        /*
                         * PMBus provides only one status register for TEMP1-3.
@@ -1323,7 +1324,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                                i1 = data->num_sensors;
                                pmbus_add_sensor(data, "temp", "min", in_index,
                                                 page, PMBUS_UT_WARN_LIMIT,
-                                                PSC_TEMPERATURE, true);
+                                                PSC_TEMPERATURE, true, false);
                                if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
                                        pmbus_add_boolean_cmp(data, "temp",
                                                "min_alarm", in_index, i1, i0,
@@ -1338,7 +1339,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                                pmbus_add_sensor(data, "temp", "lcrit",
                                                 in_index, page,
                                                 PMBUS_UT_FAULT_LIMIT,
-                                                PSC_TEMPERATURE, true);
+                                                PSC_TEMPERATURE, true, false);
                                if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
                                        pmbus_add_boolean_cmp(data, "temp",
                                                "lcrit_alarm", in_index, i1, i0,
@@ -1352,7 +1353,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                                i1 = data->num_sensors;
                                pmbus_add_sensor(data, "temp", "max", in_index,
                                                 page, PMBUS_OT_WARN_LIMIT,
-                                                PSC_TEMPERATURE, true);
+                                                PSC_TEMPERATURE, true, false);
                                if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
                                        pmbus_add_boolean_cmp(data, "temp",
                                                "max_alarm", in_index, i0, i1,
@@ -1366,7 +1367,7 @@ static void pmbus_find_attributes(struct i2c_client *client,
                                i1 = data->num_sensors;
                                pmbus_add_sensor(data, "temp", "crit", in_index,
                                                 page, PMBUS_OT_FAULT_LIMIT,
-                                                PSC_TEMPERATURE, true);
+                                                PSC_TEMPERATURE, true, false);
                                if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
                                        pmbus_add_boolean_cmp(data, "temp",
                                                "crit_alarm", in_index, i0, i1,
@@ -1421,7 +1422,8 @@ static void pmbus_find_attributes(struct i2c_client *client,
 
                        i0 = data->num_sensors;
                        pmbus_add_sensor(data, "fan", "input", in_index, page,
-                                        pmbus_fan_registers[f], PSC_FAN, true);
+                                        pmbus_fan_registers[f], PSC_FAN, true,
+                                        true);
 
                        /*
                         * Each fan status register covers multiple fans,
index eb4af28f8567db62d2c53ddd1ca4a7d958fb3010..1f29bab6b3e5a274d8cf02e0d3e4225ba8cc4a74 100644 (file)
@@ -4,6 +4,7 @@
 
 config HWSPINLOCK
        tristate "Generic Hardware Spinlock framework"
+       depends on ARCH_OMAP4
        help
          Say y here to support the generic hardware spinlock framework.
          You only need to enable this if you have hardware spinlock module
index f4077840d3abdbc027585617b8379304865dae81..0e406d73b2c8226da821bd3b2b7fb480354ed2cc 100644 (file)
@@ -440,6 +440,7 @@ void do_ide_request(struct request_queue *q)
        struct ide_host *host = hwif->host;
        struct request  *rq = NULL;
        ide_startstop_t startstop;
+       unsigned long queue_run_ms = 3; /* old plug delay */
 
        spin_unlock_irq(q->queue_lock);
 
@@ -459,6 +460,9 @@ repeat:
                prev_port = hwif->host->cur_port;
                if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
                    time_after(drive->sleep, jiffies)) {
+                       unsigned long left = jiffies - drive->sleep;
+
+                       queue_run_ms = jiffies_to_msecs(left + 1);
                        ide_unlock_port(hwif);
                        goto plug_device;
                }
@@ -547,8 +551,10 @@ plug_device:
 plug_device_2:
        spin_lock_irq(q->queue_lock);
 
-       if (rq)
+       if (rq) {
                blk_requeue_request(q, rq);
+               blk_delay_queue(q, queue_run_ms);
+       }
 }
 
 void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
@@ -562,6 +568,10 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
                blk_requeue_request(q, rq);
 
        spin_unlock_irqrestore(q->queue_lock, flags);
+
+       /* Use 3ms as that was the old plug delay */
+       if (rq)
+               blk_delay_queue(q, 3);
 }
 
 static int drive_is_ready(ide_drive_t *drive)
index b732870ecc897a1465ad8645342b9ce60435beba..71f744a8e686232bd85156e4bc8b0f04fe3980ee 100644 (file)
@@ -809,7 +809,7 @@ static int lm8323_suspend(struct device *dev)
        struct lm8323_chip *lm = i2c_get_clientdata(client);
        int i;
 
-       set_irq_wake(client->irq, 0);
+       irq_set_irq_wake(client->irq, 0);
        disable_irq(client->irq);
 
        mutex_lock(&lm->lock);
@@ -838,7 +838,7 @@ static int lm8323_resume(struct device *dev)
                        led_classdev_resume(&lm->pwm[i].cdev);
 
        enable_irq(client->irq);
-       set_irq_wake(client->irq, 1);
+       irq_set_irq_wake(client->irq, 1);
 
        return 0;
 }
index ebe9553256777aeb156e12247e1fa5ad91b9b8b9..4b2a42f9f0bb471748ee3d6676da48255fd73231 100644 (file)
@@ -149,7 +149,7 @@ static int __init ams_delta_serio_init(void)
         * at FIQ level, switch back from edge to simple interrupt handler
         * to avoid bad interaction.
         */
-       set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
+       irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
                        handle_simple_irq);
 
        serio_register_port(ams_delta_serio);
index b6b8b1c7eceaf99b6eec1d613f3511c4a4a65550..3242e7076258ebed157c3a3219fb559dee9b34dd 100644 (file)
@@ -219,7 +219,7 @@ static int wm97xx_acc_startup(struct wm97xx *wm)
                }
 
                wm->pen_irq = gpio_to_irq(irq);
-               set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
+               irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
        } else /* pen irq not supported */
                pen_int = 0;
 
index 0488498676436938a7336fcb7eb1b8fa34bbc6fe..5b0f15ec874a9d97798d686b8a3bac3ac00be9f6 100644 (file)
@@ -193,7 +193,7 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev)
                gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26);
 
        wm->pen_irq = IRQ_GPIO(gpio_touch_irq);
-       set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
 
        wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
                           WM97XX_GPIO_POL_HIGH,
index 06ecea751a39b8ec53935bcdfb331453d2e01b19..8b66e04c2ea6a833930ffbe57608911e16a494b2 100644 (file)
@@ -1777,12 +1777,6 @@ int md_integrity_register(mddev_t *mddev)
                        continue;
                if (rdev->raid_disk < 0)
                        continue;
-               /*
-                * If at least one rdev is not integrity capable, we can not
-                * enable data integrity for the md device.
-                */
-               if (!bdev_get_integrity(rdev->bdev))
-                       return -EINVAL;
                if (!reference) {
                        /* Use the first rdev as the reference */
                        reference = rdev;
@@ -1793,6 +1787,8 @@ int md_integrity_register(mddev_t *mddev)
                                rdev->bdev->bd_disk) < 0)
                        return -EINVAL;
        }
+       if (!reference || !bdev_get_integrity(reference->bdev))
+               return 0;
        /*
         * All component devices are integrity capable and have matching
         * profiles, register the common profile for the md device.
index 767406c95291441eca4fbdd0eefa1184b1e076e5..700d420a59ace300276c07eb69cd29e9a30c896e 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/swab.h>
 #include "r592.h"
 
-static int enable_dma = 1;
+static int r592_enable_dma = 1;
 static int debug;
 
 static const char *tpc_names[] = {
@@ -267,7 +267,7 @@ static void r592_stop_dma(struct r592_device *dev, int error)
 /* Test if hardware supports DMA */
 static void r592_check_dma(struct r592_device *dev)
 {
-       dev->dma_capable = enable_dma &&
+       dev->dma_capable = r592_enable_dma &&
                (r592_read_reg(dev, R592_FIFO_DMA_SETTINGS) &
                        R592_FIFO_DMA_SETTINGS_CAP);
 }
@@ -898,7 +898,7 @@ static void __exit r592_module_exit(void)
 module_init(r592_module_init);
 module_exit(r592_module_exit);
 
-module_param(enable_dma, bool, S_IRUGO);
+module_param_named(enable_dma, r592_enable_dma, bool, S_IRUGO);
 MODULE_PARM_DESC(enable_dma, "Enable usage of the DMA (default)");
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level (0-3)");
index 9c511c1604a5f09c4051172eca8c2b95bbf691df..011cb6ce861bcd8f4d820f6b1e77bff51ec9cd99 100644 (file)
@@ -416,7 +416,6 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
                                : chip->companion;
        unsigned char status_buf[INT_STATUS_NUM];
        unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-       struct irq_desc *desc;
        int i, data, mask, ret = -EINVAL;
        int __irq;
 
@@ -468,19 +467,17 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
        if (!chip->core_irq)
                goto out;
 
-       desc = irq_to_desc(chip->core_irq);
-
        /* register IRQ by genirq */
        for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
                __irq = i + chip->irq_base;
-               set_irq_chip_data(__irq, chip);
-               set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
+               irq_set_chip_data(__irq, chip);
+               irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(__irq, 1);
+               irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(__irq, IRQF_VALID);
 #else
-               set_irq_noprobe(__irq);
+               irq_set_noprobe(__irq);
 #endif
        }
 
index a9a1af49281eea983265c3084c6a1f8bed1585a9..e2fea580585a2645481a4c79e8f1ea394c35ad75 100644 (file)
@@ -60,15 +60,6 @@ config MFD_ASIC3
          This driver supports the ASIC3 multifunction chip found on many
          PDAs (mainly iPAQ and HTC based ones)
 
-config MFD_SH_MOBILE_SDHI
-       bool "Support for SuperH Mobile SDHI"
-       depends on SUPERH || ARCH_SHMOBILE
-       select MFD_CORE
-       select TMIO_MMC_DMA
-        ---help---
-         This driver supports the SDHI hardware block found in many
-         SuperH Mobile SoCs.
-
 config MFD_DAVINCI_VOICECODEC
        tristate
        select MFD_CORE
@@ -133,6 +124,7 @@ config TPS6105X
        tristate "TPS61050/61052 Boost Converters"
        depends on I2C
        select REGULATOR
+       select MFD_CORE
        select REGULATOR_FIXED_VOLTAGE
        help
          This option enables a driver for the TP61050/TPS61052
@@ -265,11 +257,6 @@ config MFD_TMIO
        bool
        default n
 
-config TMIO_MMC_DMA
-       bool
-       select DMA_ENGINE
-       select DMADEVICES
-
 config MFD_T7L66XB
        bool "Support Toshiba T7L66XB"
        depends on ARM && HAVE_CLK
@@ -591,7 +578,7 @@ config AB3550_CORE
 config MFD_CS5535
        tristate "Support for CS5535 and CS5536 southbridge core functions"
        select MFD_CORE
-       depends on PCI
+       depends on PCI && X86
        ---help---
          This is the core driver for CS5535/CS5536 MFD functions.  This is
           necessary for using the board's GPIO and MFGPT functionality.
index 47f5709f3828c48d1b85e894e241341291dccf6f..419caa9d7dcfe395282ef85c8b50bf2238ce0308 100644 (file)
@@ -6,7 +6,6 @@
 obj-$(CONFIG_MFD_88PM860X)     += 88pm860x.o
 obj-$(CONFIG_MFD_SM501)                += sm501.o
 obj-$(CONFIG_MFD_ASIC3)                += asic3.o tmio_core.o
-obj-$(CONFIG_MFD_SH_MOBILE_SDHI)               += sh_mobile_sdhi.o
 
 obj-$(CONFIG_HTC_EGPIO)                += htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)       += htc-pasic3.o
@@ -63,7 +62,7 @@ obj-$(CONFIG_UCB1400_CORE)    += ucb1400_core.o
 obj-$(CONFIG_PMIC_DA903X)      += da903x.o
 max8925-objs                   := max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)      += max8925.o
-obj-$(CONFIG_MFD_MAX8997)      += max8997.o
+obj-$(CONFIG_MFD_MAX8997)      += max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)      += max8998.o max8998-irq.o
 
 pcf50633-objs                  := pcf50633-core.o pcf50633-irq.o
index c12d042852269a6ebaeff0e132d316ef2b0a6d0e..ff86acf3e6bde2b16f6e95f2f8c6af90e92bcd64 100644 (file)
@@ -668,7 +668,7 @@ static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq)
        struct ab3550_platform_data *plf_data;
        bool val;
 
-       ab = get_irq_chip_data(irq);
+       ab = irq_get_chip_data(irq);
        plf_data = ab->i2c_client[0]->dev.platform_data;
        irq -= plf_data->irq.base;
        val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0);
@@ -1296,14 +1296,14 @@ static int __init ab3550_probe(struct i2c_client *client,
                unsigned int irq;
 
                irq = ab3550_plf_data->irq.base + i;
-               set_irq_chip_data(irq, ab);
-               set_irq_chip_and_handler(irq, &ab3550_irq_chip,
-                       handle_simple_irq);
-               set_irq_nested_thread(irq, 1);
+               irq_set_chip_data(irq, ab);
+               irq_set_chip_and_handler(irq, &ab3550_irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID);
 #else
-               set_irq_noprobe(irq);
+               irq_set_noprobe(irq);
 #endif
        }
 
index 6e185b272d00890a20a2fff6b6e2f846b00cc753..67d01c9382844f9e1b6c793181e82cd2865e58c4 100644 (file)
@@ -334,14 +334,14 @@ static int ab8500_irq_init(struct ab8500 *ab8500)
        int irq;
 
        for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
-               set_irq_chip_data(irq, ab8500);
-               set_irq_chip_and_handler(irq, &ab8500_irq_chip,
+               irq_set_chip_data(irq, ab8500);
+               irq_set_chip_and_handler(irq, &ab8500_irq_chip,
                                         handle_simple_irq);
-               set_irq_nested_thread(irq, 1);
+               irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID);
 #else
-               set_irq_noprobe(irq);
+               irq_set_noprobe(irq);
 #endif
        }
 
@@ -357,11 +357,20 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
 
+static struct resource ab8500_gpio_resources[] = {
+       {
+               .name   = "GPIO_INT6",
+               .start  = AB8500_INT_GPIO6R,
+               .end    = AB8500_INT_GPIO41F,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
 static struct resource ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
@@ -595,6 +604,11 @@ static struct mfd_cell ab8500_devs[] = {
        {
                .name = "ab8500-regulator",
        },
+       {
+               .name = "ab8500-gpio",
+               .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
+               .resources = ab8500_gpio_resources,
+       },
        {
                .name = "ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
index 6820327adf4a356916bfda15268afee50d091527..821e6b86afd2a82a73811f65176fca1b3e835110 100644 (file)
@@ -97,7 +97,7 @@ static void __exit ab8500_i2c_exit(void)
 {
        platform_driver_unregister(&ab8500_i2c_driver);
 }
-subsys_initcall(ab8500_i2c_init);
+arch_initcall(ab8500_i2c_init);
 module_exit(ab8500_i2c_exit);
 
 MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
index 0241f08fc00d63cfde562a96c7d7a43818bbf9e0..d4a851c6b5bf17f4da0b8326275a82c458c97983 100644 (file)
@@ -139,13 +139,12 @@ static void asic3_irq_flip_edge(struct asic3 *asic,
 
 static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
+       struct asic3 *asic = irq_desc_get_handler_data(desc);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        int iter, i;
        unsigned long flags;
-       struct asic3 *asic;
-
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-       asic = get_irq_data(irq);
+       data->chip->irq_ack(irq_data);
 
        for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
                u32 status;
@@ -188,8 +187,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
                                        irqnr = asic->irq_base +
                                                (ASIC3_GPIOS_PER_BANK * bank)
                                                + i;
-                                       desc = irq_to_desc(irqnr);
-                                       desc->handle_irq(irqnr, desc);
+                                       generic_handle_irq(irqnr);
                                        if (asic->irq_bothedge[bank] & bit)
                                                asic3_irq_flip_edge(asic, base,
                                                                    bit);
@@ -200,11 +198,8 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
                /* Handle remaining IRQs in the status register */
                for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
                        /* They start at bit 4 and go up */
-                       if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
-                               desc = irq_to_desc(asic->irq_base + i);
-                               desc->handle_irq(asic->irq_base + i,
-                                                desc);
-                       }
+                       if (status & (1 << (i - ASIC3_NUM_GPIOS + 4)))
+                               generic_handle_irq(asic->irq_base + i);
                }
        }
 
@@ -393,21 +388,21 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
 
        for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
                if (irq < asic->irq_base + ASIC3_NUM_GPIOS)
-                       set_irq_chip(irq, &asic3_gpio_irq_chip);
+                       irq_set_chip(irq, &asic3_gpio_irq_chip);
                else
-                       set_irq_chip(irq, &asic3_irq_chip);
+                       irq_set_chip(irq, &asic3_irq_chip);
 
-               set_irq_chip_data(irq, asic);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_data(irq, asic);
+               irq_set_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK),
                             ASIC3_INTMASK_GINTMASK);
 
-       set_irq_chained_handler(asic->irq_nr, asic3_irq_demux);
-       set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
-       set_irq_data(asic->irq_nr, asic);
+       irq_set_chained_handler(asic->irq_nr, asic3_irq_demux);
+       irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
+       irq_set_handler_data(asic->irq_nr, asic);
 
        return 0;
 }
@@ -421,11 +416,10 @@ static void asic3_irq_remove(struct platform_device *pdev)
 
        for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
                set_irq_flags(irq, 0);
-               set_irq_handler(irq, NULL);
-               set_irq_chip(irq, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
        }
-       set_irq_chained_handler(asic->irq_nr, NULL);
+       irq_set_chained_handler(asic->irq_nr, NULL);
 }
 
 /* GPIOs */
index 886a068710652613e195b54ed433c86f6c664bef..155fa04078821d6fc8d5a5475225bba3a436ba06 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mfd/core.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <asm/olpc.h>
 
 #define DRV_NAME "cs5535-mfd"
 
@@ -111,6 +112,20 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
        },
 };
 
+#ifdef CONFIG_OLPC
+static void __devinit cs5535_clone_olpc_cells(void)
+{
+       const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
+
+       if (!machine_is_olpc())
+               return;
+
+       mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones));
+}
+#else
+static void cs5535_clone_olpc_cells(void) { }
+#endif
+
 static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
                const struct pci_device_id *id)
 {
@@ -139,6 +154,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
                dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
                goto err_disable;
        }
+       cs5535_clone_olpc_cells();
 
        dev_info(&pdev->dev, "%zu devices registered.\n",
                        ARRAY_SIZE(cs5535_mfd_cells));
index 9e2d8dd5f9e53d1d57d0ebbbee5bfedb992068e1..f2f4029e21a081b5c511d768df594f7d6c89bc67 100644 (file)
@@ -162,6 +162,7 @@ static void pcap_unmask_irq(struct irq_data *d)
 
 static struct irq_chip pcap_irq_chip = {
        .name           = "pcap",
+       .irq_disable    = pcap_mask_irq,
        .irq_mask       = pcap_mask_irq,
        .irq_unmask     = pcap_unmask_irq,
 };
@@ -196,17 +197,8 @@ static void pcap_isr_work(struct work_struct *work)
                local_irq_disable();
                service = isr & ~msr;
                for (irq = pcap->irq_base; service; service >>= 1, irq++) {
-                       if (service & 1) {
-                               struct irq_desc *desc = irq_to_desc(irq);
-
-                               if (WARN(!desc, "Invalid PCAP IRQ %d\n", irq))
-                                       break;
-
-                               if (desc->status & IRQ_DISABLED)
-                                       note_interrupt(irq, desc, IRQ_NONE);
-                               else
-                                       desc->handle_irq(irq, desc);
-                       }
+                       if (service & 1)
+                               generic_handle_irq(irq);
                }
                local_irq_enable();
                ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
@@ -215,7 +207,7 @@ static void pcap_isr_work(struct work_struct *work)
 
 static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct pcap_chip *pcap = get_irq_data(irq);
+       struct pcap_chip *pcap = irq_get_handler_data(irq);
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
        queue_work(pcap->workqueue, &pcap->isr_work);
@@ -419,7 +411,7 @@ static int __devexit ezx_pcap_remove(struct spi_device *spi)
 
        /* cleanup irqchip */
        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
-               set_irq_chip_and_handler(i, NULL, NULL);
+               irq_set_chip_and_handler(i, NULL, NULL);
 
        destroy_workqueue(pcap->workqueue);
 
@@ -476,12 +468,12 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi)
 
        /* setup irq chip */
        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) {
-               set_irq_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
-               set_irq_chip_data(i, pcap);
+               irq_set_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
+               irq_set_chip_data(i, pcap);
 #ifdef CONFIG_ARM
                set_irq_flags(i, IRQF_VALID);
 #else
-               set_irq_noprobe(i);
+               irq_set_noprobe(i);
 #endif
        }
 
@@ -490,10 +482,10 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi)
        ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
        pcap->msr = PCAP_MASK_ALL_INTERRUPT;
 
-       set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
-       set_irq_data(spi->irq, pcap);
-       set_irq_chained_handler(spi->irq, pcap_irq_handler);
-       set_irq_wake(spi->irq, 1);
+       irq_set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
+       irq_set_handler_data(spi->irq, pcap);
+       irq_set_chained_handler(spi->irq, pcap_irq_handler);
+       irq_set_irq_wake(spi->irq, 1);
 
        /* ADC */
        adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
@@ -522,7 +514,7 @@ remove_subdevs:
        free_irq(adc_irq, pcap);
 free_irqchip:
        for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
-               set_irq_chip_and_handler(i, NULL, NULL);
+               irq_set_chip_and_handler(i, NULL, NULL);
 /* destroy_workqueue: */
        destroy_workqueue(pcap->workqueue);
 free_pcap:
index d00b6d1a69e531daedb85a479fad72849a1e30c9..bbaec0ccba8f1185dcb4dce0fd899c5b83ecef8a 100644 (file)
@@ -100,7 +100,7 @@ static struct irq_chip egpio_muxed_chip = {
 
 static void egpio_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct egpio_info *ei = get_irq_data(irq);
+       struct egpio_info *ei = irq_desc_get_handler_data(desc);
        int irqpin;
 
        /* Read current pins. */
@@ -113,9 +113,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc)
        for_each_set_bit(irqpin, &readval, ei->nirqs) {
                /* Run irq handler */
                pr_debug("got IRQ %d\n", irqpin);
-               irq = ei->irq_start + irqpin;
-               desc = irq_to_desc(irq);
-               desc->handle_irq(irq, desc);
+               generic_handle_irq(ei->irq_start + irqpin);
        }
 }
 
@@ -346,14 +344,14 @@ static int __init egpio_probe(struct platform_device *pdev)
                        ei->ack_write = 0;
                irq_end = ei->irq_start + ei->nirqs;
                for (irq = ei->irq_start; irq < irq_end; irq++) {
-                       set_irq_chip(irq, &egpio_muxed_chip);
-                       set_irq_chip_data(irq, ei);
-                       set_irq_handler(irq, handle_simple_irq);
+                       irq_set_chip_and_handler(irq, &egpio_muxed_chip,
+                                                handle_simple_irq);
+                       irq_set_chip_data(irq, ei);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
-               set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
-               set_irq_data(ei->chained_irq, ei);
-               set_irq_chained_handler(ei->chained_irq, egpio_handler);
+               irq_set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
+               irq_set_handler_data(ei->chained_irq, ei);
+               irq_set_chained_handler(ei->chained_irq, egpio_handler);
                ack_irqs(ei);
 
                device_init_wakeup(&pdev->dev, 1);
@@ -375,11 +373,10 @@ static int __exit egpio_remove(struct platform_device *pdev)
        if (ei->chained_irq) {
                irq_end = ei->irq_start + ei->nirqs;
                for (irq = ei->irq_start; irq < irq_end; irq++) {
-                       set_irq_chip(irq, NULL);
-                       set_irq_handler(irq, NULL);
+                       irq_set_chip_and_handler(irq, NULL, NULL);
                        set_irq_flags(irq, 0);
                }
-               set_irq_chained_handler(ei->chained_irq, NULL);
+               irq_set_chained_handler(ei->chained_irq, NULL);
                device_init_wakeup(&pdev->dev, 0);
        }
        iounmap(ei->base_addr);
index 296ad1562f69a76d0c9b13101eb2821cdf8fcc31..d55065cc324c7cfa9ae91911eff72a51beac2d0a 100644 (file)
@@ -58,6 +58,7 @@ struct htcpld_chip {
        uint                    irq_start;
        int                     nirqs;
 
+       unsigned int            flow_type;
        /*
         * Work structure to allow for setting values outside of any
         * possible interrupt context
@@ -97,12 +98,7 @@ static void htcpld_unmask(struct irq_data *data)
 
 static int htcpld_set_type(struct irq_data *data, unsigned int flags)
 {
-       struct irq_desc *d = irq_to_desc(data->irq);
-
-       if (!d) {
-               pr_err("HTCPLD invalid IRQ: %d\n", data->irq);
-               return -EINVAL;
-       }
+       struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
 
        if (flags & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
@@ -111,9 +107,7 @@ static int htcpld_set_type(struct irq_data *data, unsigned int flags)
        if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
                return -EINVAL;
 
-       d->status &= ~IRQ_TYPE_SENSE_MASK;
-       d->status |= flags;
-
+       chip->flow_type = flags;
        return 0;
 }
 
@@ -135,7 +129,6 @@ static irqreturn_t htcpld_handler(int irq, void *dev)
        unsigned int i;
        unsigned long flags;
        int irqpin;
-       struct irq_desc *desc;
 
        if (!htcpld) {
                pr_debug("htcpld is null in ISR\n");
@@ -195,23 +188,19 @@ static irqreturn_t htcpld_handler(int irq, void *dev)
                 * associated interrupts.
                 */
                for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
-                       unsigned oldb, newb;
-                       int flags;
+                       unsigned oldb, newb, type = chip->flow_type;
 
                        irq = chip->irq_start + irqpin;
-                       desc = irq_to_desc(irq);
-                       flags = desc->status;
 
                        /* Run the IRQ handler, but only if the bit value
                         * changed, and the proper flags are set */
                        oldb = (old_val >> irqpin) & 1;
                        newb = (uval >> irqpin) & 1;
 
-                       if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) ||
-                           (oldb && !newb &&
-                            (flags & IRQ_TYPE_EDGE_FALLING))) {
+                       if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) ||
+                           (oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) {
                                pr_debug("fire IRQ %d\n", irqpin);
-                               desc->handle_irq(irq, desc);
+                               generic_handle_irq(irq);
                        }
                }
        }
@@ -359,13 +348,13 @@ static int __devinit htcpld_setup_chip_irq(
        /* Setup irq handlers */
        irq_end = chip->irq_start + chip->nirqs;
        for (irq = chip->irq_start; irq < irq_end; irq++) {
-               set_irq_chip(irq, &htcpld_muxed_chip);
-               set_irq_chip_data(irq, chip);
-               set_irq_handler(irq, handle_simple_irq);
+               irq_set_chip_and_handler(irq, &htcpld_muxed_chip,
+                                        handle_simple_irq);
+               irq_set_chip_data(irq, chip);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #else
-               set_irq_probe(irq);
+               irq_set_probe(irq);
 #endif
        }
 
index aa518b9beaf5c4e7ebb9059ddbd8f62d55916c84..a0bd0cf05af3912b1c0c7d490419a3e6eab9d102 100644 (file)
@@ -112,7 +112,7 @@ static struct irq_chip jz4740_adc_irq_chip = {
 
 static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct jz4740_adc *adc = get_irq_desc_data(desc);
+       struct jz4740_adc *adc = irq_desc_get_handler_data(desc);
        uint8_t status;
        unsigned int i;
 
@@ -310,13 +310,13 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, adc);
 
        for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) {
-               set_irq_chip_data(irq, adc);
-               set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip,
-                   handle_level_irq);
+               irq_set_chip_data(irq, adc);
+               irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
+                                        handle_level_irq);
        }
 
-       set_irq_data(adc->irq, adc);
-       set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux);
+       irq_set_handler_data(adc->irq, adc);
+       irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);
 
        writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
        writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
@@ -347,8 +347,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
 
        mfd_remove_devices(&pdev->dev);
 
-       set_irq_data(adc->irq, NULL);
-       set_irq_chained_handler(adc->irq, NULL);
+       irq_set_handler_data(adc->irq, NULL);
+       irq_set_chained_handler(adc->irq, NULL);
 
        iounmap(adc->base);
        release_mem_region(adc->mem->start, resource_size(adc->mem));
index 0e998dc4e7d8cb0c9407a90cb615e9559d6d1b21..58cc5fdde01647be4260f4736a55596d5c684242 100644 (file)
@@ -517,7 +517,6 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
                            struct max8925_platform_data *pdata)
 {
        unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-       struct irq_desc *desc;
        int i, ret;
        int __irq;
 
@@ -544,19 +543,18 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
        mutex_init(&chip->irq_lock);
        chip->core_irq = irq;
        chip->irq_base = pdata->irq_base;
-       desc = irq_to_desc(chip->core_irq);
 
        /* register with genirq */
        for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
                __irq = i + chip->irq_base;
-               set_irq_chip_data(__irq, chip);
-               set_irq_chip_and_handler(__irq, &max8925_irq_chip,
+               irq_set_chip_data(__irq, chip);
+               irq_set_chip_and_handler(__irq, &max8925_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(__irq, 1);
+               irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(__irq, IRQF_VALID);
 #else
-               set_irq_noprobe(__irq);
+               irq_set_noprobe(__irq);
 #endif
        }
        if (!irq) {
diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
new file mode 100644 (file)
index 0000000..638bf7e
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * max8997-irq.c - Interrupt controller support for MAX8997
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ * This driver is based on max8998-irq.c
+ */
+
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+static const u8 max8997_mask_reg[] = {
+       [PMIC_INT1] = MAX8997_REG_INT1MSK,
+       [PMIC_INT2] = MAX8997_REG_INT2MSK,
+       [PMIC_INT3] = MAX8997_REG_INT3MSK,
+       [PMIC_INT4] = MAX8997_REG_INT4MSK,
+       [FUEL_GAUGE] = MAX8997_REG_INVALID,
+       [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
+       [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
+       [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
+       [GPIO_LOW] = MAX8997_REG_INVALID,
+       [GPIO_HI] = MAX8997_REG_INVALID,
+       [FLASH_STATUS] = MAX8997_REG_INVALID,
+};
+
+static struct i2c_client *get_i2c(struct max8997_dev *max8997,
+                               enum max8997_irq_source src)
+{
+       switch (src) {
+       case PMIC_INT1 ... PMIC_INT4:
+               return max8997->i2c;
+       case FUEL_GAUGE:
+               return NULL;
+       case MUIC_INT1 ... MUIC_INT3:
+               return max8997->muic;
+       case GPIO_LOW ... GPIO_HI:
+               return max8997->i2c;
+       case FLASH_STATUS:
+               return max8997->i2c;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
+struct max8997_irq_data {
+       int mask;
+       enum max8997_irq_source group;
+};
+
+#define DECLARE_IRQ(idx, _group, _mask)                \
+       [(idx)] = { .group = (_group), .mask = (_mask) }
+static const struct max8997_irq_data max8997_irqs[] = {
+       DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR,     PMIC_INT1, 1 << 0),
+       DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF,     PMIC_INT1, 1 << 1),
+       DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC,  PMIC_INT1, 1 << 3),
+       DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR,     PMIC_INT1, 1 << 4),
+       DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF,     PMIC_INT1, 1 << 5),
+       DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2,    PMIC_INT1, 1 << 6),
+       DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1,    PMIC_INT1, 1 << 7),
+
+       DECLARE_IRQ(MAX8997_PMICIRQ_JIGR,       PMIC_INT2, 1 << 0),
+       DECLARE_IRQ(MAX8997_PMICIRQ_JIGF,       PMIC_INT2, 1 << 1),
+       DECLARE_IRQ(MAX8997_PMICIRQ_MR,         PMIC_INT2, 1 << 2),
+       DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK,     PMIC_INT2, 1 << 3),
+       DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK,     PMIC_INT2, 1 << 4),
+       DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK,     PMIC_INT2, 1 << 5),
+       DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK,     PMIC_INT2, 1 << 6),
+
+       DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS,     PMIC_INT3, 1 << 0),
+       DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM,      PMIC_INT3, 1 << 1),
+       DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP,    PMIC_INT3, 1 << 2),
+       DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR,    PMIC_INT3, 1 << 3),
+       DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF,    PMIC_INT3, 1 << 5),
+       DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD,        PMIC_INT3, 1 << 7),
+
+       DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S,     PMIC_INT4, 1 << 0),
+       DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1,      PMIC_INT4, 1 << 1),
+       DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2,      PMIC_INT4, 1 << 2),
+       DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT,   PMIC_INT4, 1 << 3),
+       DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S,      PMIC_INT4, 1 << 4),
+       DECLARE_IRQ(MAX8997_PMICIRQ_WTSR,       PMIC_INT4, 1 << 5),
+
+       DECLARE_IRQ(MAX8997_MUICIRQ_ADCError,   MUIC_INT1, 1 << 2),
+       DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow,     MUIC_INT1, 1 << 1),
+       DECLARE_IRQ(MAX8997_MUICIRQ_ADC,        MUIC_INT1, 1 << 0),
+
+       DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt,     MUIC_INT2, 1 << 4),
+       DECLARE_IRQ(MAX8997_MUICIRQ_DBChg,      MUIC_INT2, 1 << 3),
+       DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr,     MUIC_INT2, 1 << 2),
+       DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun,  MUIC_INT2, 1 << 1),
+       DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp,     MUIC_INT2, 1 << 0),
+
+       DECLARE_IRQ(MAX8997_MUICIRQ_OVP,        MUIC_INT3, 1 << 2),
+};
+
+static void max8997_irq_lock(struct irq_data *data)
+{
+       struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+
+       mutex_lock(&max8997->irqlock);
+}
+
+static void max8997_irq_sync_unlock(struct irq_data *data)
+{
+       struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+       int i;
+
+       for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
+               u8 mask_reg = max8997_mask_reg[i];
+               struct i2c_client *i2c = get_i2c(max8997, i);
+
+               if (mask_reg == MAX8997_REG_INVALID ||
+                               IS_ERR_OR_NULL(i2c))
+                       continue;
+               max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
+
+               max8997_write_reg(i2c, max8997_mask_reg[i],
+                               max8997->irq_masks_cur[i]);
+       }
+
+       mutex_unlock(&max8997->irqlock);
+}
+
+static const inline struct max8997_irq_data *
+irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
+{
+       return &max8997_irqs[irq - max8997->irq_base];
+}
+
+static void max8997_irq_mask(struct irq_data *data)
+{
+       struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+       const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
+                                                               data->irq);
+
+       max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
+}
+
+static void max8997_irq_unmask(struct irq_data *data)
+{
+       struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+       const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
+                                                               data->irq);
+
+       max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
+}
+
+static struct irq_chip max8997_irq_chip = {
+       .name                   = "max8997",
+       .irq_bus_lock           = max8997_irq_lock,
+       .irq_bus_sync_unlock    = max8997_irq_sync_unlock,
+       .irq_mask               = max8997_irq_mask,
+       .irq_unmask             = max8997_irq_unmask,
+};
+
+#define MAX8997_IRQSRC_PMIC            (1 << 1)
+#define MAX8997_IRQSRC_FUELGAUGE       (1 << 2)
+#define MAX8997_IRQSRC_MUIC            (1 << 3)
+#define MAX8997_IRQSRC_GPIO            (1 << 4)
+#define MAX8997_IRQSRC_FLASH           (1 << 5)
+static irqreturn_t max8997_irq_thread(int irq, void *data)
+{
+       struct max8997_dev *max8997 = data;
+       u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
+       u8 irq_src;
+       int ret;
+       int i;
+
+       ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
+       if (ret < 0) {
+               dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
+                               ret);
+               return IRQ_NONE;
+       }
+
+       if (irq_src & MAX8997_IRQSRC_PMIC) {
+               /* PMIC INT1 ~ INT4 */
+               max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
+                               &irq_reg[PMIC_INT1]);
+       }
+       if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
+               /*
+                * TODO: FUEL GAUGE
+                *
+                * This is to be supported by Max17042 driver. When
+                * an interrupt incurs here, it should be relayed to a
+                * Max17042 device that is connected (probably by
+                * platform-data). However, we do not have interrupt
+                * handling in Max17042 driver currently. The Max17042 IRQ
+                * driver should be ready to be used as a stand-alone device and
+                * a Max8997-dependent device. Because it is not ready in
+                * Max17042-side and it is not too critical in operating
+                * Max8997, we do not implement this in initial releases.
+                */
+               irq_reg[FUEL_GAUGE] = 0;
+       }
+       if (irq_src & MAX8997_IRQSRC_MUIC) {
+               /* MUIC INT1 ~ INT3 */
+               max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
+                               &irq_reg[MUIC_INT1]);
+       }
+       if (irq_src & MAX8997_IRQSRC_GPIO) {
+               /* GPIO Interrupt */
+               u8 gpio_info[MAX8997_NUM_GPIO];
+
+               irq_reg[GPIO_LOW] = 0;
+               irq_reg[GPIO_HI] = 0;
+
+               max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
+                               MAX8997_NUM_GPIO, gpio_info);
+               for (i = 0; i < MAX8997_NUM_GPIO; i++) {
+                       bool interrupt = false;
+
+                       switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
+                       case MAX8997_GPIO_INT_BOTH:
+                               if (max8997->gpio_status[i] != gpio_info[i])
+                                       interrupt = true;
+                               break;
+                       case MAX8997_GPIO_INT_RISE:
+                               if ((max8997->gpio_status[i] != gpio_info[i]) &&
+                                   (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
+                                       interrupt = true;
+                               break;
+                       case MAX8997_GPIO_INT_FALL:
+                               if ((max8997->gpio_status[i] != gpio_info[i]) &&
+                                   !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
+                                       interrupt = true;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       if (interrupt) {
+                               if (i < 8)
+                                       irq_reg[GPIO_LOW] |= (1 << i);
+                               else
+                                       irq_reg[GPIO_HI] |= (1 << (i - 8));
+                       }
+
+               }
+       }
+       if (irq_src & MAX8997_IRQSRC_FLASH) {
+               /* Flash Status Interrupt */
+               ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
+                               &irq_reg[FLASH_STATUS]);
+       }
+
+       /* Apply masking */
+       for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
+               irq_reg[i] &= ~max8997->irq_masks_cur[i];
+
+       /* Report */
+       for (i = 0; i < MAX8997_IRQ_NR; i++) {
+               if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask)
+                       handle_nested_irq(max8997->irq_base + i);
+       }
+
+       return IRQ_HANDLED;
+}
+
+int max8997_irq_resume(struct max8997_dev *max8997)
+{
+       if (max8997->irq && max8997->irq_base)
+               max8997_irq_thread(max8997->irq_base, max8997);
+       return 0;
+}
+
+int max8997_irq_init(struct max8997_dev *max8997)
+{
+       int i;
+       int cur_irq;
+       int ret;
+       u8 val;
+
+       if (!max8997->irq) {
+               dev_warn(max8997->dev, "No interrupt specified.\n");
+               max8997->irq_base = 0;
+               return 0;
+       }
+
+       if (!max8997->irq_base) {
+               dev_err(max8997->dev, "No interrupt base specified.\n");
+               return 0;
+       }
+
+       mutex_init(&max8997->irqlock);
+
+       /* Mask individual interrupt sources */
+       for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
+               struct i2c_client *i2c;
+
+               max8997->irq_masks_cur[i] = 0xff;
+               max8997->irq_masks_cache[i] = 0xff;
+               i2c = get_i2c(max8997, i);
+
+               if (IS_ERR_OR_NULL(i2c))
+                       continue;
+               if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
+                       continue;
+
+               max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
+       }
+
+       for (i = 0; i < MAX8997_NUM_GPIO; i++) {
+               max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
+                                               MAX8997_REG_GPIOCNTL1 + i,
+                                               &val)
+                                       & MAX8997_GPIO_DATA_MASK) ?
+                                       true : false;
+       }
+
+       /* Register with genirq */
+       for (i = 0; i < MAX8997_IRQ_NR; i++) {
+               cur_irq = i + max8997->irq_base;
+               irq_set_chip_data(cur_irq, max8997);
+               irq_set_chip_and_handler(cur_irq, &max8997_irq_chip,
+                               handle_edge_irq);
+               irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(cur_irq, IRQF_VALID);
+#else
+               irq_set_noprobe(cur_irq);
+#endif
+       }
+
+       ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
+                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       "max8997-irq", max8997);
+
+       if (ret) {
+               dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
+                               max8997->irq, ret);
+               return ret;
+       }
+
+       if (!max8997->ono)
+               return 0;
+
+       ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
+                       IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+                       IRQF_ONESHOT, "max8997-ono", max8997);
+
+       if (ret)
+               dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
+                               max8997->ono, ret);
+
+       return 0;
+}
+
+void max8997_irq_exit(struct max8997_dev *max8997)
+{
+       if (max8997->ono)
+               free_irq(max8997->ono, max8997);
+
+       if (max8997->irq)
+               free_irq(max8997->irq, max8997);
+}
index 3903e1fbb3347b0792dc83a651b125163ad52c3c..5919710dc9ed47aae020619d6f0b1e5c7a808c23 100644 (file)
@@ -224,14 +224,14 @@ int max8998_irq_init(struct max8998_dev *max8998)
        /* register with genirq */
        for (i = 0; i < MAX8998_IRQ_NR; i++) {
                cur_irq = i + max8998->irq_base;
-               set_irq_chip_data(cur_irq, max8998);
-               set_irq_chip_and_handler(cur_irq, &max8998_irq_chip,
+               irq_set_chip_data(cur_irq, max8998);
+               irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(cur_irq, 1);
+               irq_set_nested_thread(cur_irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(cur_irq, IRQF_VALID);
 #else
-               set_irq_noprobe(cur_irq);
+               irq_set_noprobe(cur_irq);
 #endif
        }
 
index c00214257da28c97e80e27c30cedf3ac86ac7cfe..9ec7570f5b8140b53bc620edbba36df37b9757b4 100644 (file)
@@ -209,7 +209,7 @@ static int max8998_suspend(struct device *dev)
        struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
 
        if (max8998->wakeup)
-               set_irq_wake(max8998->irq, 1);
+               irq_set_irq_wake(max8998->irq, 1);
        return 0;
 }
 
@@ -219,7 +219,7 @@ static int max8998_resume(struct device *dev)
        struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
 
        if (max8998->wakeup)
-               set_irq_wake(max8998->irq, 0);
+               irq_set_irq_wake(max8998->irq, 0);
        /*
         * In LP3974, if IRQ registers are not "read & clear"
         * when it's set during sleep, the interrupt becomes
index 79eda0264fb277176a2141338d9d4aa8682ea3b7..d01574d98870a0473b56be995cd0341786b9b767 100644 (file)
@@ -184,16 +184,12 @@ void mfd_remove_devices(struct device *parent)
 }
 EXPORT_SYMBOL(mfd_remove_devices);
 
-static int add_shared_platform_device(const char *cell, const char *name)
+int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
 {
        struct mfd_cell cell_entry;
        struct device *dev;
        struct platform_device *pdev;
-       int err;
-
-       /* check if we've already registered a device (don't fail if we have) */
-       if (bus_find_device_by_name(&platform_bus_type, NULL, name))
-               return 0;
+       int i;
 
        /* fetch the parent cell's device (should already be registered!) */
        dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
@@ -206,44 +202,17 @@ static int add_shared_platform_device(const char *cell, const char *name)
 
        WARN_ON(!cell_entry.enable);
 
-       cell_entry.name = name;
-       err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0);
-       if (err)
-               dev_err(dev, "MFD add devices failed: %d\n", err);
-       return err;
-}
-
-int mfd_shared_platform_driver_register(struct platform_driver *drv,
-               const char *cellname)
-{
-       int err;
-
-       err = add_shared_platform_device(cellname, drv->driver.name);
-       if (err)
-               printk(KERN_ERR "failed to add platform device %s\n",
-                               drv->driver.name);
-
-       err = platform_driver_register(drv);
-       if (err)
-               printk(KERN_ERR "failed to add platform driver %s\n",
-                               drv->driver.name);
-
-       return err;
-}
-EXPORT_SYMBOL(mfd_shared_platform_driver_register);
-
-void mfd_shared_platform_driver_unregister(struct platform_driver *drv)
-{
-       struct device *dev;
-
-       dev = bus_find_device_by_name(&platform_bus_type, NULL,
-                       drv->driver.name);
-       if (dev)
-               platform_device_unregister(to_platform_device(dev));
+       for (i = 0; i < n_clones; i++) {
+               cell_entry.name = clones[i];
+               /* don't give up if a single call fails; just report error */
+               if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
+                       dev_err(dev, "failed to create platform device '%s'\n",
+                                       clones[i]);
+       }
 
-       platform_driver_unregister(drv);
+       return 0;
 }
-EXPORT_SYMBOL(mfd_shared_platform_driver_unregister);
+EXPORT_SYMBOL(mfd_clone_cell);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
index c1306ed43e3c10cf0c7f69a95dabcf0ecdbc6bd0..c7687f6a78a0ef9d1799801f667689ca2b214124 100644 (file)
@@ -356,7 +356,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
        return 0;
 }
 
-static struct i2c_device_id pcf50633_id_table[] = {
+static const struct i2c_device_id pcf50633_id_table[] = {
        {"pcf50633", 0x73},
        {/* end of list */}
 };
index 193c940225b5bc45bec2fe3a9ce7204e79ef464d..10dbe6374a89328b00da7014e4eccfa886906f2f 100644 (file)
@@ -97,6 +97,7 @@ static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
        {}
 };
+MODULE_DEVICE_TABLE(pci, rdc321x_sb_table);
 
 static struct pci_driver rdc321x_sb_driver = {
        .name           = "RDC321x Southbridge",
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
deleted file mode 100644 (file)
index 53a6302..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * SuperH Mobile SDHI
- *
- * Copyright (C) 2009 Magnus Damm
- *
- * 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.
- *
- * Based on "Compaq ASIC3 support":
- *
- * Copyright 2001 Compaq Computer Corporation.
- * Copyright 2004-2005 Phil Blundell
- * Copyright 2007-2008 OpenedHand Ltd.
- *
- * Authors: Phil Blundell <pb@handhelds.org>,
- *         Samuel Ortiz <sameo@openedhand.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
-#include <linux/sh_dma.h>
-
-struct sh_mobile_sdhi {
-       struct clk *clk;
-       struct tmio_mmc_data mmc_data;
-       struct mfd_cell cell_mmc;
-       struct sh_dmae_slave param_tx;
-       struct sh_dmae_slave param_rx;
-       struct tmio_mmc_dma dma_priv;
-};
-
-static struct resource sh_mobile_sdhi_resources[] = {
-       {
-               .start = 0x000,
-               .end   = 0x1ff,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = 0,
-               .end   = 0,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-static struct mfd_cell sh_mobile_sdhi_cell = {
-       .name          = "tmio-mmc",
-       .num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources),
-       .resources     = sh_mobile_sdhi_resources,
-};
-
-static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state)
-{
-       struct platform_device *pdev = to_platform_device(tmio->dev.parent);
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-       if (p && p->set_pwr)
-               p->set_pwr(pdev, state);
-}
-
-static int sh_mobile_sdhi_get_cd(struct platform_device *tmio)
-{
-       struct platform_device *pdev = to_platform_device(tmio->dev.parent);
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-       if (p && p->get_cd)
-               return p->get_cd(pdev);
-       else
-               return -ENOSYS;
-}
-
-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
-{
-       struct sh_mobile_sdhi *priv;
-       struct tmio_mmc_data *mmc_data;
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-       struct resource *mem;
-       char clk_name[8];
-       int ret, irq;
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem)
-               dev_err(&pdev->dev, "missing MEM resource\n");
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               dev_err(&pdev->dev, "missing IRQ resource\n");
-
-       if (!mem || (irq < 0))
-               return -EINVAL;
-
-       priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
-       if (priv == NULL) {
-               dev_err(&pdev->dev, "kzalloc failed\n");
-               return -ENOMEM;
-       }
-
-       mmc_data = &priv->mmc_data;
-
-       snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
-       priv->clk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(priv->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               ret = PTR_ERR(priv->clk);
-               kfree(priv);
-               return ret;
-       }
-
-       clk_enable(priv->clk);
-
-       mmc_data->hclk = clk_get_rate(priv->clk);
-       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
-       if (p) {
-               mmc_data->flags = p->tmio_flags;
-               mmc_data->ocr_mask = p->tmio_ocr_mask;
-               mmc_data->capabilities |= p->tmio_caps;
-       }
-
-       /*
-        * All SDHI blocks support 2-byte and larger block sizes in 4-bit
-        * bus width mode.
-        */
-       mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES;
-
-       /*
-        * All SDHI blocks support SDIO IRQ signalling.
-        */
-       mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
-
-       if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
-               priv->param_tx.slave_id = p->dma_slave_tx;
-               priv->param_rx.slave_id = p->dma_slave_rx;
-               priv->dma_priv.chan_priv_tx = &priv->param_tx;
-               priv->dma_priv.chan_priv_rx = &priv->param_rx;
-               priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
-               mmc_data->dma = &priv->dma_priv;
-       }
-
-       memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
-       priv->cell_mmc.mfd_data = mmc_data;
-
-       platform_set_drvdata(pdev, priv);
-
-       ret = mfd_add_devices(&pdev->dev, pdev->id,
-                             &priv->cell_mmc, 1, mem, irq);
-       if (ret) {
-               clk_disable(priv->clk);
-               clk_put(priv->clk);
-               kfree(priv);
-       }
-
-       return ret;
-}
-
-static int sh_mobile_sdhi_remove(struct platform_device *pdev)
-{
-       struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev);
-
-       mfd_remove_devices(&pdev->dev);
-       clk_disable(priv->clk);
-       clk_put(priv->clk);
-       kfree(priv);
-
-       return 0;
-}
-
-static struct platform_driver sh_mobile_sdhi_driver = {
-       .driver         = {
-               .name   = "sh_mobile_sdhi",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = sh_mobile_sdhi_probe,
-       .remove         = __devexit_p(sh_mobile_sdhi_remove),
-};
-
-static int __init sh_mobile_sdhi_init(void)
-{
-       return platform_driver_register(&sh_mobile_sdhi_driver);
-}
-
-static void __exit sh_mobile_sdhi_exit(void)
-{
-       platform_driver_unregister(&sh_mobile_sdhi_driver);
-}
-
-module_init(sh_mobile_sdhi_init);
-module_exit(sh_mobile_sdhi_exit);
-
-MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
-MODULE_AUTHOR("Magnus Damm");
-MODULE_LICENSE("GPL v2");
index 3e5732b58c49900efd5da19ad14a72f659df92f5..7ab7746631d4e58a9e2fd0611c13da211ce54463 100644 (file)
@@ -762,14 +762,14 @@ static int __devinit stmpe_irq_init(struct stmpe *stmpe)
        int irq;
 
        for (irq = base; irq < base + num_irqs; irq++) {
-               set_irq_chip_data(irq, stmpe);
-               set_irq_chip_and_handler(irq, &stmpe_irq_chip,
+               irq_set_chip_data(irq, stmpe);
+               irq_set_chip_and_handler(irq, &stmpe_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(irq, 1);
+               irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID);
 #else
-               set_irq_noprobe(irq);
+               irq_set_noprobe(irq);
 #endif
        }
 
@@ -786,8 +786,8 @@ static void stmpe_irq_remove(struct stmpe *stmpe)
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
 
index af57fc706a4cedf49043309c93d6f5cc47ca7e10..42830e6929649ae99e729479eb76dd1dd4bd917c 100644 (file)
@@ -186,7 +186,7 @@ static struct mfd_cell t7l66xb_cells[] = {
 /* Handle the T7L66XB interrupt mux */
 static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct t7l66xb *t7l66xb = get_irq_data(irq);
+       struct t7l66xb *t7l66xb = irq_get_handler_data(irq);
        unsigned int isr;
        unsigned int i, irq_base;
 
@@ -243,17 +243,16 @@ static void t7l66xb_attach_irq(struct platform_device *dev)
        irq_base = t7l66xb->irq_base;
 
        for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
-               set_irq_chip(irq, &t7l66xb_chip);
-               set_irq_chip_data(irq, t7l66xb);
-               set_irq_handler(irq, handle_level_irq);
+               irq_set_chip_and_handler(irq, &t7l66xb_chip, handle_level_irq);
+               irq_set_chip_data(irq, t7l66xb);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #endif
        }
 
-       set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
-       set_irq_data(t7l66xb->irq, t7l66xb);
-       set_irq_chained_handler(t7l66xb->irq, t7l66xb_irq);
+       irq_set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
+       irq_set_handler_data(t7l66xb->irq, t7l66xb);
+       irq_set_chained_handler(t7l66xb->irq, t7l66xb_irq);
 }
 
 static void t7l66xb_detach_irq(struct platform_device *dev)
@@ -263,15 +262,15 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
 
        irq_base = t7l66xb->irq_base;
 
-       set_irq_chained_handler(t7l66xb->irq, NULL);
-       set_irq_data(t7l66xb->irq, NULL);
+       irq_set_chained_handler(t7l66xb->irq, NULL);
+       irq_set_handler_data(t7l66xb->irq, NULL);
 
        for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
-               set_irq_chip(irq, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip(irq, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
 
index 729dbeed2ce09f0c83f09483e345ffe1c1e63ebb..c27e515b0722b2dfa72263e5bd3725ddd27885fd 100644 (file)
@@ -192,14 +192,14 @@ static int tc3589x_irq_init(struct tc3589x *tc3589x)
        int irq;
 
        for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
-               set_irq_chip_data(irq, tc3589x);
-               set_irq_chip_and_handler(irq, &dummy_irq_chip,
+               irq_set_chip_data(irq, tc3589x);
+               irq_set_chip_and_handler(irq, &dummy_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(irq, 1);
+               irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(irq, IRQF_VALID);
 #else
-               set_irq_noprobe(irq);
+               irq_set_noprobe(irq);
 #endif
        }
 
@@ -215,8 +215,8 @@ static void tc3589x_irq_remove(struct tc3589x *tc3589x)
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip_and_handler(irq, NULL, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
 
index 3d62ded86a8fe478a386ae96c41d88e3d81a368d..fc53ce287601b84062940d80428fdf3dcb358c16 100644 (file)
@@ -513,7 +513,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
 static void
 tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct tc6393xb *tc6393xb = get_irq_data(irq);
+       struct tc6393xb *tc6393xb = irq_get_handler_data(irq);
        unsigned int isr;
        unsigned int i, irq_base;
 
@@ -572,15 +572,14 @@ static void tc6393xb_attach_irq(struct platform_device *dev)
        irq_base = tc6393xb->irq_base;
 
        for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
-               set_irq_chip(irq, &tc6393xb_chip);
-               set_irq_chip_data(irq, tc6393xb);
-               set_irq_handler(irq, handle_edge_irq);
+               irq_set_chip_and_handler(irq, &tc6393xb_chip, handle_edge_irq);
+               irq_set_chip_data(irq, tc6393xb);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
-       set_irq_data(tc6393xb->irq, tc6393xb);
-       set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
+       irq_set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
+       irq_set_handler_data(tc6393xb->irq, tc6393xb);
+       irq_set_chained_handler(tc6393xb->irq, tc6393xb_irq);
 }
 
 static void tc6393xb_detach_irq(struct platform_device *dev)
@@ -588,15 +587,15 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
        struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
        unsigned int irq, irq_base;
 
-       set_irq_chained_handler(tc6393xb->irq, NULL);
-       set_irq_data(tc6393xb->irq, NULL);
+       irq_set_chained_handler(tc6393xb->irq, NULL);
+       irq_set_handler_data(tc6393xb->irq, NULL);
 
        irq_base = tc6393xb->irq_base;
 
        for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
                set_irq_flags(irq, 0);
-               set_irq_chip(irq, NULL);
-               set_irq_chip_data(irq, NULL);
+               irq_set_chip(irq, NULL);
+               irq_set_chip_data(irq, NULL);
        }
 }
 
index 0aa9186aec1961cb19d8a6b35ae027c07ffb3a04..b600808690c1092e1d9946f848e537647dbd1def 100644 (file)
@@ -422,10 +422,10 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 
        for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
                int __irq = i + tps6586x->irq_base;
-               set_irq_chip_data(__irq, tps6586x);
-               set_irq_chip_and_handler(__irq, &tps6586x->irq_chip,
+               irq_set_chip_data(__irq, tps6586x);
+               irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
                                         handle_simple_irq);
-               set_irq_nested_thread(__irq, 1);
+               irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(__irq, IRQF_VALID);
 #endif
index 63a30e88908f8e903df95883c3f571e91fccff9e..8a7ee3139b86fda3bded6748e572893d37b577fb 100644 (file)
@@ -320,24 +320,8 @@ static int twl4030_irq_thread(void *data)
                for (module_irq = twl4030_irq_base;
                                pih_isr;
                                pih_isr >>= 1, module_irq++) {
-                       if (pih_isr & 0x1) {
-                               struct irq_desc *d = irq_to_desc(module_irq);
-
-                               if (!d) {
-                                       pr_err("twl4030: Invalid SIH IRQ: %d\n",
-                                              module_irq);
-                                       return -EINVAL;
-                               }
-
-                               /* These can't be masked ... always warn
-                                * if we get any surprises.
-                                */
-                               if (d->status & IRQ_DISABLED)
-                                       note_interrupt(module_irq, d,
-                                                       IRQ_NONE);
-                               else
-                                       d->handle_irq(module_irq, d);
-                       }
+                       if (pih_isr & 0x1)
+                               generic_handle_irq(module_irq);
                }
                local_irq_enable();
 
@@ -470,7 +454,7 @@ static inline void activate_irq(int irq)
        set_irq_flags(irq, IRQF_VALID);
 #else
        /* same effect on other architectures */
-       set_irq_noprobe(irq);
+       irq_set_noprobe(irq);
 #endif
 }
 
@@ -560,24 +544,18 @@ static void twl4030_sih_do_edge(struct work_struct *work)
        /* Modify only the bits we know must change */
        while (edge_change) {
                int             i = fls(edge_change) - 1;
-               struct irq_desc *d = irq_to_desc(i + agent->irq_base);
+               struct irq_data *idata = irq_get_irq_data(i + agent->irq_base);
                int             byte = 1 + (i >> 2);
                int             off = (i & 0x3) * 2;
-
-               if (!d) {
-                       pr_err("twl4030: Invalid IRQ: %d\n",
-                              i + agent->irq_base);
-                       return;
-               }
+               unsigned int    type;
 
                bytes[byte] &= ~(0x03 << off);
 
-               raw_spin_lock_irq(&d->lock);
-               if (d->status & IRQ_TYPE_EDGE_RISING)
+               type = irqd_get_trigger_type(idata);
+               if (type & IRQ_TYPE_EDGE_RISING)
                        bytes[byte] |= BIT(off + 1);
-               if (d->status & IRQ_TYPE_EDGE_FALLING)
+               if (type & IRQ_TYPE_EDGE_FALLING)
                        bytes[byte] |= BIT(off + 0);
-               raw_spin_unlock_irq(&d->lock);
 
                edge_change &= ~BIT(i);
        }
@@ -626,21 +604,13 @@ static void twl4030_sih_unmask(struct irq_data *data)
 static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
 {
        struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-       struct irq_desc *desc = irq_to_desc(data->irq);
        unsigned long flags;
 
-       if (!desc) {
-               pr_err("twl4030: Invalid IRQ: %d\n", data->irq);
-               return -EINVAL;
-       }
-
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
 
        spin_lock_irqsave(&sih_agent_lock, flags);
-       if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
-               desc->status &= ~IRQ_TYPE_SENSE_MASK;
-               desc->status |= trigger;
+       if (irqd_get_trigger_type(data) != trigger) {
                sih->edge_change |= BIT(data->irq - sih->irq_base);
                queue_work(wq, &sih->edge_work);
        }
@@ -680,7 +650,7 @@ static inline int sih_read_isr(const struct sih *sih)
  */
 static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
 {
-       struct sih_agent *agent = get_irq_data(irq);
+       struct sih_agent *agent = irq_get_handler_data(irq);
        const struct sih *sih = agent->sih;
        int isr;
 
@@ -754,9 +724,9 @@ int twl4030_sih_setup(int module)
        for (i = 0; i < sih->bits; i++) {
                irq = irq_base + i;
 
-               set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip,
-                               handle_edge_irq);
-               set_irq_chip_data(irq, agent);
+               irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
+                                        handle_edge_irq);
+               irq_set_chip_data(irq, agent);
                activate_irq(irq);
        }
 
@@ -765,8 +735,8 @@ int twl4030_sih_setup(int module)
 
        /* replace generic PIH handler (handle_simple_irq) */
        irq = sih_mod + twl4030_irq_base;
-       set_irq_data(irq, agent);
-       set_irq_chained_handler(irq, handle_twl4030_sih);
+       irq_set_handler_data(irq, agent);
+       irq_set_chained_handler(irq, handle_twl4030_sih);
 
        pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
                        irq, irq_base, twl4030_irq_next - 1);
@@ -815,8 +785,8 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        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,
-                               handle_simple_irq);
+               irq_set_chip_and_handler(i, &twl4030_irq_chip,
+                                        handle_simple_irq);
                activate_irq(i);
        }
        twl4030_irq_next = i;
@@ -856,7 +826,7 @@ fail_rqirq:
        /* clean up twl4030_sih_setup */
 fail:
        for (i = irq_base; i < irq_end; i++)
-               set_irq_chip_and_handler(i, NULL, NULL);
+               irq_set_chip_and_handler(i, NULL, NULL);
        destroy_workqueue(wq);
        wq = NULL;
        return status;
index 4082ed73613f98a6abd0fb0a1b8463f0d45a788e..fa937052fbab996b564e46ed17f3fefdae422010 100644 (file)
@@ -140,22 +140,7 @@ static int twl6030_irq_thread(void *data)
                        if (sts.int_sts & 0x1) {
                                int module_irq = twl6030_irq_base +
                                        twl6030_interrupt_mapping[i];
-                               struct irq_desc *d = irq_to_desc(module_irq);
-
-                               if (!d) {
-                                       pr_err("twl6030: Invalid SIH IRQ: %d\n",
-                                              module_irq);
-                                       return -EINVAL;
-                               }
-
-                               /* These can't be masked ... always warn
-                                * if we get any surprises.
-                                */
-                               if (d->status & IRQ_DISABLED)
-                                       note_interrupt(module_irq, d,
-                                                       IRQ_NONE);
-                               else
-                                       d->handle_irq(module_irq, d);
+                               generic_handle_irq(module_irq);
 
                        }
                local_irq_enable();
@@ -198,7 +183,7 @@ static inline void activate_irq(int irq)
        set_irq_flags(irq, IRQF_VALID);
 #else
        /* same effect on other architectures */
-       set_irq_noprobe(irq);
+       irq_set_noprobe(irq);
 #endif
 }
 
@@ -335,8 +320,8 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        twl6030_irq_chip.irq_set_type = NULL;
 
        for (i = irq_base; i < irq_end; i++) {
-               set_irq_chip_and_handler(i, &twl6030_irq_chip,
-                               handle_simple_irq);
+               irq_set_chip_and_handler(i, &twl6030_irq_chip,
+                                        handle_simple_irq);
                activate_irq(i);
        }
 
@@ -365,7 +350,7 @@ fail_irq:
 
 fail_kthread:
        for (i = irq_base; i < irq_end; i++)
-               set_irq_chip_and_handler(i, NULL, NULL);
+               irq_set_chip_and_handler(i, NULL, NULL);
        return status;
 }
 
index f76f6c798046434baeb0dddea523de6b05158d0a..04914f2836c0ad3d22a97d2787d789a1f34e1ae9 100644 (file)
@@ -25,7 +25,7 @@
 
 #define DRIVER_DESC "WL1273 FM Radio Core"
 
-static struct i2c_device_id wl1273_driver_id_table[] = {
+static const struct i2c_device_id wl1273_driver_id_table[] = {
        { WL1273_FM_DRIVER_NAME, 0 },
        { }
 };
index a5cd17e18d09d93ec582d36f19478c66259e71d2..23e66af89dea12d0871aa44fe2b824e692aee8b3 100644 (file)
@@ -553,17 +553,17 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
        for (cur_irq = wm831x->irq_base;
             cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
             cur_irq++) {
-               set_irq_chip_data(cur_irq, wm831x);
-               set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip,
+               irq_set_chip_data(cur_irq, wm831x);
+               irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(cur_irq, 1);
+               irq_set_nested_thread(cur_irq, 1);
 
                /* ARM needs us to explicitly flag the IRQ as valid
                 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
                set_irq_flags(cur_irq, IRQF_VALID);
 #else
-               set_irq_noprobe(cur_irq);
+               irq_set_noprobe(cur_irq);
 #endif
        }
 
index 5839966ebd85bfbd73b8ee229e0ee666c4b98cd2..ed4b22a167b30104d3628bed7d3ee34753dd867b 100644 (file)
@@ -518,17 +518,17 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
        for (cur_irq = wm8350->irq_base;
             cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
             cur_irq++) {
-               set_irq_chip_data(cur_irq, wm8350);
-               set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
+               irq_set_chip_data(cur_irq, wm8350);
+               irq_set_chip_and_handler(cur_irq, &wm8350_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(cur_irq, 1);
+               irq_set_nested_thread(cur_irq, 1);
 
                /* ARM needs us to explicitly flag the IRQ as valid
                 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
                set_irq_flags(cur_irq, IRQF_VALID);
 #else
-               set_irq_noprobe(cur_irq);
+               irq_set_noprobe(cur_irq);
 #endif
        }
 
index 1e3bf4a2ff8ef7dbfdd0caab962559c6fe5ed3c3..71c6e8f9aedb47af0fb1ab5d72a48bca872ad6ef 100644 (file)
@@ -278,17 +278,17 @@ int wm8994_irq_init(struct wm8994 *wm8994)
        for (cur_irq = wm8994->irq_base;
             cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
             cur_irq++) {
-               set_irq_chip_data(cur_irq, wm8994);
-               set_irq_chip_and_handler(cur_irq, &wm8994_irq_chip,
+               irq_set_chip_data(cur_irq, wm8994);
+               irq_set_chip_and_handler(cur_irq, &wm8994_irq_chip,
                                         handle_edge_irq);
-               set_irq_nested_thread(cur_irq, 1);
+               irq_set_nested_thread(cur_irq, 1);
 
                /* ARM needs us to explicitly flag the IRQ as valid
                 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
                set_irq_flags(cur_irq, IRQF_VALID);
 #else
-               set_irq_noprobe(cur_irq);
+               irq_set_noprobe(cur_irq);
 #endif
        }
 
index 28852dfa310dbfe60122ce6fce90597164a05d2a..20e4e9395b61ca1c6d85b09511b88f535a8ec120 100644 (file)
@@ -373,7 +373,7 @@ static int gru_chiplet_setup_tlb_irq(int chiplet, char *irq_name,
 
        if (gru_irq_count[chiplet] == 0) {
                gru_chip[chiplet].name = irq_name;
-               ret = set_irq_chip(irq, &gru_chip[chiplet]);
+               ret = irq_set_chip(irq, &gru_chip[chiplet]);
                if (ret) {
                        printk(KERN_ERR "%s: set_irq_chip failed, errno=%d\n",
                               GRU_DRIVER_ID_STR, -ret);
index 5ec8eddfcf6e6e4db69633c71875005c44812688..f5cedeccad426d8cf2c583cc23efe162ddd26189 100644 (file)
@@ -1875,7 +1875,7 @@ static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
                             unsigned int tot_sz, int max_scatter)
 {
        unsigned int dev_addr, i, cnt, sz, ssz;
-       struct timespec ts1, ts2, ts;
+       struct timespec ts1, ts2;
        int ret;
 
        sz = test->area.max_tfr;
@@ -1912,7 +1912,6 @@ static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
        }
        getnstimeofday(&ts2);
 
-       ts = timespec_sub(ts2, ts1);
        mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
 
        return 0;
index 797cdb5887fd0a7cd0be254f23b4acc843f3ce4d..76af349c14b41e41c8e6de62878ee364c6a61232 100644 (file)
@@ -9,6 +9,7 @@
  * your option) any later version.
  */
 
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/scatterlist.h>
 
@@ -252,6 +253,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
        struct mmc_command cmd;
        struct mmc_data data;
        struct scatterlist sg;
+       void *data_buf;
 
        BUG_ON(!card);
        BUG_ON(!card->host);
@@ -263,6 +265,13 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
        if (err)
                return err;
 
+       /* dma onto stack is unsafe/nonportable, but callers to this
+        * routine normally provide temporary on-stack buffers ...
+        */
+       data_buf = kmalloc(sizeof(card->raw_scr), GFP_KERNEL);
+       if (data_buf == NULL)
+               return -ENOMEM;
+
        memset(&mrq, 0, sizeof(struct mmc_request));
        memset(&cmd, 0, sizeof(struct mmc_command));
        memset(&data, 0, sizeof(struct mmc_data));
@@ -280,12 +289,15 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
        data.sg = &sg;
        data.sg_len = 1;
 
-       sg_init_one(&sg, scr, 8);
+       sg_init_one(&sg, data_buf, 8);
 
        mmc_set_data_timeout(&data, card);
 
        mmc_wait_for_req(card->host, &mrq);
 
+       memcpy(scr, data_buf, sizeof(card->raw_scr));
+       kfree(data_buf);
+
        if (cmd.error)
                return cmd.error;
        if (data.error)
index 1a21c6427a19769c84cb31018c7d745ea5517164..94df40531c38caaa597fc05086b9e14b36f166d5 100644 (file)
@@ -439,13 +439,25 @@ config MMC_SDRICOH_CS
          To compile this driver as a module, choose M here: the
          module will be called sdricoh_cs.
 
+config MMC_TMIO_CORE
+       tristate
+
 config MMC_TMIO
        tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
-       depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI
+       depends on MFD_TMIO || MFD_ASIC3
+       select MMC_TMIO_CORE
        help
          This provides support for the SD/MMC cell found in TC6393XB,
          T7L66XB and also HTC ASIC3
 
+config MMC_SDHI
+       tristate "SH-Mobile SDHI SD/SDIO controller support"
+       depends on SUPERH || ARCH_SHMOBILE
+       select MMC_TMIO_CORE
+       help
+         This provides support for the SDHI SD/SDIO controller found in
+         SuperH and ARM SH-Mobile SoCs
+
 config MMC_CB710
        tristate "ENE CB710 MMC/SD Interface support"
        depends on PCI
index 30aa6867745f442ddbba5bfe219a5881bd8ef053..4f1df0aae574eb429f2f0356d20ffd57a7da1e8d 100644 (file)
@@ -29,7 +29,13 @@ endif
 obj-$(CONFIG_MMC_S3C)          += s3cmci.o
 obj-$(CONFIG_MMC_SDRICOH_CS)   += sdricoh_cs.o
 obj-$(CONFIG_MMC_TMIO)         += tmio_mmc.o
-obj-$(CONFIG_MMC_CB710)        += cb710-mmc.o
+obj-$(CONFIG_MMC_TMIO_CORE)    += tmio_mmc_core.o
+tmio_mmc_core-y                        := tmio_mmc_pio.o
+ifneq ($(CONFIG_MMC_SDHI),n)
+tmio_mmc_core-y                        += tmio_mmc_dma.o
+endif
+obj-$(CONFIG_MMC_SDHI)         += sh_mobile_sdhi.o
+obj-$(CONFIG_MMC_CB710)                += cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)    += via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)         += bfin_sdh.o
 obj-$(CONFIG_MMC_DW)           += dw_mmc.o
index 5a614069cb00b67122d053635897e769972adb0d..87e1f57ec9bae7ea4711c9ddfed81600ce819dcb 100644 (file)
@@ -316,7 +316,7 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
 
        /* Stop the IDMAC running */
        temp = mci_readl(host, BMOD);
-       temp &= ~SDMMC_IDMAC_ENABLE;
+       temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
        mci_writel(host, BMOD, temp);
 }
 
@@ -385,7 +385,7 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 
        /* Enable the IDMAC */
        temp = mci_readl(host, BMOD);
-       temp |= SDMMC_IDMAC_ENABLE;
+       temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB;
        mci_writel(host, BMOD, temp);
 
        /* Start it running */
index 5bbb87d102514b62c25a4c78b50be5c753e51c80..b4a7e4fba90fa2fdb30e78632e09d85a484baff2 100644 (file)
@@ -68,6 +68,12 @@ static struct variant_data variant_arm = {
        .datalength_bits        = 16,
 };
 
+static struct variant_data variant_arm_extended_fifo = {
+       .fifosize               = 128 * 4,
+       .fifohalfsize           = 64 * 4,
+       .datalength_bits        = 16,
+};
+
 static struct variant_data variant_u300 = {
        .fifosize               = 16 * 4,
        .fifohalfsize           = 8 * 4,
@@ -1277,9 +1283,14 @@ static int mmci_resume(struct amba_device *dev)
 static struct amba_id mmci_ids[] = {
        {
                .id     = 0x00041180,
-               .mask   = 0x000fffff,
+               .mask   = 0xff0fffff,
                .data   = &variant_arm,
        },
+       {
+               .id     = 0x01041180,
+               .mask   = 0xff0fffff,
+               .data   = &variant_arm_extended_fifo,
+       },
        {
                .id     = 0x00041181,
                .mask   = 0x000fffff,
index 5530def54e5bbf8a08be34e3ce4ea2534a8802da..e2aecb7f1d5cfe32aab9ffe35aabfbe0ba9a643c 100644 (file)
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/of_irq.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
 #include <linux/mmc/core.h>
index 3b5248567973dc794d2cf1c8232317d118f1727a..a19967d0bfc48b0ce8216de0d1a727093ee9fa03 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-pltfm.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
 #include <mach/hardware.h>
 #include <mach/esdhc.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
+/* VENDOR SPEC register */
+#define SDHCI_VENDOR_SPEC              0xC0
+#define  SDHCI_VENDOR_SPEC_SDIO_QUIRK  0x00000002
+
+#define ESDHC_FLAG_GPIO_FOR_CD_WP      (1 << 0)
+/*
+ * The CMDTYPE of the CMD register (offset 0xE) should be set to
+ * "11" when the STOP CMD12 is issued on imx53 to abort one
+ * open ended multi-blk IO. Otherwise the TC INT wouldn't
+ * be generated.
+ * In exact block transfer, the controller doesn't complete the
+ * operations automatically as required at the end of the
+ * transfer and remains on hold if the abort command is not sent.
+ * As a result, the TC flag is not asserted and SW  received timeout
+ * exeception. Bit1 of Vendor Spec registor is used to fix it.
+ */
+#define ESDHC_FLAG_MULTIBLK_NO_INT     (1 << 1)
+
+struct pltfm_imx_data {
+       int flags;
+       u32 scratchpad;
+};
+
 static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
 {
        void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -34,10 +60,14 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
        /* fake CARD_PRESENT flag on mx25/35 */
        u32 val = readl(host->ioaddr + reg);
 
-       if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+       if (unlikely((reg == SDHCI_PRESENT_STATE)
+                       && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
                struct esdhc_platform_data *boarddata =
                                host->mmc->parent->platform_data;
 
@@ -55,13 +85,26 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 
 static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 {
-       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE))
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+       if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
+                       && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
                /*
                 * these interrupts won't work with a custom card_detect gpio
                 * (only applied to mx25/35)
                 */
                val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
 
+       if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+                               && (reg == SDHCI_INT_STATUS)
+                               && (val & SDHCI_INT_DATA_END))) {
+                       u32 v;
+                       v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+                       v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+                       writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+       }
+
        writel(val, host->ioaddr + reg);
 }
 
@@ -76,6 +119,7 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
        switch (reg) {
        case SDHCI_TRANSFER_MODE:
@@ -83,10 +127,22 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                 * Postpone this write, we must do it together with a
                 * command write that is down below.
                 */
-               pltfm_host->scratchpad = val;
+               if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+                               && (host->cmd->opcode == SD_IO_RW_EXTENDED)
+                               && (host->cmd->data->blocks > 1)
+                               && (host->cmd->data->flags & MMC_DATA_READ)) {
+                       u32 v;
+                       v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+                       v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+                       writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+               }
+               imx_data->scratchpad = val;
                return;
        case SDHCI_COMMAND:
-               writel(val << 16 | pltfm_host->scratchpad,
+               if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
+                       && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+                       val |= SDHCI_CMD_ABORTCMD;
+               writel(val << 16 | imx_data->scratchpad,
                        host->ioaddr + SDHCI_TRANSFER_MODE);
                return;
        case SDHCI_BLOCK_SIZE:
@@ -146,7 +202,9 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
 }
 
 static struct sdhci_ops sdhci_esdhc_ops = {
+       .read_l = esdhc_readl_le,
        .read_w = esdhc_readw_le,
+       .write_l = esdhc_writel_le,
        .write_w = esdhc_writew_le,
        .write_b = esdhc_writeb_le,
        .set_clock = esdhc_set_clock,
@@ -168,6 +226,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
        struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
        struct clk *clk;
        int err;
+       struct pltfm_imx_data *imx_data;
 
        clk = clk_get(mmc_dev(host->mmc), NULL);
        if (IS_ERR(clk)) {
@@ -177,7 +236,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
        clk_enable(clk);
        pltfm_host->clk = clk;
 
-       if (cpu_is_mx35() || cpu_is_mx51())
+       imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+       if (!imx_data) {
+               clk_disable(pltfm_host->clk);
+               clk_put(pltfm_host->clk);
+               return -ENOMEM;
+       }
+       pltfm_host->priv = imx_data;
+
+       if (!cpu_is_mx25())
                host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
        if (cpu_is_mx25() || cpu_is_mx35()) {
@@ -187,6 +254,9 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
                sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
        }
 
+       if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
+               imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
+
        if (boarddata) {
                err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
                if (err) {
@@ -214,8 +284,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
                        goto no_card_detect_irq;
                }
 
-               sdhci_esdhc_ops.write_l = esdhc_writel_le;
-               sdhci_esdhc_ops.read_l = esdhc_readl_le;
+               imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
                /* Now we have a working card_detect again */
                host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
        }
@@ -227,6 +296,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
  no_card_detect_pin:
        boarddata->cd_gpio = err;
  not_supported:
+       kfree(imx_data);
        return 0;
 }
 
@@ -234,6 +304,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
        if (boarddata && gpio_is_valid(boarddata->wp_gpio))
                gpio_free(boarddata->wp_gpio);
@@ -247,6 +318,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
 
        clk_disable(pltfm_host->clk);
        clk_put(pltfm_host->clk);
+       kfree(imx_data);
 }
 
 struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
index c55aae828aac1eb450657da0dac9eafdfd427d4e..c3b08f1119426d66d7f7ee1f4e0d466038631f9d 100644 (file)
@@ -23,8 +23,7 @@
                                SDHCI_QUIRK_NONSTANDARD_CLOCK | \
                                SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
                                SDHCI_QUIRK_PIO_NEEDS_DELAY | \
-                               SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | \
-                               SDHCI_QUIRK_NO_CARD_NO_RESET)
+                               SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
 
 #define ESDHC_SYSTEM_CONTROL   0x2c
 #define ESDHC_CLOCK_MASK       0x0000fff0
index 08161f690ae872320c9799e48774bc5b714eea2a..ba40d6d035c797c096b37f16e7a61a761d05580b 100644 (file)
@@ -74,7 +74,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
 
 struct sdhci_of_data sdhci_esdhc = {
        /* card detection could be handled via GPIO */
-       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+               | SDHCI_QUIRK_NO_CARD_NO_RESET,
        .ops = {
                .read_l = sdhci_be32bs_readl,
                .read_w = esdhc_readw,
index 2f8d46854acd0fb5430ec22ac15ed439ec3b8710..a136be7063478bc9f9f6b130cc92010c47737fc5 100644 (file)
@@ -1016,16 +1016,14 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        struct sdhci_pci_chip *chip;
        struct sdhci_pci_slot *slot;
 
-       u8 slots, rev, first_bar;
+       u8 slots, first_bar;
        int ret, i;
 
        BUG_ON(pdev == NULL);
        BUG_ON(ent == NULL);
 
-       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
-
        dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
-                (int)pdev->vendor, (int)pdev->device, (int)rev);
+                (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
 
        ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
        if (ret)
index ea2e44d9be5e0c4defac9428933e4cc89cae39d0..2b37016ad0acccb67f8fb5540cdf4d6cfe6ae5a5 100644 (file)
@@ -17,7 +17,7 @@
 
 struct sdhci_pltfm_host {
        struct clk *clk;
-       u32 scratchpad; /* to handle quirks across io-accessor calls */
+       void *priv; /* to handle quirks across io-accessor calls */
 };
 
 extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
index d70c54c7b70addca9ef1faab845765c542f10a1d..60a4c97d3d18f9deba2d46abde3cb26e4ffffef4 100644 (file)
@@ -50,7 +50,7 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
        /* val == 1 -> card removed, val == 0 -> card inserted */
        /* if card removed - set irq for low level, else vice versa */
        gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
-       set_irq_type(irq, gpio_irq_type);
+       irq_set_irq_type(irq, gpio_irq_type);
 
        if (sdhci->data->card_power_gpio >= 0) {
                if (!sdhci->data->power_always_enb) {
index 6e0969e40650709c4e785267e63e8c1656f2a7b0..25e8bde600d1e839a3b44caf77558ec8a52d381c 100644 (file)
@@ -45,6 +45,7 @@
 #define  SDHCI_CMD_CRC         0x08
 #define  SDHCI_CMD_INDEX       0x10
 #define  SDHCI_CMD_DATA                0x20
+#define  SDHCI_CMD_ABORTCMD    0xC0
 
 #define  SDHCI_CMD_RESP_NONE   0x00
 #define  SDHCI_CMD_RESP_LONG   0x01
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
new file mode 100644 (file)
index 0000000..cc70123
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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.
+ *
+ * Based on "Compaq ASIC3 support":
+ *
+ * Copyright 2001 Compaq Computer Corporation.
+ * Copyright 2004-2005 Phil Blundell
+ * Copyright 2007-2008 OpenedHand Ltd.
+ *
+ * Authors: Phil Blundell <pb@handhelds.org>,
+ *         Samuel Ortiz <sameo@openedhand.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
+#include <linux/sh_dma.h>
+
+#include "tmio_mmc.h"
+
+struct sh_mobile_sdhi {
+       struct clk *clk;
+       struct tmio_mmc_data mmc_data;
+       struct sh_dmae_slave param_tx;
+       struct sh_dmae_slave param_rx;
+       struct tmio_mmc_dma dma_priv;
+};
+
+static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
+{
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+
+       if (p && p->set_pwr)
+               p->set_pwr(pdev, state);
+}
+
+static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
+{
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+
+       if (p && p->get_cd)
+               return p->get_cd(pdev);
+       else
+               return -ENOSYS;
+}
+
+static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+{
+       struct sh_mobile_sdhi *priv;
+       struct tmio_mmc_data *mmc_data;
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+       struct tmio_mmc_host *host;
+       char clk_name[8];
+       int ret;
+
+       priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
+       if (priv == NULL) {
+               dev_err(&pdev->dev, "kzalloc failed\n");
+               return -ENOMEM;
+       }
+
+       mmc_data = &priv->mmc_data;
+
+       snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
+       priv->clk = clk_get(&pdev->dev, clk_name);
+       if (IS_ERR(priv->clk)) {
+               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+               ret = PTR_ERR(priv->clk);
+               goto eclkget;
+       }
+
+       clk_enable(priv->clk);
+
+       mmc_data->hclk = clk_get_rate(priv->clk);
+       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
+       if (p) {
+               mmc_data->flags = p->tmio_flags;
+               mmc_data->ocr_mask = p->tmio_ocr_mask;
+               mmc_data->capabilities |= p->tmio_caps;
+
+               if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
+                       priv->param_tx.slave_id = p->dma_slave_tx;
+                       priv->param_rx.slave_id = p->dma_slave_rx;
+                       priv->dma_priv.chan_priv_tx = &priv->param_tx;
+                       priv->dma_priv.chan_priv_rx = &priv->param_rx;
+                       priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
+                       mmc_data->dma = &priv->dma_priv;
+               }
+       }
+
+       /*
+        * All SDHI blocks support 2-byte and larger block sizes in 4-bit
+        * bus width mode.
+        */
+       mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES;
+
+       /*
+        * All SDHI blocks support SDIO IRQ signalling.
+        */
+       mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
+
+       ret = tmio_mmc_host_probe(&host, pdev, mmc_data);
+       if (ret < 0)
+               goto eprobe;
+
+       pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
+               (unsigned long)host->ctl, host->irq);
+
+       return ret;
+
+eprobe:
+       clk_disable(priv->clk);
+       clk_put(priv->clk);
+eclkget:
+       kfree(priv);
+       return ret;
+}
+
+static int sh_mobile_sdhi_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+
+       tmio_mmc_host_remove(host);
+       clk_disable(priv->clk);
+       clk_put(priv->clk);
+       kfree(priv);
+
+       return 0;
+}
+
+static struct platform_driver sh_mobile_sdhi_driver = {
+       .driver         = {
+               .name   = "sh_mobile_sdhi",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = sh_mobile_sdhi_probe,
+       .remove         = __devexit_p(sh_mobile_sdhi_remove),
+};
+
+static int __init sh_mobile_sdhi_init(void)
+{
+       return platform_driver_register(&sh_mobile_sdhi_driver);
+}
+
+static void __exit sh_mobile_sdhi_exit(void)
+{
+       platform_driver_unregister(&sh_mobile_sdhi_driver);
+}
+
+module_init(sh_mobile_sdhi_init);
+module_exit(sh_mobile_sdhi_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sh_mobile_sdhi");
index ab1adeabdd224f43e78fec6cbe01dfb1c13f4f45..79c568461d59565b587627237ba6bb6de8950005 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *  linux/drivers/mmc/tmio_mmc.c
+ * linux/drivers/mmc/host/tmio_mmc.c
  *
- *  Copyright (C) 2004 Ian Molton
- *  Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
  *
  * 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
  * Driver for the MMC / SD / SDIO cell found in:
  *
  * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
- *
- * This driver draws mainly on scattered spec sheets, Reverse engineering
- * of the toshiba e800  SD driver and some parts of the 2.4 ASIC3 driver (4 bit
- * support). (Further 4 bit support from a later datasheet).
- *
- * TODO:
- *   Investigate using a workqueue for PIO transfers
- *   Eliminate FIXMEs
- *   SDIO support
- *   Better Power management
- *   Handle MMC errors better
- *   double buffer support
- *
  */
 
-#include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <linux/highmem.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
-#include <linux/workqueue.h>
-#include <linux/spinlock.h>
-
-#define CTL_SD_CMD 0x00
-#define CTL_ARG_REG 0x04
-#define CTL_STOP_INTERNAL_ACTION 0x08
-#define CTL_XFER_BLK_COUNT 0xa
-#define CTL_RESPONSE 0x0c
-#define CTL_STATUS 0x1c
-#define CTL_IRQ_MASK 0x20
-#define CTL_SD_CARD_CLK_CTL 0x24
-#define CTL_SD_XFER_LEN 0x26
-#define CTL_SD_MEM_CARD_OPT 0x28
-#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
-#define CTL_SD_DATA_PORT 0x30
-#define CTL_TRANSACTION_CTL 0x34
-#define CTL_SDIO_STATUS 0x36
-#define CTL_SDIO_IRQ_MASK 0x38
-#define CTL_RESET_SD 0xe0
-#define CTL_SDIO_REGS 0x100
-#define CTL_CLK_AND_WAIT_CTL 0x138
-#define CTL_RESET_SDIO 0x1e0
-
-/* Definitions for values the CTRL_STATUS register can take. */
-#define TMIO_STAT_CMDRESPEND    0x00000001
-#define TMIO_STAT_DATAEND       0x00000004
-#define TMIO_STAT_CARD_REMOVE   0x00000008
-#define TMIO_STAT_CARD_INSERT   0x00000010
-#define TMIO_STAT_SIGSTATE      0x00000020
-#define TMIO_STAT_WRPROTECT     0x00000080
-#define TMIO_STAT_CARD_REMOVE_A 0x00000100
-#define TMIO_STAT_CARD_INSERT_A 0x00000200
-#define TMIO_STAT_SIGSTATE_A    0x00000400
-#define TMIO_STAT_CMD_IDX_ERR   0x00010000
-#define TMIO_STAT_CRCFAIL       0x00020000
-#define TMIO_STAT_STOPBIT_ERR   0x00040000
-#define TMIO_STAT_DATATIMEOUT   0x00080000
-#define TMIO_STAT_RXOVERFLOW    0x00100000
-#define TMIO_STAT_TXUNDERRUN    0x00200000
-#define TMIO_STAT_CMDTIMEOUT    0x00400000
-#define TMIO_STAT_RXRDY         0x01000000
-#define TMIO_STAT_TXRQ          0x02000000
-#define TMIO_STAT_ILL_FUNC      0x20000000
-#define TMIO_STAT_CMD_BUSY      0x40000000
-#define TMIO_STAT_ILL_ACCESS    0x80000000
-
-/* Definitions for values the CTRL_SDIO_STATUS register can take. */
-#define TMIO_SDIO_STAT_IOIRQ   0x0001
-#define TMIO_SDIO_STAT_EXPUB52 0x4000
-#define TMIO_SDIO_STAT_EXWT    0x8000
-#define TMIO_SDIO_MASK_ALL     0xc007
-
-/* Define some IRQ masks */
-/* This is the mask used at reset by the chip */
-#define TMIO_MASK_ALL           0x837f031d
-#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
-#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
-#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
-               TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
-
-#define enable_mmc_irqs(host, i) \
-       do { \
-               u32 mask;\
-               mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-               mask &= ~((i) & TMIO_MASK_IRQ); \
-               sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-       } while (0)
-
-#define disable_mmc_irqs(host, i) \
-       do { \
-               u32 mask;\
-               mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-               mask |= ((i) & TMIO_MASK_IRQ); \
-               sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-       } while (0)
-
-#define ack_mmc_irqs(host, i) \
-       do { \
-               sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
-       } while (0)
-
-/* This is arbitrary, just noone needed any higher alignment yet */
-#define MAX_ALIGN 4
-
-struct tmio_mmc_host {
-       void __iomem *ctl;
-       unsigned long bus_shift;
-       struct mmc_command      *cmd;
-       struct mmc_request      *mrq;
-       struct mmc_data         *data;
-       struct mmc_host         *mmc;
-       int                     irq;
-       unsigned int            sdio_irq_enabled;
-
-       /* Callbacks for clock / power control */
-       void (*set_pwr)(struct platform_device *host, int state);
-       void (*set_clk_div)(struct platform_device *host, int state);
-
-       /* pio related stuff */
-       struct scatterlist      *sg_ptr;
-       struct scatterlist      *sg_orig;
-       unsigned int            sg_len;
-       unsigned int            sg_off;
-
-       struct platform_device *pdev;
-
-       /* DMA support */
-       struct dma_chan         *chan_rx;
-       struct dma_chan         *chan_tx;
-       struct tasklet_struct   dma_complete;
-       struct tasklet_struct   dma_issue;
-#ifdef CONFIG_TMIO_MMC_DMA
-       u8                      bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN)));
-       struct scatterlist      bounce_sg;
-#endif
-
-       /* Track lost interrupts */
-       struct delayed_work     delayed_reset_work;
-       spinlock_t              lock;
-       unsigned long           last_req_ts;
-};
-
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host);
-
-static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
-{
-       return readw(host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
-               u16 *buf, int count)
-{
-       readsw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
-{
-       return readw(host->ctl + (addr << host->bus_shift)) |
-              readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
-}
-
-static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
-{
-       writew(val, host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
-               u16 *buf, int count)
-{
-       writesw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
-{
-       writew(val, host->ctl + (addr << host->bus_shift));
-       writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
-}
-
-static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
-{
-       host->sg_len = data->sg_len;
-       host->sg_ptr = data->sg;
-       host->sg_orig = data->sg;
-       host->sg_off = 0;
-}
-
-static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
-{
-       host->sg_ptr = sg_next(host->sg_ptr);
-       host->sg_off = 0;
-       return --host->sg_len;
-}
-
-static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
-{
-       local_irq_save(*flags);
-       return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static void tmio_mmc_kunmap_atomic(struct scatterlist *sg, unsigned long *flags, void *virt)
-{
-       kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
-       local_irq_restore(*flags);
-}
-
-#ifdef CONFIG_MMC_DEBUG
-
-#define STATUS_TO_TEXT(a, status, i) \
-       do { \
-               if (status & TMIO_STAT_##a) { \
-                       if (i++) \
-                               printk(" | "); \
-                       printk(#a); \
-               } \
-       } while (0)
-
-void pr_debug_status(u32 status)
-{
-       int i = 0;
-       printk(KERN_DEBUG "status: %08x = ", status);
-       STATUS_TO_TEXT(CARD_REMOVE, status, i);
-       STATUS_TO_TEXT(CARD_INSERT, status, i);
-       STATUS_TO_TEXT(SIGSTATE, status, i);
-       STATUS_TO_TEXT(WRPROTECT, status, i);
-       STATUS_TO_TEXT(CARD_REMOVE_A, status, i);
-       STATUS_TO_TEXT(CARD_INSERT_A, status, i);
-       STATUS_TO_TEXT(SIGSTATE_A, status, i);
-       STATUS_TO_TEXT(CMD_IDX_ERR, status, i);
-       STATUS_TO_TEXT(STOPBIT_ERR, status, i);
-       STATUS_TO_TEXT(ILL_FUNC, status, i);
-       STATUS_TO_TEXT(CMD_BUSY, status, i);
-       STATUS_TO_TEXT(CMDRESPEND, status, i);
-       STATUS_TO_TEXT(DATAEND, status, i);
-       STATUS_TO_TEXT(CRCFAIL, status, i);
-       STATUS_TO_TEXT(DATATIMEOUT, status, i);
-       STATUS_TO_TEXT(CMDTIMEOUT, status, i);
-       STATUS_TO_TEXT(RXOVERFLOW, status, i);
-       STATUS_TO_TEXT(TXUNDERRUN, status, i);
-       STATUS_TO_TEXT(RXRDY, status, i);
-       STATUS_TO_TEXT(TXRQ, status, i);
-       STATUS_TO_TEXT(ILL_ACCESS, status, i);
-       printk("\n");
-}
-
-#else
-#define pr_debug_status(s)  do { } while (0)
-#endif
-
-static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-
-       if (enable) {
-               host->sdio_irq_enabled = 1;
-               sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
-               sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
-                       (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
-       } else {
-               sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
-               sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
-               host->sdio_irq_enabled = 0;
-       }
-}
-
-static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
-{
-       u32 clk = 0, clock;
-
-       if (new_clock) {
-               for (clock = host->mmc->f_min, clk = 0x80000080;
-                       new_clock >= (clock<<1); clk >>= 1)
-                       clock <<= 1;
-               clk |= 0x100;
-       }
-
-       if (host->set_clk_div)
-               host->set_clk_div(host->pdev, (clk>>22) & 1);
-
-       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
-}
-
-static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
-{
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-
-       /*
-        * Testing on sh-mobile showed that SDIO IRQs are unmasked when
-        * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the
-        * device IRQ here and restore the SDIO IRQ mask before
-        * re-enabling the device IRQ.
-        */
-       if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-               disable_irq(host->irq);
-       sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
-       msleep(10);
-       if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
-               tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
-               enable_irq(host->irq);
-       }
-       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
-               sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
-       msleep(10);
-}
-
-static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
-{
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-
-       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
-               sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
-       msleep(10);
-       /* see comment in tmio_mmc_clk_stop above */
-       if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-               disable_irq(host->irq);
-       sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
-       msleep(10);
-       if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
-               tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
-               enable_irq(host->irq);
-       }
-}
-
-static void reset(struct tmio_mmc_host *host)
-{
-       /* FIXME - should we set stop clock reg here */
-       sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
-       sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
-       msleep(10);
-       sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
-       sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
-       msleep(10);
-}
-
-static void tmio_mmc_reset_work(struct work_struct *work)
-{
-       struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
-                                                 delayed_reset_work.work);
-       struct mmc_request *mrq;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-       mrq = host->mrq;
-
-       /* request already finished */
-       if (!mrq
-           || time_is_after_jiffies(host->last_req_ts +
-               msecs_to_jiffies(2000))) {
-               spin_unlock_irqrestore(&host->lock, flags);
-               return;
-       }
-
-       dev_warn(&host->pdev->dev,
-               "timeout waiting for hardware interrupt (CMD%u)\n",
-               mrq->cmd->opcode);
-
-       if (host->data)
-               host->data->error = -ETIMEDOUT;
-       else if (host->cmd)
-               host->cmd->error = -ETIMEDOUT;
-       else
-               mrq->cmd->error = -ETIMEDOUT;
-
-       host->cmd = NULL;
-       host->data = NULL;
-       host->mrq = NULL;
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       reset(host);
-
-       mmc_request_done(host->mmc, mrq);
-}
-
-static void
-tmio_mmc_finish_request(struct tmio_mmc_host *host)
-{
-       struct mmc_request *mrq = host->mrq;
-
-       if (!mrq)
-               return;
-
-       host->mrq = NULL;
-       host->cmd = NULL;
-       host->data = NULL;
-
-       cancel_delayed_work(&host->delayed_reset_work);
-
-       mmc_request_done(host->mmc, mrq);
-}
-
-/* These are the bitmasks the tmio chip requires to implement the MMC response
- * types. Note that R1 and R6 are the same in this scheme. */
-#define APP_CMD        0x0040
-#define RESP_NONE      0x0300
-#define RESP_R1        0x0400
-#define RESP_R1B       0x0500
-#define RESP_R2        0x0600
-#define RESP_R3        0x0700
-#define DATA_PRESENT   0x0800
-#define TRANSFER_READ  0x1000
-#define TRANSFER_MULTI 0x2000
-#define SECURITY_CMD   0x4000
-
-static int
-tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
-{
-       struct mmc_data *data = host->data;
-       int c = cmd->opcode;
-
-       /* Command 12 is handled by hardware */
-       if (cmd->opcode == 12 && !cmd->arg) {
-               sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
-               return 0;
-       }
-
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_NONE: c |= RESP_NONE; break;
-       case MMC_RSP_R1:   c |= RESP_R1;   break;
-       case MMC_RSP_R1B:  c |= RESP_R1B;  break;
-       case MMC_RSP_R2:   c |= RESP_R2;   break;
-       case MMC_RSP_R3:   c |= RESP_R3;   break;
-       default:
-               pr_debug("Unknown response type %d\n", mmc_resp_type(cmd));
-               return -EINVAL;
-       }
-
-       host->cmd = cmd;
-
-/* FIXME - this seems to be ok commented out but the spec suggest this bit
- *         should be set when issuing app commands.
- *     if(cmd->flags & MMC_FLAG_ACMD)
- *             c |= APP_CMD;
- */
-       if (data) {
-               c |= DATA_PRESENT;
-               if (data->blocks > 1) {
-                       sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
-                       c |= TRANSFER_MULTI;
-               }
-               if (data->flags & MMC_DATA_READ)
-                       c |= TRANSFER_READ;
-       }
-
-       enable_mmc_irqs(host, TMIO_MASK_CMD);
-
-       /* Fire off the command */
-       sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
-       sd_ctrl_write16(host, CTL_SD_CMD, c);
-
-       return 0;
-}
-
-/*
- * This chip always returns (at least?) as much data as you ask for.
- * I'm unsure what happens if you ask for less than a block. This should be
- * looked into to ensure that a funny length read doesnt hose the controller.
- */
-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;
-
-       if (!data) {
-               pr_debug("Spurious PIO IRQ\n");
-               return;
-       }
-
-       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)
-               count = data->blksz;
-
-       pr_debug("count: %08x offset: %08x flags %08x\n",
-                count, host->sg_off, data->flags);
-
-       /* Transfer the data */
-       if (data->flags & MMC_DATA_READ)
-               sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
-       else
-               sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
-
-       host->sg_off += count;
-
-       tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt);
-
-       if (host->sg_off == host->sg_ptr->length)
-               tmio_mmc_next_sg(host);
-
-       return;
-}
-
-/* needs to be called with host->lock held */
-static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
-{
-       struct mmc_data *data = host->data;
-       struct mmc_command *stop;
-
-       host->data = NULL;
-
-       if (!data) {
-               dev_warn(&host->pdev->dev, "Spurious data end IRQ\n");
-               return;
-       }
-       stop = data->stop;
-
-       /* FIXME - return correct transfer count on errors */
-       if (!data->error)
-               data->bytes_xfered = data->blocks * data->blksz;
-       else
-               data->bytes_xfered = 0;
-
-       pr_debug("Completed data request\n");
-
-       /*
-        * FIXME: other drivers allow an optional stop command of any given type
-        *        which we dont do, as the chip can auto generate them.
-        *        Perhaps we can be smarter about when to use auto CMD12 and
-        *        only issue the auto request when we know this is the desired
-        *        stop command, allowing fallback to the stop command the
-        *        upper layers expect. For now, we do what works.
-        */
-
-       if (data->flags & MMC_DATA_READ) {
-               if (!host->chan_rx)
-                       disable_mmc_irqs(host, TMIO_MASK_READOP);
-               else
-                       tmio_check_bounce_buffer(host);
-               dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
-                       host->mrq);
-       } else {
-               if (!host->chan_tx)
-                       disable_mmc_irqs(host, TMIO_MASK_WRITEOP);
-               dev_dbg(&host->pdev->dev, "Complete Tx request %p\n",
-                       host->mrq);
-       }
-
-       if (stop) {
-               if (stop->opcode == 12 && !stop->arg)
-                       sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
-               else
-                       BUG();
-       }
-
-       tmio_mmc_finish_request(host);
-}
-
-static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
-{
-       struct mmc_data *data;
-       spin_lock(&host->lock);
-       data = host->data;
-
-       if (!data)
-               goto out;
-
-       if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) {
-               /*
-                * Has all data been written out yet? Testing on SuperH showed,
-                * that in most cases the first interrupt comes already with the
-                * BUSY status bit clear, but on some operations, like mount or
-                * in the beginning of a write / sync / umount, there is one
-                * DATAEND interrupt with the BUSY bit set, in this cases
-                * waiting for one more interrupt fixes the problem.
-                */
-               if (!(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_CMD_BUSY)) {
-                       disable_mmc_irqs(host, TMIO_STAT_DATAEND);
-                       tasklet_schedule(&host->dma_complete);
-               }
-       } else if (host->chan_rx && (data->flags & MMC_DATA_READ)) {
-               disable_mmc_irqs(host, TMIO_STAT_DATAEND);
-               tasklet_schedule(&host->dma_complete);
-       } else {
-               tmio_mmc_do_data_irq(host);
-       }
-out:
-       spin_unlock(&host->lock);
-}
-
-static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
-       unsigned int stat)
-{
-       struct mmc_command *cmd = host->cmd;
-       int i, addr;
-
-       spin_lock(&host->lock);
-
-       if (!host->cmd) {
-               pr_debug("Spurious CMD irq\n");
-               goto out;
-       }
-
-       host->cmd = NULL;
-
-       /* This controller is sicker than the PXA one. Not only do we need to
-        * drop the top 8 bits of the first response word, we also need to
-        * modify the order of the response for short response command types.
-        */
-
-       for (i = 3, addr = CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
-               cmd->resp[i] = sd_ctrl_read32(host, addr);
-
-       if (cmd->flags &  MMC_RSP_136) {
-               cmd->resp[0] = (cmd->resp[0] << 8) | (cmd->resp[1] >> 24);
-               cmd->resp[1] = (cmd->resp[1] << 8) | (cmd->resp[2] >> 24);
-               cmd->resp[2] = (cmd->resp[2] << 8) | (cmd->resp[3] >> 24);
-               cmd->resp[3] <<= 8;
-       } else if (cmd->flags & MMC_RSP_R3) {
-               cmd->resp[0] = cmd->resp[3];
-       }
-
-       if (stat & TMIO_STAT_CMDTIMEOUT)
-               cmd->error = -ETIMEDOUT;
-       else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
-               cmd->error = -EILSEQ;
-
-       /* If there is data to handle we enable data IRQs here, and
-        * we will ultimatley finish the request in the data_end handler.
-        * If theres no data or we encountered an error, finish now.
-        */
-       if (host->data && !cmd->error) {
-               if (host->data->flags & MMC_DATA_READ) {
-                       if (!host->chan_rx)
-                               enable_mmc_irqs(host, TMIO_MASK_READOP);
-               } else {
-                       if (!host->chan_tx)
-                               enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
-                       else
-                               tasklet_schedule(&host->dma_issue);
-               }
-       } else {
-               tmio_mmc_finish_request(host);
-       }
-
-out:
-       spin_unlock(&host->lock);
-
-       return;
-}
-
-static irqreturn_t tmio_mmc_irq(int irq, void *devid)
-{
-       struct tmio_mmc_host *host = devid;
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-       unsigned int ireg, irq_mask, status;
-       unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
-
-       pr_debug("MMC IRQ begin\n");
-
-       status = sd_ctrl_read32(host, CTL_STATUS);
-       irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
-       ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-
-       sdio_ireg = 0;
-       if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
-               sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
-               sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
-               sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
-
-               sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
-
-               if (sdio_ireg && !host->sdio_irq_enabled) {
-                       pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
-                                  sdio_status, sdio_irq_mask, sdio_ireg);
-                       tmio_mmc_enable_sdio_irq(host->mmc, 0);
-                       goto out;
-               }
 
-               if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
-                       sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
-                       mmc_signal_sdio_irq(host->mmc);
-
-               if (sdio_ireg)
-                       goto out;
-       }
-
-       pr_debug_status(status);
-       pr_debug_status(ireg);
-
-       if (!ireg) {
-               disable_mmc_irqs(host, status & ~irq_mask);
-
-               pr_warning("tmio_mmc: Spurious irq, disabling! "
-                       "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
-               pr_debug_status(status);
-
-               goto out;
-       }
-
-       while (ireg) {
-               /* Card insert / remove attempts */
-               if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
-                       ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
-                               TMIO_STAT_CARD_REMOVE);
-                       mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-               }
-
-               /* CRC and other errors */
-/*             if (ireg & TMIO_STAT_ERR_IRQ)
- *                     handled |= tmio_error_irq(host, irq, stat);
- */
-
-               /* Command completion */
-               if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
-                       ack_mmc_irqs(host,
-                                    TMIO_STAT_CMDRESPEND |
-                                    TMIO_STAT_CMDTIMEOUT);
-                       tmio_mmc_cmd_irq(host, status);
-               }
-
-               /* Data transfer */
-               if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
-                       ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
-                       tmio_mmc_pio_irq(host);
-               }
-
-               /* Data transfer completion */
-               if (ireg & TMIO_STAT_DATAEND) {
-                       ack_mmc_irqs(host, TMIO_STAT_DATAEND);
-                       tmio_mmc_data_irq(host);
-               }
-
-               /* Check status - keep going until we've handled it all */
-               status = sd_ctrl_read32(host, CTL_STATUS);
-               irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
-               ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-
-               pr_debug("Status at end of loop: %08x\n", status);
-               pr_debug_status(status);
-       }
-       pr_debug("MMC IRQ end\n");
-
-out:
-       return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_TMIO_MMC_DMA
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
-{
-       if (host->sg_ptr == &host->bounce_sg) {
-               unsigned long flags;
-               void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
-               memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
-               tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr);
-       }
-}
-
-static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
-{
-#if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
-       /* Switch DMA mode on or off - SuperH specific? */
-       sd_ctrl_write16(host, 0xd8, enable ? 2 : 0);
-#endif
-}
-
-static void tmio_dma_complete(void *arg)
-{
-       struct tmio_mmc_host *host = arg;
-
-       dev_dbg(&host->pdev->dev, "Command completed\n");
-
-       if (!host->data)
-               dev_warn(&host->pdev->dev, "NULL data in DMA completion!\n");
-       else
-               enable_mmc_irqs(host, TMIO_STAT_DATAEND);
-}
-
-static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
-{
-       struct scatterlist *sg = host->sg_ptr, *sg_tmp;
-       struct dma_async_tx_descriptor *desc = NULL;
-       struct dma_chan *chan = host->chan_rx;
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-       dma_cookie_t cookie;
-       int ret, i;
-       bool aligned = true, multiple = true;
-       unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
-
-       for_each_sg(sg, sg_tmp, host->sg_len, i) {
-               if (sg_tmp->offset & align)
-                       aligned = false;
-               if (sg_tmp->length & align) {
-                       multiple = false;
-                       break;
-               }
-       }
-
-       if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
-                         align >= MAX_ALIGN)) || !multiple) {
-               ret = -EINVAL;
-               goto pio;
-       }
-
-       /* The only sg element can be unaligned, use our bounce buffer then */
-       if (!aligned) {
-               sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
-               host->sg_ptr = &host->bounce_sg;
-               sg = host->sg_ptr;
-       }
-
-       ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
-       if (ret > 0)
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (desc) {
-               desc->callback = tmio_dma_complete;
-               desc->callback_param = host;
-               cookie = dmaengine_submit(desc);
-               dma_async_issue_pending(chan);
-       }
-       dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-               __func__, host->sg_len, ret, cookie, host->mrq);
-
-pio:
-       if (!desc) {
-               /* DMA failed, fall back to PIO */
-               if (ret >= 0)
-                       ret = -EIO;
-               host->chan_rx = NULL;
-               dma_release_channel(chan);
-               /* Free the Tx channel too */
-               chan = host->chan_tx;
-               if (chan) {
-                       host->chan_tx = NULL;
-                       dma_release_channel(chan);
-               }
-               dev_warn(&host->pdev->dev,
-                        "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
-       }
-
-       dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
-               desc, cookie, host->sg_len);
-}
-
-static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
-{
-       struct scatterlist *sg = host->sg_ptr, *sg_tmp;
-       struct dma_async_tx_descriptor *desc = NULL;
-       struct dma_chan *chan = host->chan_tx;
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-       dma_cookie_t cookie;
-       int ret, i;
-       bool aligned = true, multiple = true;
-       unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
-
-       for_each_sg(sg, sg_tmp, host->sg_len, i) {
-               if (sg_tmp->offset & align)
-                       aligned = false;
-               if (sg_tmp->length & align) {
-                       multiple = false;
-                       break;
-               }
-       }
-
-       if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
-                         align >= MAX_ALIGN)) || !multiple) {
-               ret = -EINVAL;
-               goto pio;
-       }
-
-       /* The only sg element can be unaligned, use our bounce buffer then */
-       if (!aligned) {
-               unsigned long flags;
-               void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
-               sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
-               memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
-               tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr);
-               host->sg_ptr = &host->bounce_sg;
-               sg = host->sg_ptr;
-       }
-
-       ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
-       if (ret > 0)
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (desc) {
-               desc->callback = tmio_dma_complete;
-               desc->callback_param = host;
-               cookie = dmaengine_submit(desc);
-       }
-       dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-               __func__, host->sg_len, ret, cookie, host->mrq);
-
-pio:
-       if (!desc) {
-               /* DMA failed, fall back to PIO */
-               if (ret >= 0)
-                       ret = -EIO;
-               host->chan_tx = NULL;
-               dma_release_channel(chan);
-               /* Free the Rx channel too */
-               chan = host->chan_rx;
-               if (chan) {
-                       host->chan_rx = NULL;
-                       dma_release_channel(chan);
-               }
-               dev_warn(&host->pdev->dev,
-                        "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
-       }
-
-       dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
-               desc, cookie);
-}
-
-static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
-                              struct mmc_data *data)
-{
-       if (data->flags & MMC_DATA_READ) {
-               if (host->chan_rx)
-                       tmio_mmc_start_dma_rx(host);
-       } else {
-               if (host->chan_tx)
-                       tmio_mmc_start_dma_tx(host);
-       }
-}
-
-static void tmio_issue_tasklet_fn(unsigned long priv)
-{
-       struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
-       struct dma_chan *chan = host->chan_tx;
-
-       dma_async_issue_pending(chan);
-}
-
-static void tmio_tasklet_fn(unsigned long arg)
-{
-       struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (!host->data)
-               goto out;
-
-       if (host->data->flags & MMC_DATA_READ)
-               dma_unmap_sg(host->chan_rx->device->dev,
-                            host->sg_ptr, host->sg_len,
-                            DMA_FROM_DEVICE);
-       else
-               dma_unmap_sg(host->chan_tx->device->dev,
-                            host->sg_ptr, host->sg_len,
-                            DMA_TO_DEVICE);
-
-       tmio_mmc_do_data_irq(host);
-out:
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-/* It might be necessary to make filter MFD specific */
-static bool tmio_mmc_filter(struct dma_chan *chan, void *arg)
-{
-       dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
-       chan->private = arg;
-       return true;
-}
-
-static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
-                                struct tmio_mmc_data *pdata)
-{
-       /* We can only either use DMA for both Tx and Rx or not use it at all */
-       if (pdata->dma) {
-               dma_cap_mask_t mask;
-
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-
-               host->chan_tx = dma_request_channel(mask, tmio_mmc_filter,
-                                                   pdata->dma->chan_priv_tx);
-               dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__,
-                       host->chan_tx);
-
-               if (!host->chan_tx)
-                       return;
-
-               host->chan_rx = dma_request_channel(mask, tmio_mmc_filter,
-                                                   pdata->dma->chan_priv_rx);
-               dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__,
-                       host->chan_rx);
-
-               if (!host->chan_rx) {
-                       dma_release_channel(host->chan_tx);
-                       host->chan_tx = NULL;
-                       return;
-               }
-
-               tasklet_init(&host->dma_complete, tmio_tasklet_fn, (unsigned long)host);
-               tasklet_init(&host->dma_issue, tmio_issue_tasklet_fn, (unsigned long)host);
-
-               tmio_mmc_enable_dma(host, true);
-       }
-}
-
-static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
-{
-       if (host->chan_tx) {
-               struct dma_chan *chan = host->chan_tx;
-               host->chan_tx = NULL;
-               dma_release_channel(chan);
-       }
-       if (host->chan_rx) {
-               struct dma_chan *chan = host->chan_rx;
-               host->chan_rx = NULL;
-               dma_release_channel(chan);
-       }
-}
-#else
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
-{
-}
-
-static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
-                              struct mmc_data *data)
-{
-}
-
-static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
-                                struct tmio_mmc_data *pdata)
-{
-       host->chan_tx = NULL;
-       host->chan_rx = NULL;
-}
-
-static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
-{
-}
-#endif
-
-static int tmio_mmc_start_data(struct tmio_mmc_host *host,
-       struct mmc_data *data)
-{
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-
-       pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
-                data->blksz, data->blocks);
-
-       /* Some hardware cannot perform 2 byte requests in 4 bit mode */
-       if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
-               int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
-
-               if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
-                       pr_err("%s: %d byte block unsupported in 4 bit mode\n",
-                              mmc_hostname(host->mmc), data->blksz);
-                       return -EINVAL;
-               }
-       }
-
-       tmio_mmc_init_sg(host, data);
-       host->data = data;
-
-       /* Set transfer length / blocksize */
-       sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
-       sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
-
-       tmio_mmc_start_dma(host, data);
-
-       return 0;
-}
-
-/* Process requests from the MMC layer */
-static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-       int ret;
-
-       if (host->mrq)
-               pr_debug("request not null\n");
-
-       host->last_req_ts = jiffies;
-       wmb();
-       host->mrq = mrq;
-
-       if (mrq->data) {
-               ret = tmio_mmc_start_data(host, mrq->data);
-               if (ret)
-                       goto fail;
-       }
-
-       ret = tmio_mmc_start_command(host, mrq->cmd);
-       if (!ret) {
-               schedule_delayed_work(&host->delayed_reset_work,
-                                     msecs_to_jiffies(2000));
-               return;
-       }
-
-fail:
-       host->mrq = NULL;
-       mrq->cmd->error = ret;
-       mmc_request_done(mmc, mrq);
-}
-
-/* Set MMC clock / power.
- * Note: This controller uses a simple divider scheme therefore it cannot
- * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
- * MMC wont run that fast, it has to be clocked at 12MHz which is the next
- * slowest setting.
- */
-static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-
-       if (ios->clock)
-               tmio_mmc_set_clock(host, ios->clock);
-
-       /* Power sequence - OFF -> ON -> UP */
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF: /* power down SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 0);
-               tmio_mmc_clk_stop(host);
-               break;
-       case MMC_POWER_ON: /* power up SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 1);
-               break;
-       case MMC_POWER_UP: /* start bus clock */
-               tmio_mmc_clk_start(host);
-               break;
-       }
-
-       switch (ios->bus_width) {
-       case MMC_BUS_WIDTH_1:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-       break;
-       case MMC_BUS_WIDTH_4:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-       break;
-       }
-
-       /* Let things settle. delay taken from winCE driver */
-       udelay(140);
-}
-
-static int tmio_mmc_get_ro(struct mmc_host *mmc)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-
-       return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
-               (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1;
-}
-
-static int tmio_mmc_get_cd(struct mmc_host *mmc)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-       struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
-
-       if (!pdata->get_cd)
-               return -ENOSYS;
-       else
-               return pdata->get_cd(host->pdev);
-}
-
-static const struct mmc_host_ops tmio_mmc_ops = {
-       .request        = tmio_mmc_request,
-       .set_ios        = tmio_mmc_set_ios,
-       .get_ro         = tmio_mmc_get_ro,
-       .get_cd         = tmio_mmc_get_cd,
-       .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
-};
+#include "tmio_mmc.h"
 
 #ifdef CONFIG_PM
 static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
@@ -1227,138 +62,54 @@ out:
 #define tmio_mmc_resume NULL
 #endif
 
-static int __devinit tmio_mmc_probe(struct platform_device *dev)
+static int __devinit tmio_mmc_probe(struct platform_device *pdev)
 {
-       const struct mfd_cell *cell = mfd_get_cell(dev);
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
        struct tmio_mmc_data *pdata;
-       struct resource *res_ctl;
        struct tmio_mmc_host *host;
-       struct mmc_host *mmc;
        int ret = -EINVAL;
-       u32 irq_mask = TMIO_MASK_CMD;
 
-       if (dev->num_resources != 2)
+       if (pdev->num_resources != 2)
                goto out;
 
-       res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res_ctl)
-               goto out;
-
-       pdata = mfd_get_data(dev);
+       pdata = mfd_get_data(pdev);
        if (!pdata || !pdata->hclk)
                goto out;
 
-       ret = -ENOMEM;
-
-       mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
-       if (!mmc)
-               goto out;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-       host->pdev = dev;
-       platform_set_drvdata(dev, mmc);
-
-       host->set_pwr = pdata->set_pwr;
-       host->set_clk_div = pdata->set_clk_div;
-
-       /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
-       host->bus_shift = resource_size(res_ctl) >> 10;
-
-       host->ctl = ioremap(res_ctl->start, resource_size(res_ctl));
-       if (!host->ctl)
-               goto host_free;
-
-       mmc->ops = &tmio_mmc_ops;
-       mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-       mmc->f_max = pdata->hclk;
-       mmc->f_min = mmc->f_max / 512;
-       mmc->max_segs = 32;
-       mmc->max_blk_size = 512;
-       mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
-               mmc->max_segs;
-       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-       mmc->max_seg_size = mmc->max_req_size;
-       if (pdata->ocr_mask)
-               mmc->ocr_avail = pdata->ocr_mask;
-       else
-               mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-
        /* Tell the MFD core we are ready to be enabled */
        if (cell->enable) {
-               ret = cell->enable(dev);
+               ret = cell->enable(pdev);
                if (ret)
-                       goto unmap_ctl;
+                       goto out;
        }
 
-       tmio_mmc_clk_stop(host);
-       reset(host);
-
-       ret = platform_get_irq(dev, 0);
-       if (ret >= 0)
-               host->irq = ret;
-       else
-               goto cell_disable;
-
-       disable_mmc_irqs(host, TMIO_MASK_ALL);
-       if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-               tmio_mmc_enable_sdio_irq(mmc, 0);
-
-       ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
-               IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
+       ret = tmio_mmc_host_probe(&host, pdev, pdata);
        if (ret)
                goto cell_disable;
 
-       spin_lock_init(&host->lock);
-
-       /* Init delayed work for request timeouts */
-       INIT_DELAYED_WORK(&host->delayed_reset_work, tmio_mmc_reset_work);
-
-       /* See if we also get DMA */
-       tmio_mmc_request_dma(host, pdata);
-
-       mmc_add_host(mmc);
-
        pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
                (unsigned long)host->ctl, host->irq);
 
-       /* Unmask the IRQs we want to know about */
-       if (!host->chan_rx)
-               irq_mask |= TMIO_MASK_READOP;
-       if (!host->chan_tx)
-               irq_mask |= TMIO_MASK_WRITEOP;
-       enable_mmc_irqs(host, irq_mask);
-
        return 0;
 
 cell_disable:
        if (cell->disable)
-               cell->disable(dev);
-unmap_ctl:
-       iounmap(host->ctl);
-host_free:
-       mmc_free_host(mmc);
+               cell->disable(pdev);
 out:
        return ret;
 }
 
-static int __devexit tmio_mmc_remove(struct platform_device *dev)
+static int __devexit tmio_mmc_remove(struct platform_device *pdev)
 {
-       const struct mfd_cell *cell = mfd_get_cell(dev);
-       struct mmc_host *mmc = platform_get_drvdata(dev);
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
 
-       platform_set_drvdata(dev, NULL);
+       platform_set_drvdata(pdev, NULL);
 
        if (mmc) {
-               struct tmio_mmc_host *host = mmc_priv(mmc);
-               mmc_remove_host(mmc);
-               cancel_delayed_work_sync(&host->delayed_reset_work);
-               tmio_mmc_release_dma(host);
-               free_irq(host->irq, host);
+               tmio_mmc_host_remove(mmc_priv(mmc));
                if (cell->disable)
-                       cell->disable(dev);
-               iounmap(host->ctl);
-               mmc_free_host(mmc);
+                       cell->disable(pdev);
        }
 
        return 0;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
new file mode 100644 (file)
index 0000000..099ed49
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * linux/drivers/mmc/host/tmio_mmc.h
+ *
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
+ *
+ * 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.
+ *
+ * Driver for the MMC / SD / SDIO cell found in:
+ *
+ * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
+ */
+
+#ifndef TMIO_MMC_H
+#define TMIO_MMC_H
+
+#include <linux/highmem.h>
+#include <linux/mmc/tmio.h>
+#include <linux/pagemap.h>
+
+/* Definitions for values the CTRL_SDIO_STATUS register can take. */
+#define TMIO_SDIO_STAT_IOIRQ   0x0001
+#define TMIO_SDIO_STAT_EXPUB52 0x4000
+#define TMIO_SDIO_STAT_EXWT    0x8000
+#define TMIO_SDIO_MASK_ALL     0xc007
+
+/* Define some IRQ masks */
+/* This is the mask used at reset by the chip */
+#define TMIO_MASK_ALL           0x837f031d
+#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
+#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
+               TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
+#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
+
+struct tmio_mmc_data;
+
+struct tmio_mmc_host {
+       void __iomem *ctl;
+       unsigned long bus_shift;
+       struct mmc_command      *cmd;
+       struct mmc_request      *mrq;
+       struct mmc_data         *data;
+       struct mmc_host         *mmc;
+       int                     irq;
+       unsigned int            sdio_irq_enabled;
+
+       /* Callbacks for clock / power control */
+       void (*set_pwr)(struct platform_device *host, int state);
+       void (*set_clk_div)(struct platform_device *host, int state);
+
+       /* pio related stuff */
+       struct scatterlist      *sg_ptr;
+       struct scatterlist      *sg_orig;
+       unsigned int            sg_len;
+       unsigned int            sg_off;
+
+       struct platform_device *pdev;
+       struct tmio_mmc_data *pdata;
+
+       /* DMA support */
+       bool                    force_pio;
+       struct dma_chan         *chan_rx;
+       struct dma_chan         *chan_tx;
+       struct tasklet_struct   dma_complete;
+       struct tasklet_struct   dma_issue;
+       struct scatterlist      bounce_sg;
+       u8                      *bounce_buf;
+
+       /* Track lost interrupts */
+       struct delayed_work     delayed_reset_work;
+       spinlock_t              lock;
+       unsigned long           last_req_ts;
+};
+
+int tmio_mmc_host_probe(struct tmio_mmc_host **host,
+                       struct platform_device *pdev,
+                       struct tmio_mmc_data *pdata);
+void tmio_mmc_host_remove(struct tmio_mmc_host *host);
+void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
+
+void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
+void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
+
+static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
+                                        unsigned long *flags)
+{
+       local_irq_save(*flags);
+       return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
+                                         unsigned long *flags, void *virt)
+{
+       kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
+       local_irq_restore(*flags);
+}
+
+#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
+void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
+void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
+void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+#else
+static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
+                              struct mmc_data *data)
+{
+}
+
+static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
+                                struct tmio_mmc_data *pdata)
+{
+       host->chan_tx = NULL;
+       host->chan_rx = NULL;
+}
+
+static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
new file mode 100644 (file)
index 0000000..d3de74a
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * linux/drivers/mmc/tmio_mmc_dma.c
+ *
+ * Copyright (C) 2010-2011 Guennadi Liakhovetski
+ *
+ * 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.
+ *
+ * DMA function for TMIO MMC implementations
+ */
+
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/tmio.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+
+#include "tmio_mmc.h"
+
+#define TMIO_MMC_MIN_DMA_LEN 8
+
+static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+{
+#if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
+       /* Switch DMA mode on or off - SuperH specific? */
+       writew(enable ? 2 : 0, host->ctl + (0xd8 << host->bus_shift));
+#endif
+}
+
+static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
+{
+       struct scatterlist *sg = host->sg_ptr, *sg_tmp;
+       struct dma_async_tx_descriptor *desc = NULL;
+       struct dma_chan *chan = host->chan_rx;
+       struct tmio_mmc_data *pdata = host->pdata;
+       dma_cookie_t cookie;
+       int ret, i;
+       bool aligned = true, multiple = true;
+       unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+       for_each_sg(sg, sg_tmp, host->sg_len, i) {
+               if (sg_tmp->offset & align)
+                       aligned = false;
+               if (sg_tmp->length & align) {
+                       multiple = false;
+                       break;
+               }
+       }
+
+       if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+                         (align & PAGE_MASK))) || !multiple) {
+               ret = -EINVAL;
+               goto pio;
+       }
+
+       if (sg->length < TMIO_MMC_MIN_DMA_LEN) {
+               host->force_pio = true;
+               return;
+       }
+
+       tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_RXRDY);
+
+       /* The only sg element can be unaligned, use our bounce buffer then */
+       if (!aligned) {
+               sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+               host->sg_ptr = &host->bounce_sg;
+               sg = host->sg_ptr;
+       }
+
+       ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
+       if (ret > 0)
+               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+                       DMA_FROM_DEVICE, DMA_CTRL_ACK);
+
+       if (desc) {
+               cookie = dmaengine_submit(desc);
+               if (cookie < 0) {
+                       desc = NULL;
+                       ret = cookie;
+               }
+       }
+       dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
+               __func__, host->sg_len, ret, cookie, host->mrq);
+
+pio:
+       if (!desc) {
+               /* DMA failed, fall back to PIO */
+               if (ret >= 0)
+                       ret = -EIO;
+               host->chan_rx = NULL;
+               dma_release_channel(chan);
+               /* Free the Tx channel too */
+               chan = host->chan_tx;
+               if (chan) {
+                       host->chan_tx = NULL;
+                       dma_release_channel(chan);
+               }
+               dev_warn(&host->pdev->dev,
+                        "DMA failed: %d, falling back to PIO\n", ret);
+               tmio_mmc_enable_dma(host, false);
+       }
+
+       dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
+               desc, cookie, host->sg_len);
+}
+
+static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
+{
+       struct scatterlist *sg = host->sg_ptr, *sg_tmp;
+       struct dma_async_tx_descriptor *desc = NULL;
+       struct dma_chan *chan = host->chan_tx;
+       struct tmio_mmc_data *pdata = host->pdata;
+       dma_cookie_t cookie;
+       int ret, i;
+       bool aligned = true, multiple = true;
+       unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+       for_each_sg(sg, sg_tmp, host->sg_len, i) {
+               if (sg_tmp->offset & align)
+                       aligned = false;
+               if (sg_tmp->length & align) {
+                       multiple = false;
+                       break;
+               }
+       }
+
+       if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+                         (align & PAGE_MASK))) || !multiple) {
+               ret = -EINVAL;
+               goto pio;
+       }
+
+       if (sg->length < TMIO_MMC_MIN_DMA_LEN) {
+               host->force_pio = true;
+               return;
+       }
+
+       tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_TXRQ);
+
+       /* The only sg element can be unaligned, use our bounce buffer then */
+       if (!aligned) {
+               unsigned long flags;
+               void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
+               sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+               memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
+               tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr);
+               host->sg_ptr = &host->bounce_sg;
+               sg = host->sg_ptr;
+       }
+
+       ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
+       if (ret > 0)
+               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+                       DMA_TO_DEVICE, DMA_CTRL_ACK);
+
+       if (desc) {
+               cookie = dmaengine_submit(desc);
+               if (cookie < 0) {
+                       desc = NULL;
+                       ret = cookie;
+               }
+       }
+       dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
+               __func__, host->sg_len, ret, cookie, host->mrq);
+
+pio:
+       if (!desc) {
+               /* DMA failed, fall back to PIO */
+               if (ret >= 0)
+                       ret = -EIO;
+               host->chan_tx = NULL;
+               dma_release_channel(chan);
+               /* Free the Rx channel too */
+               chan = host->chan_rx;
+               if (chan) {
+                       host->chan_rx = NULL;
+                       dma_release_channel(chan);
+               }
+               dev_warn(&host->pdev->dev,
+                        "DMA failed: %d, falling back to PIO\n", ret);
+               tmio_mmc_enable_dma(host, false);
+       }
+
+       dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
+               desc, cookie);
+}
+
+void tmio_mmc_start_dma(struct tmio_mmc_host *host,
+                              struct mmc_data *data)
+{
+       if (data->flags & MMC_DATA_READ) {
+               if (host->chan_rx)
+                       tmio_mmc_start_dma_rx(host);
+       } else {
+               if (host->chan_tx)
+                       tmio_mmc_start_dma_tx(host);
+       }
+}
+
+static void tmio_mmc_issue_tasklet_fn(unsigned long priv)
+{
+       struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
+       struct dma_chan *chan = NULL;
+
+       spin_lock_irq(&host->lock);
+
+       if (host && host->data) {
+               if (host->data->flags & MMC_DATA_READ)
+                       chan = host->chan_rx;
+               else
+                       chan = host->chan_tx;
+       }
+
+       spin_unlock_irq(&host->lock);
+
+       tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND);
+
+       if (chan)
+               dma_async_issue_pending(chan);
+}
+
+static void tmio_mmc_tasklet_fn(unsigned long arg)
+{
+       struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+
+       spin_lock_irq(&host->lock);
+
+       if (!host->data)
+               goto out;
+
+       if (host->data->flags & MMC_DATA_READ)
+               dma_unmap_sg(host->chan_rx->device->dev,
+                            host->sg_ptr, host->sg_len,
+                            DMA_FROM_DEVICE);
+       else
+               dma_unmap_sg(host->chan_tx->device->dev,
+                            host->sg_ptr, host->sg_len,
+                            DMA_TO_DEVICE);
+
+       tmio_mmc_do_data_irq(host);
+out:
+       spin_unlock_irq(&host->lock);
+}
+
+/* It might be necessary to make filter MFD specific */
+static bool tmio_mmc_filter(struct dma_chan *chan, void *arg)
+{
+       dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
+       chan->private = arg;
+       return true;
+}
+
+void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata)
+{
+       /* We can only either use DMA for both Tx and Rx or not use it at all */
+       if (pdata->dma) {
+               dma_cap_mask_t mask;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+
+               host->chan_tx = dma_request_channel(mask, tmio_mmc_filter,
+                                                   pdata->dma->chan_priv_tx);
+               dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__,
+                       host->chan_tx);
+
+               if (!host->chan_tx)
+                       return;
+
+               host->chan_rx = dma_request_channel(mask, tmio_mmc_filter,
+                                                   pdata->dma->chan_priv_rx);
+               dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__,
+                       host->chan_rx);
+
+               if (!host->chan_rx)
+                       goto ereqrx;
+
+               host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA);
+               if (!host->bounce_buf)
+                       goto ebouncebuf;
+
+               tasklet_init(&host->dma_complete, tmio_mmc_tasklet_fn, (unsigned long)host);
+               tasklet_init(&host->dma_issue, tmio_mmc_issue_tasklet_fn, (unsigned long)host);
+
+               tmio_mmc_enable_dma(host, true);
+
+               return;
+ebouncebuf:
+               dma_release_channel(host->chan_rx);
+               host->chan_rx = NULL;
+ereqrx:
+               dma_release_channel(host->chan_tx);
+               host->chan_tx = NULL;
+               return;
+       }
+}
+
+void tmio_mmc_release_dma(struct tmio_mmc_host *host)
+{
+       if (host->chan_tx) {
+               struct dma_chan *chan = host->chan_tx;
+               host->chan_tx = NULL;
+               dma_release_channel(chan);
+       }
+       if (host->chan_rx) {
+               struct dma_chan *chan = host->chan_rx;
+               host->chan_rx = NULL;
+               dma_release_channel(chan);
+       }
+       if (host->bounce_buf) {
+               free_pages((unsigned long)host->bounce_buf, 0);
+               host->bounce_buf = NULL;
+       }
+}
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
new file mode 100644 (file)
index 0000000..6ae8d2f
--- /dev/null
@@ -0,0 +1,897 @@
+/*
+ * linux/drivers/mmc/host/tmio_mmc_pio.c
+ *
+ * Copyright (C) 2011 Guennadi Liakhovetski
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
+ *
+ * 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.
+ *
+ * Driver for the MMC / SD / SDIO IP found in:
+ *
+ * TC6393XB, TC6391XB, TC6387XB, T7L66XB, ASIC3, SH-Mobile SoCs
+ *
+ * This driver draws mainly on scattered spec sheets, Reverse engineering
+ * of the toshiba e800  SD driver and some parts of the 2.4 ASIC3 driver (4 bit
+ * support). (Further 4 bit support from a later datasheet).
+ *
+ * TODO:
+ *   Investigate using a workqueue for PIO transfers
+ *   Eliminate FIXMEs
+ *   SDIO support
+ *   Better Power management
+ *   Handle MMC errors better
+ *   double buffer support
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/tmio.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+
+#include "tmio_mmc.h"
+
+static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+       return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+               u16 *buf, int count)
+{
+       readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+       return readw(host->ctl + (addr << host->bus_shift)) |
+              readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
+{
+       writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+               u16 *buf, int count)
+{
+       writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+       writew(val, host->ctl + (addr << host->bus_shift));
+       writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+       u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ);
+       sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+}
+
+void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+       u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) | (i & TMIO_MASK_IRQ);
+       sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+}
+
+static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+       sd_ctrl_write32(host, CTL_STATUS, ~i);
+}
+
+static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
+{
+       host->sg_len = data->sg_len;
+       host->sg_ptr = data->sg;
+       host->sg_orig = data->sg;
+       host->sg_off = 0;
+}
+
+static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
+{
+       host->sg_ptr = sg_next(host->sg_ptr);
+       host->sg_off = 0;
+       return --host->sg_len;
+}
+
+#ifdef CONFIG_MMC_DEBUG
+
+#define STATUS_TO_TEXT(a, status, i) \
+       do { \
+               if (status & TMIO_STAT_##a) { \
+                       if (i++) \
+                               printk(" | "); \
+                       printk(#a); \
+               } \
+       } while (0)
+
+static void pr_debug_status(u32 status)
+{
+       int i = 0;
+       printk(KERN_DEBUG "status: %08x = ", status);
+       STATUS_TO_TEXT(CARD_REMOVE, status, i);
+       STATUS_TO_TEXT(CARD_INSERT, status, i);
+       STATUS_TO_TEXT(SIGSTATE, status, i);
+       STATUS_TO_TEXT(WRPROTECT, status, i);
+       STATUS_TO_TEXT(CARD_REMOVE_A, status, i);
+       STATUS_TO_TEXT(CARD_INSERT_A, status, i);
+       STATUS_TO_TEXT(SIGSTATE_A, status, i);
+       STATUS_TO_TEXT(CMD_IDX_ERR, status, i);
+       STATUS_TO_TEXT(STOPBIT_ERR, status, i);
+       STATUS_TO_TEXT(ILL_FUNC, status, i);
+       STATUS_TO_TEXT(CMD_BUSY, status, i);
+       STATUS_TO_TEXT(CMDRESPEND, status, i);
+       STATUS_TO_TEXT(DATAEND, status, i);
+       STATUS_TO_TEXT(CRCFAIL, status, i);
+       STATUS_TO_TEXT(DATATIMEOUT, status, i);
+       STATUS_TO_TEXT(CMDTIMEOUT, status, i);
+       STATUS_TO_TEXT(RXOVERFLOW, status, i);
+       STATUS_TO_TEXT(TXUNDERRUN, status, i);
+       STATUS_TO_TEXT(RXRDY, status, i);
+       STATUS_TO_TEXT(TXRQ, status, i);
+       STATUS_TO_TEXT(ILL_ACCESS, status, i);
+       printk("\n");
+}
+
+#else
+#define pr_debug_status(s)  do { } while (0)
+#endif
+
+static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+
+       if (enable) {
+               host->sdio_irq_enabled = 1;
+               sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
+               sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
+                       (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
+       } else {
+               sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
+               sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
+               host->sdio_irq_enabled = 0;
+       }
+}
+
+static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
+{
+       u32 clk = 0, clock;
+
+       if (new_clock) {
+               for (clock = host->mmc->f_min, clk = 0x80000080;
+                       new_clock >= (clock<<1); clk >>= 1)
+                       clock <<= 1;
+               clk |= 0x100;
+       }
+
+       if (host->set_clk_div)
+               host->set_clk_div(host->pdev, (clk>>22) & 1);
+
+       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
+}
+
+static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
+{
+       struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+       /* implicit BUG_ON(!res) */
+       if (resource_size(res) > 0x100) {
+               sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
+               msleep(10);
+       }
+
+       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
+               sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+       msleep(10);
+}
+
+static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
+{
+       struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+       sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
+               sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+       msleep(10);
+
+       /* implicit BUG_ON(!res) */
+       if (resource_size(res) > 0x100) {
+               sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
+               msleep(10);
+       }
+}
+
+static void tmio_mmc_reset(struct tmio_mmc_host *host)
+{
+       struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+       /* FIXME - should we set stop clock reg here */
+       sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
+       /* implicit BUG_ON(!res) */
+       if (resource_size(res) > 0x100)
+               sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
+       msleep(10);
+       sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
+       if (resource_size(res) > 0x100)
+               sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
+       msleep(10);
+}
+
+static void tmio_mmc_reset_work(struct work_struct *work)
+{
+       struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
+                                                 delayed_reset_work.work);
+       struct mmc_request *mrq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       mrq = host->mrq;
+
+       /* request already finished */
+       if (!mrq
+           || time_is_after_jiffies(host->last_req_ts +
+               msecs_to_jiffies(2000))) {
+               spin_unlock_irqrestore(&host->lock, flags);
+               return;
+       }
+
+       dev_warn(&host->pdev->dev,
+               "timeout waiting for hardware interrupt (CMD%u)\n",
+               mrq->cmd->opcode);
+
+       if (host->data)
+               host->data->error = -ETIMEDOUT;
+       else if (host->cmd)
+               host->cmd->error = -ETIMEDOUT;
+       else
+               mrq->cmd->error = -ETIMEDOUT;
+
+       host->cmd = NULL;
+       host->data = NULL;
+       host->mrq = NULL;
+       host->force_pio = false;
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       tmio_mmc_reset(host);
+
+       mmc_request_done(host->mmc, mrq);
+}
+
+static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
+{
+       struct mmc_request *mrq = host->mrq;
+
+       if (!mrq)
+               return;
+
+       host->mrq = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+       host->force_pio = false;
+
+       cancel_delayed_work(&host->delayed_reset_work);
+
+       mmc_request_done(host->mmc, mrq);
+}
+
+/* These are the bitmasks the tmio chip requires to implement the MMC response
+ * types. Note that R1 and R6 are the same in this scheme. */
+#define APP_CMD        0x0040
+#define RESP_NONE      0x0300
+#define RESP_R1        0x0400
+#define RESP_R1B       0x0500
+#define RESP_R2        0x0600
+#define RESP_R3        0x0700
+#define DATA_PRESENT   0x0800
+#define TRANSFER_READ  0x1000
+#define TRANSFER_MULTI 0x2000
+#define SECURITY_CMD   0x4000
+
+static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
+{
+       struct mmc_data *data = host->data;
+       int c = cmd->opcode;
+
+       /* Command 12 is handled by hardware */
+       if (cmd->opcode == 12 && !cmd->arg) {
+               sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
+               return 0;
+       }
+
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE: c |= RESP_NONE; break;
+       case MMC_RSP_R1:   c |= RESP_R1;   break;
+       case MMC_RSP_R1B:  c |= RESP_R1B;  break;
+       case MMC_RSP_R2:   c |= RESP_R2;   break;
+       case MMC_RSP_R3:   c |= RESP_R3;   break;
+       default:
+               pr_debug("Unknown response type %d\n", mmc_resp_type(cmd));
+               return -EINVAL;
+       }
+
+       host->cmd = cmd;
+
+/* FIXME - this seems to be ok commented out but the spec suggest this bit
+ *         should be set when issuing app commands.
+ *     if(cmd->flags & MMC_FLAG_ACMD)
+ *             c |= APP_CMD;
+ */
+       if (data) {
+               c |= DATA_PRESENT;
+               if (data->blocks > 1) {
+                       sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
+                       c |= TRANSFER_MULTI;
+               }
+               if (data->flags & MMC_DATA_READ)
+                       c |= TRANSFER_READ;
+       }
+
+       tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_CMD);
+
+       /* Fire off the command */
+       sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
+       sd_ctrl_write16(host, CTL_SD_CMD, c);
+
+       return 0;
+}
+
+/*
+ * This chip always returns (at least?) as much data as you ask for.
+ * I'm unsure what happens if you ask for less than a block. This should be
+ * looked into to ensure that a funny length read doesnt hose the controller.
+ */
+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;
+
+       if ((host->chan_tx || host->chan_rx) && !host->force_pio) {
+               pr_err("PIO IRQ in DMA mode!\n");
+               return;
+       } else if (!data) {
+               pr_debug("Spurious PIO IRQ\n");
+               return;
+       }
+
+       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)
+               count = data->blksz;
+
+       pr_debug("count: %08x offset: %08x flags %08x\n",
+                count, host->sg_off, data->flags);
+
+       /* Transfer the data */
+       if (data->flags & MMC_DATA_READ)
+               sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+       else
+               sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+
+       host->sg_off += count;
+
+       tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt);
+
+       if (host->sg_off == host->sg_ptr->length)
+               tmio_mmc_next_sg(host);
+
+       return;
+}
+
+static void tmio_mmc_check_bounce_buffer(struct tmio_mmc_host *host)
+{
+       if (host->sg_ptr == &host->bounce_sg) {
+               unsigned long flags;
+               void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
+               memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
+               tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr);
+       }
+}
+
+/* needs to be called with host->lock held */
+void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
+{
+       struct mmc_data *data = host->data;
+       struct mmc_command *stop;
+
+       host->data = NULL;
+
+       if (!data) {
+               dev_warn(&host->pdev->dev, "Spurious data end IRQ\n");
+               return;
+       }
+       stop = data->stop;
+
+       /* FIXME - return correct transfer count on errors */
+       if (!data->error)
+               data->bytes_xfered = data->blocks * data->blksz;
+       else
+               data->bytes_xfered = 0;
+
+       pr_debug("Completed data request\n");
+
+       /*
+        * FIXME: other drivers allow an optional stop command of any given type
+        *        which we dont do, as the chip can auto generate them.
+        *        Perhaps we can be smarter about when to use auto CMD12 and
+        *        only issue the auto request when we know this is the desired
+        *        stop command, allowing fallback to the stop command the
+        *        upper layers expect. For now, we do what works.
+        */
+
+       if (data->flags & MMC_DATA_READ) {
+               if (host->chan_rx && !host->force_pio)
+                       tmio_mmc_check_bounce_buffer(host);
+               dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
+                       host->mrq);
+       } else {
+               dev_dbg(&host->pdev->dev, "Complete Tx request %p\n",
+                       host->mrq);
+       }
+
+       if (stop) {
+               if (stop->opcode == 12 && !stop->arg)
+                       sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
+               else
+                       BUG();
+       }
+
+       tmio_mmc_finish_request(host);
+}
+
+static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
+{
+       struct mmc_data *data;
+       spin_lock(&host->lock);
+       data = host->data;
+
+       if (!data)
+               goto out;
+
+       if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
+               /*
+                * Has all data been written out yet? Testing on SuperH showed,
+                * that in most cases the first interrupt comes already with the
+                * BUSY status bit clear, but on some operations, like mount or
+                * in the beginning of a write / sync / umount, there is one
+                * DATAEND interrupt with the BUSY bit set, in this cases
+                * waiting for one more interrupt fixes the problem.
+                */
+               if (!(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_CMD_BUSY)) {
+                       tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_DATAEND);
+                       tasklet_schedule(&host->dma_complete);
+               }
+       } else if (host->chan_rx && (data->flags & MMC_DATA_READ) && !host->force_pio) {
+               tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_DATAEND);
+               tasklet_schedule(&host->dma_complete);
+       } else {
+               tmio_mmc_do_data_irq(host);
+               tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_READOP | TMIO_MASK_WRITEOP);
+       }
+out:
+       spin_unlock(&host->lock);
+}
+
+static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
+       unsigned int stat)
+{
+       struct mmc_command *cmd = host->cmd;
+       int i, addr;
+
+       spin_lock(&host->lock);
+
+       if (!host->cmd) {
+               pr_debug("Spurious CMD irq\n");
+               goto out;
+       }
+
+       host->cmd = NULL;
+
+       /* This controller is sicker than the PXA one. Not only do we need to
+        * drop the top 8 bits of the first response word, we also need to
+        * modify the order of the response for short response command types.
+        */
+
+       for (i = 3, addr = CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
+               cmd->resp[i] = sd_ctrl_read32(host, addr);
+
+       if (cmd->flags &  MMC_RSP_136) {
+               cmd->resp[0] = (cmd->resp[0] << 8) | (cmd->resp[1] >> 24);
+               cmd->resp[1] = (cmd->resp[1] << 8) | (cmd->resp[2] >> 24);
+               cmd->resp[2] = (cmd->resp[2] << 8) | (cmd->resp[3] >> 24);
+               cmd->resp[3] <<= 8;
+       } else if (cmd->flags & MMC_RSP_R3) {
+               cmd->resp[0] = cmd->resp[3];
+       }
+
+       if (stat & TMIO_STAT_CMDTIMEOUT)
+               cmd->error = -ETIMEDOUT;
+       else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
+               cmd->error = -EILSEQ;
+
+       /* If there is data to handle we enable data IRQs here, and
+        * we will ultimatley finish the request in the data_end handler.
+        * If theres no data or we encountered an error, finish now.
+        */
+       if (host->data && !cmd->error) {
+               if (host->data->flags & MMC_DATA_READ) {
+                       if (host->force_pio || !host->chan_rx)
+                               tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP);
+                       else
+                               tasklet_schedule(&host->dma_issue);
+               } else {
+                       if (host->force_pio || !host->chan_tx)
+                               tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
+                       else
+                               tasklet_schedule(&host->dma_issue);
+               }
+       } else {
+               tmio_mmc_finish_request(host);
+       }
+
+out:
+       spin_unlock(&host->lock);
+}
+
+static irqreturn_t tmio_mmc_irq(int irq, void *devid)
+{
+       struct tmio_mmc_host *host = devid;
+       struct tmio_mmc_data *pdata = host->pdata;
+       unsigned int ireg, irq_mask, status;
+       unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
+
+       pr_debug("MMC IRQ begin\n");
+
+       status = sd_ctrl_read32(host, CTL_STATUS);
+       irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
+       ireg = status & TMIO_MASK_IRQ & ~irq_mask;
+
+       sdio_ireg = 0;
+       if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
+               sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+               sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
+               sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
+
+               sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
+
+               if (sdio_ireg && !host->sdio_irq_enabled) {
+                       pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
+                                  sdio_status, sdio_irq_mask, sdio_ireg);
+                       tmio_mmc_enable_sdio_irq(host->mmc, 0);
+                       goto out;
+               }
+
+               if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
+                       sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
+                       mmc_signal_sdio_irq(host->mmc);
+
+               if (sdio_ireg)
+                       goto out;
+       }
+
+       pr_debug_status(status);
+       pr_debug_status(ireg);
+
+       if (!ireg) {
+               tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
+
+               pr_warning("tmio_mmc: Spurious irq, disabling! "
+                       "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
+               pr_debug_status(status);
+
+               goto out;
+       }
+
+       while (ireg) {
+               /* Card insert / remove attempts */
+               if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
+                       tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
+                               TMIO_STAT_CARD_REMOVE);
+                       mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+               }
+
+               /* CRC and other errors */
+/*             if (ireg & TMIO_STAT_ERR_IRQ)
+ *                     handled |= tmio_error_irq(host, irq, stat);
+ */
+
+               /* Command completion */
+               if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
+                       tmio_mmc_ack_mmc_irqs(host,
+                                    TMIO_STAT_CMDRESPEND |
+                                    TMIO_STAT_CMDTIMEOUT);
+                       tmio_mmc_cmd_irq(host, status);
+               }
+
+               /* Data transfer */
+               if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
+                       tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
+                       tmio_mmc_pio_irq(host);
+               }
+
+               /* Data transfer completion */
+               if (ireg & TMIO_STAT_DATAEND) {
+                       tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
+                       tmio_mmc_data_irq(host);
+               }
+
+               /* Check status - keep going until we've handled it all */
+               status = sd_ctrl_read32(host, CTL_STATUS);
+               irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
+               ireg = status & TMIO_MASK_IRQ & ~irq_mask;
+
+               pr_debug("Status at end of loop: %08x\n", status);
+               pr_debug_status(status);
+       }
+       pr_debug("MMC IRQ end\n");
+
+out:
+       return IRQ_HANDLED;
+}
+
+static int tmio_mmc_start_data(struct tmio_mmc_host *host,
+       struct mmc_data *data)
+{
+       struct tmio_mmc_data *pdata = host->pdata;
+
+       pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
+                data->blksz, data->blocks);
+
+       /* Some hardware cannot perform 2 byte requests in 4 bit mode */
+       if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+               int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
+
+               if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
+                       pr_err("%s: %d byte block unsupported in 4 bit mode\n",
+                              mmc_hostname(host->mmc), data->blksz);
+                       return -EINVAL;
+               }
+       }
+
+       tmio_mmc_init_sg(host, data);
+       host->data = data;
+
+       /* Set transfer length / blocksize */
+       sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
+       sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
+
+       tmio_mmc_start_dma(host, data);
+
+       return 0;
+}
+
+/* Process requests from the MMC layer */
+static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       int ret;
+
+       if (host->mrq)
+               pr_debug("request not null\n");
+
+       host->last_req_ts = jiffies;
+       wmb();
+       host->mrq = mrq;
+
+       if (mrq->data) {
+               ret = tmio_mmc_start_data(host, mrq->data);
+               if (ret)
+                       goto fail;
+       }
+
+       ret = tmio_mmc_start_command(host, mrq->cmd);
+       if (!ret) {
+               schedule_delayed_work(&host->delayed_reset_work,
+                                     msecs_to_jiffies(2000));
+               return;
+       }
+
+fail:
+       host->mrq = NULL;
+       host->force_pio = false;
+       mrq->cmd->error = ret;
+       mmc_request_done(mmc, mrq);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot
+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
+ * slowest setting.
+ */
+static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+
+       if (ios->clock)
+               tmio_mmc_set_clock(host, ios->clock);
+
+       /* Power sequence - OFF -> UP -> ON */
+       if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
+               /* power down SD bus */
+               if (ios->power_mode == MMC_POWER_OFF && host->set_pwr)
+                       host->set_pwr(host->pdev, 0);
+               tmio_mmc_clk_stop(host);
+       } else if (ios->power_mode == MMC_POWER_UP) {
+               /* power up SD bus */
+               if (host->set_pwr)
+                       host->set_pwr(host->pdev, 1);
+       } else {
+               /* start bus clock */
+               tmio_mmc_clk_start(host);
+       }
+
+       switch (ios->bus_width) {
+       case MMC_BUS_WIDTH_1:
+               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
+       break;
+       case MMC_BUS_WIDTH_4:
+               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
+       break;
+       }
+
+       /* Let things settle. delay taken from winCE driver */
+       udelay(140);
+}
+
+static int tmio_mmc_get_ro(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
+
+       return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
+               !(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
+}
+
+static int tmio_mmc_get_cd(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
+
+       if (!pdata->get_cd)
+               return -ENOSYS;
+       else
+               return pdata->get_cd(host->pdev);
+}
+
+static const struct mmc_host_ops tmio_mmc_ops = {
+       .request        = tmio_mmc_request,
+       .set_ios        = tmio_mmc_set_ios,
+       .get_ro         = tmio_mmc_get_ro,
+       .get_cd         = tmio_mmc_get_cd,
+       .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
+};
+
+int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+                                 struct platform_device *pdev,
+                                 struct tmio_mmc_data *pdata)
+{
+       struct tmio_mmc_host *_host;
+       struct mmc_host *mmc;
+       struct resource *res_ctl;
+       int ret;
+       u32 irq_mask = TMIO_MASK_CMD;
+
+       res_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res_ctl)
+               return -EINVAL;
+
+       mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &pdev->dev);
+       if (!mmc)
+               return -ENOMEM;
+
+       _host = mmc_priv(mmc);
+       _host->pdata = pdata;
+       _host->mmc = mmc;
+       _host->pdev = pdev;
+       platform_set_drvdata(pdev, mmc);
+
+       _host->set_pwr = pdata->set_pwr;
+       _host->set_clk_div = pdata->set_clk_div;
+
+       /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
+       _host->bus_shift = resource_size(res_ctl) >> 10;
+
+       _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl));
+       if (!_host->ctl) {
+               ret = -ENOMEM;
+               goto host_free;
+       }
+
+       mmc->ops = &tmio_mmc_ops;
+       mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
+       mmc->f_max = pdata->hclk;
+       mmc->f_min = mmc->f_max / 512;
+       mmc->max_segs = 32;
+       mmc->max_blk_size = 512;
+       mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
+               mmc->max_segs;
+       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       mmc->max_seg_size = mmc->max_req_size;
+       if (pdata->ocr_mask)
+               mmc->ocr_avail = pdata->ocr_mask;
+       else
+               mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+       tmio_mmc_clk_stop(_host);
+       tmio_mmc_reset(_host);
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               goto unmap_ctl;
+
+       _host->irq = ret;
+
+       tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
+       if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+               tmio_mmc_enable_sdio_irq(mmc, 0);
+
+       ret = request_irq(_host->irq, tmio_mmc_irq, IRQF_DISABLED |
+               IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), _host);
+       if (ret)
+               goto unmap_ctl;
+
+       spin_lock_init(&_host->lock);
+
+       /* Init delayed work for request timeouts */
+       INIT_DELAYED_WORK(&_host->delayed_reset_work, tmio_mmc_reset_work);
+
+       /* See if we also get DMA */
+       tmio_mmc_request_dma(_host, pdata);
+
+       mmc_add_host(mmc);
+
+       /* Unmask the IRQs we want to know about */
+       if (!_host->chan_rx)
+               irq_mask |= TMIO_MASK_READOP;
+       if (!_host->chan_tx)
+               irq_mask |= TMIO_MASK_WRITEOP;
+
+       tmio_mmc_enable_mmc_irqs(_host, irq_mask);
+
+       *host = _host;
+
+       return 0;
+
+unmap_ctl:
+       iounmap(_host->ctl);
+host_free:
+       mmc_free_host(mmc);
+
+       return ret;
+}
+EXPORT_SYMBOL(tmio_mmc_host_probe);
+
+void tmio_mmc_host_remove(struct tmio_mmc_host *host)
+{
+       mmc_remove_host(host->mmc);
+       cancel_delayed_work_sync(&host->delayed_reset_work);
+       tmio_mmc_release_dma(host);
+       free_irq(host->irq, host);
+       iounmap(host->ctl);
+       mmc_free_host(host->mmc);
+}
+EXPORT_SYMBOL(tmio_mmc_host_remove);
+
+MODULE_LICENSE("GPL v2");
index 8c5b4881ccd6068fc766fd6e0ae77dbbe2669664..4dfe2c02ea91f340fd3de23db2b371da9020fc91 100644 (file)
@@ -1087,14 +1087,13 @@ static int __devinit via_sd_probe(struct pci_dev *pcidev,
        struct mmc_host *mmc;
        struct via_crdr_mmc_host *sdhost;
        u32 base, len;
-       u8 rev, gatt;
+       u8  gatt;
        int ret;
 
-       pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &rev);
        pr_info(DRV_NAME
                ": VIA SDMMC controller found at %s [%04x:%04x] (rev %x)\n",
                pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
-               (int)rev);
+               (int)pcidev->revision);
 
        ret = pci_enable_device(pcidev);
        if (ret)
index 77414702cb00ed7c02dbaefb87b140396773df0b..b4567c35a322c709f0d9a501fda63156950ad148 100644 (file)
@@ -33,14 +33,6 @@ config MTD_TESTS
          should normally be compiled as kernel modules. The modules perform
          various checks and verifications when loaded.
 
-config MTD_CONCAT
-       tristate "MTD concatenating support"
-       help
-         Support for concatenating several MTD devices into a single
-         (virtual) one. This allows you to have -for example- a JFFS(2)
-         file system spanning multiple physical flash chips. If unsure,
-         say 'Y'.
-
 config MTD_PARTITIONS
        bool "MTD partitioning support"
        help
@@ -333,6 +325,16 @@ config MTD_OOPS
          To use, add console=ttyMTDx to the kernel command line,
          where x is the MTD device number to use.
 
+config MTD_SWAP
+       tristate "Swap on MTD device support"
+       depends on MTD && SWAP
+       select MTD_BLKDEVS
+       help
+         Provides volatile block device driver on top of mtd partition
+          suitable for swapping.  The mapping of written blocks is not saved.
+         The driver provides wear leveling by storing erase counter into the
+         OOB.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
index d4e7f25b1ebb6e3686c0336f2471c206ddd56348..d578095fb25595a5856a72be137dde75372b9c4d 100644 (file)
@@ -4,11 +4,10 @@
 
 # Core functionality.
 obj-$(CONFIG_MTD)              += mtd.o
-mtd-y                          := mtdcore.o mtdsuper.o
+mtd-y                          := mtdcore.o mtdsuper.o mtdconcat.o
 mtd-$(CONFIG_MTD_PARTITIONS)   += mtdpart.o
 mtd-$(CONFIG_MTD_OF_PARTS)     += ofpart.o
 
-obj-$(CONFIG_MTD_CONCAT)       += mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)    += afs.o
@@ -26,6 +25,7 @@ obj-$(CONFIG_RFD_FTL)         += rfd_ftl.o
 obj-$(CONFIG_SSFDC)            += ssfdc.o
 obj-$(CONFIG_SM_FTL)           += sm_ftl.o
 obj-$(CONFIG_MTD_OOPS)         += mtdoops.o
+obj-$(CONFIG_MTD_SWAP)         += mtdswap.o
 
 nftl-objs              := nftlcore.o nftlmount.o
 inftl-objs             := inftlcore.o inftlmount.o
index 4aaa88f8ab5f0323f015dd34c46c4d0f98703ada..092aef11120cb70f13129a29788eb95a1eabbe8c 100644 (file)
@@ -455,7 +455,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
        mtd->flags   = MTD_CAP_NORFLASH;
        mtd->name    = map->name;
        mtd->writesize = 1;
-       mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+       mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
        mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
 
index f072fcfde04ee86fd5133b83c720b73cac2071d7..f9a5331e9445a3fb16e1f1604097c7a54f833201 100644 (file)
@@ -349,6 +349,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
        { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
 #ifdef AMD_BOOTLOC_BUG
        { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock },
+       { CFI_MFR_AMIC, CFI_ID_ANY, fixup_amd_bootblock },
        { CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock },
 #endif
        { CFI_MFR_AMD, 0x0050, fixup_use_secsi },
@@ -440,7 +441,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
        mtd->flags   = MTD_CAP_NORFLASH;
        mtd->name    = map->name;
        mtd->writesize = 1;
-       mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+       mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
        DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
                __func__, mtd->writebufsize);
index c04b7658abe90c39c6942e2d9d1b18a0ce7219f5..ed56ad3884fbc5d88ef97c46e046da4d7afab3a8 100644 (file)
@@ -238,7 +238,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
        mtd->resume = cfi_staa_resume;
        mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
        mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
-       mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+       mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
        map->fldrv = &cfi_staa_chipdrv;
        __module_get(THIS_MODULE);
        mtd->name = map->name;
index e4eba6cc1b2e7c98ba8fac09db7b9569012d34b0..3fb981d4bb51071563ceb99805b9c4361033c12c 100644 (file)
@@ -655,7 +655,8 @@ static const struct spi_device_id m25p_ids[] = {
        { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
        { "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
 
-       /* EON -- en25pxx */
+       /* EON -- en25xxx */
+       { "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
        { "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
        { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 
@@ -728,6 +729,8 @@ static const struct spi_device_id m25p_ids[] = {
        { "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
        { "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
+       { "m25px64", INFO(0x207117,  0, 64 * 1024, 128, 0) },
+
        /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
        { "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
        { "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
index 26a6e809013d272059b8f5dbebc2730283bf2c02..1483e18971cef934b0c713fe9e5ab5727561cf12 100644 (file)
@@ -121,6 +121,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
        mtd->flags = MTD_CAP_RAM;
        mtd->size = size;
        mtd->writesize = 1;
+       mtd->writebufsize = 64; /* Mimic CFI NOR flashes */
        mtd->erasesize = MTDRAM_ERASE_SIZE;
        mtd->priv = mapped_address;
 
index 52393282eaf10ca813ed131565ce45951443542e..8d28fa02a5a2f13d342c196be185ba4e88b68452 100644 (file)
@@ -117,6 +117,7 @@ static void unregister_devices(void)
        list_for_each_entry_safe(this, safe, &phram_list, list) {
                del_mtd_device(&this->mtd);
                iounmap(this->mtd.priv);
+               kfree(this->mtd.name);
                kfree(this);
        }
 }
@@ -275,6 +276,8 @@ static int phram_setup(const char *val, struct kernel_param *kp)
        ret = register_device(name, start, len);
        if (!ret)
                pr_info("%s device: %#x at %#x\n", name, len, start);
+       else
+               kfree(name);
 
        return ret;
 }
index 5d37d315fa98e18d37d58fa77410e7fa80954b26..44b1f46458cabf89dafed26b1972ee9866141761 100644 (file)
@@ -114,7 +114,7 @@ config MTD_SUN_UFLASH
 
 config MTD_SC520CDP
        tristate "CFI Flash device mapped on AMD SC520 CDP"
-       depends on X86 && MTD_CFI && MTD_CONCAT
+       depends on X86 && MTD_CFI
        help
          The SC520 CDP board has two banks of CFI-compliant chips and one
          Dual-in-line JEDEC chip. This 'mapping' driver supports that
@@ -262,7 +262,7 @@ config MTD_BCM963XX
 
 config MTD_DILNETPC
        tristate "CFI Flash device mapped on DIL/Net PC"
-       depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
+       depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
        help
          MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
          For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
@@ -552,4 +552,13 @@ config MTD_PISMO
 
          When built as a module, it will be called pismo.ko
 
+config MTD_LATCH_ADDR
+        tristate "Latch-assisted Flash Chip Support"
+        depends on MTD_COMPLEX_MAPPINGS
+        help
+          Map driver which allows flashes to be partially physically addressed
+          and have the upper address lines set by a board specific code.
+
+          If compiled as a module, it will be called latch-addr-flash.
+
 endmenu
index c7869c7a6b18f1a2534976cb4388aa22efc2839b..08533bd5cba7c4adfeef23f4fe8d348b2ad0015d 100644 (file)
@@ -59,3 +59,4 @@ obj-$(CONFIG_MTD_RBTX4939)    += rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)          += vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)    += gpio-addr-flash.o
 obj-$(CONFIG_MTD_BCM963XX)     += bcm963xx-flash.o
+obj-$(CONFIG_MTD_LATCH_ADDR)   += latch-addr-flash.o
index c09f4f57093ee65e4a149b537cec45ef868be9ff..e5f645b775ad1e721623ed9293a9396cc27d2cef 100644 (file)
@@ -194,16 +194,10 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info
                         * We detected multiple devices.  Concatenate
                         * them together.
                         */
-#ifdef CONFIG_MTD_CONCAT
                        *rmtd = mtd_concat_create(subdev, found,
                                                  "clps flash");
                        if (*rmtd == NULL)
                                ret = -ENXIO;
-#else
-                       printk(KERN_ERR "clps flash: multiple devices "
-                              "found but MTD concat support disabled.\n");
-                       ret = -ENXIO;
-#endif
                }
        }
 
index 2aac41bde8b314feda6bf213472c76277881c6ca..e22ff5adbbf4b34016d98c82eebaba24e050133d 100644 (file)
@@ -202,7 +202,6 @@ static int armflash_probe(struct platform_device *dev)
        if (info->nr_subdev == 1)
                info->mtd = info->subdev[0].mtd;
        else if (info->nr_subdev > 1) {
-#ifdef CONFIG_MTD_CONCAT
                struct mtd_info *cdev[info->nr_subdev];
 
                /*
@@ -215,11 +214,6 @@ static int armflash_probe(struct platform_device *dev)
                                              dev_name(&dev->dev));
                if (info->mtd == NULL)
                        err = -ENXIO;
-#else
-               printk(KERN_ERR "armflash: multiple devices found but "
-                      "MTD concat support disabled.\n");
-               err = -ENXIO;
-#endif
        }
 
        if (err < 0)
@@ -244,10 +238,8 @@ static int armflash_probe(struct platform_device *dev)
  cleanup:
        if (info->mtd) {
                del_mtd_partitions(info->mtd);
-#ifdef CONFIG_MTD_CONCAT
                if (info->mtd != info->subdev[0].mtd)
                        mtd_concat_destroy(info->mtd);
-#endif
        }
        kfree(info->parts);
  subdev_err:
@@ -272,10 +264,8 @@ static int armflash_remove(struct platform_device *dev)
        if (info) {
                if (info->mtd) {
                        del_mtd_partitions(info->mtd);
-#ifdef CONFIG_MTD_CONCAT
                        if (info->mtd != info->subdev[0].mtd)
                                mtd_concat_destroy(info->mtd);
-#endif
                }
                kfree(info->parts);
 
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
new file mode 100644 (file)
index 0000000..ee25480
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Interface for NOR flash driver whose high address lines are latched
+ *
+ * Copyright Â© 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright Â© 2005-2008 Analog Devices Inc.
+ * Copyright Â© 2008 MontaVista Software, Inc. <source@mvista.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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "latch-addr-flash"
+
+struct latch_addr_flash_info {
+       struct mtd_info         *mtd;
+       struct map_info         map;
+       struct resource         *res;
+
+       void                    (*set_window)(unsigned long offset, void *data);
+       void                    *data;
+
+       /* cache; could be found out of res */
+       unsigned long           win_mask;
+
+       int                     nr_parts;
+       struct mtd_partition    *parts;
+
+       spinlock_t              lock;
+};
+
+static map_word lf_read(struct map_info *map, unsigned long ofs)
+{
+       struct latch_addr_flash_info *info;
+       map_word datum;
+
+       info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+       spin_lock(&info->lock);
+
+       info->set_window(ofs, info->data);
+       datum = inline_map_read(map, info->win_mask & ofs);
+
+       spin_unlock(&info->lock);
+
+       return datum;
+}
+
+static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
+{
+       struct latch_addr_flash_info *info;
+
+       info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+       spin_lock(&info->lock);
+
+       info->set_window(ofs, info->data);
+       inline_map_write(map, datum, info->win_mask & ofs);
+
+       spin_unlock(&info->lock);
+}
+
+static void lf_copy_from(struct map_info *map, void *to,
+               unsigned long from, ssize_t len)
+{
+       struct latch_addr_flash_info *info =
+               (struct latch_addr_flash_info *) map->map_priv_1;
+       unsigned n;
+
+       while (len > 0) {
+               n = info->win_mask + 1 - (from & info->win_mask);
+               if (n > len)
+                       n = len;
+
+               spin_lock(&info->lock);
+
+               info->set_window(from, info->data);
+               memcpy_fromio(to, map->virt + (from & info->win_mask), n);
+
+               spin_unlock(&info->lock);
+
+               to += n;
+               from += n;
+               len -= n;
+       }
+}
+
+static char *rom_probe_types[] = { "cfi_probe", NULL };
+
+static char *part_probe_types[] = { "cmdlinepart", NULL };
+
+static int latch_addr_flash_remove(struct platform_device *dev)
+{
+       struct latch_addr_flash_info *info;
+       struct latch_addr_flash_data *latch_addr_data;
+
+       info = platform_get_drvdata(dev);
+       if (info == NULL)
+               return 0;
+       platform_set_drvdata(dev, NULL);
+
+       latch_addr_data = dev->dev.platform_data;
+
+       if (info->mtd != NULL) {
+               if (mtd_has_partitions()) {
+                       if (info->nr_parts) {
+                               del_mtd_partitions(info->mtd);
+                               kfree(info->parts);
+                       } else if (latch_addr_data->nr_parts) {
+                               del_mtd_partitions(info->mtd);
+                       } else {
+                               del_mtd_device(info->mtd);
+                       }
+               } else {
+                       del_mtd_device(info->mtd);
+               }
+               map_destroy(info->mtd);
+       }
+
+       if (info->map.virt != NULL)
+               iounmap(info->map.virt);
+
+       if (info->res != NULL)
+               release_mem_region(info->res->start, resource_size(info->res));
+
+       kfree(info);
+
+       if (latch_addr_data->done)
+               latch_addr_data->done(latch_addr_data->data);
+
+       return 0;
+}
+
+static int __devinit latch_addr_flash_probe(struct platform_device *dev)
+{
+       struct latch_addr_flash_data *latch_addr_data;
+       struct latch_addr_flash_info *info;
+       resource_size_t win_base = dev->resource->start;
+       resource_size_t win_size = resource_size(dev->resource);
+       char **probe_type;
+       int chipsel;
+       int err;
+
+       latch_addr_data = dev->dev.platform_data;
+       if (latch_addr_data == NULL)
+               return -ENODEV;
+
+       pr_notice("latch-addr platform flash device: %#llx byte "
+                 "window at %#.8llx\n",
+                 (unsigned long long)win_size, (unsigned long long)win_base);
+
+       chipsel = dev->id;
+
+       if (latch_addr_data->init) {
+               err = latch_addr_data->init(latch_addr_data->data, chipsel);
+               if (err != 0)
+                       return err;
+       }
+
+       info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
+       if (info == NULL) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       platform_set_drvdata(dev, info);
+
+       info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
+       if (info->res == NULL) {
+               dev_err(&dev->dev, "Could not reserve memory region\n");
+               err = -EBUSY;
+               goto free_info;
+       }
+
+       info->map.name          = DRIVER_NAME;
+       info->map.size          = latch_addr_data->size;
+       info->map.bankwidth     = latch_addr_data->width;
+
+       info->map.phys          = NO_XIP;
+       info->map.virt          = ioremap(win_base, win_size);
+       if (!info->map.virt) {
+               err = -ENOMEM;
+               goto free_res;
+       }
+
+       info->map.map_priv_1    = (unsigned long)info;
+
+       info->map.read          = lf_read;
+       info->map.copy_from     = lf_copy_from;
+       info->map.write         = lf_write;
+       info->set_window        = latch_addr_data->set_window;
+       info->data              = latch_addr_data->data;
+       info->win_mask          = win_size - 1;
+
+       spin_lock_init(&info->lock);
+
+       for (probe_type = rom_probe_types; !info->mtd && *probe_type;
+               probe_type++)
+               info->mtd = do_map_probe(*probe_type, &info->map);
+
+       if (info->mtd == NULL) {
+               dev_err(&dev->dev, "map_probe failed\n");
+               err = -ENODEV;
+               goto iounmap;
+       }
+       info->mtd->owner = THIS_MODULE;
+
+       if (mtd_has_partitions()) {
+
+               err = parse_mtd_partitions(info->mtd,
+                                          (const char **)part_probe_types,
+                                          &info->parts, 0);
+               if (err > 0) {
+                       add_mtd_partitions(info->mtd, info->parts, err);
+                       return 0;
+               }
+               if (latch_addr_data->nr_parts) {
+                       pr_notice("Using latch-addr-flash partition information\n");
+                       add_mtd_partitions(info->mtd, latch_addr_data->parts,
+                                       latch_addr_data->nr_parts);
+                       return 0;
+               }
+       }
+       add_mtd_device(info->mtd);
+       return 0;
+
+iounmap:
+       iounmap(info->map.virt);
+free_res:
+       release_mem_region(info->res->start, resource_size(info->res));
+free_info:
+       kfree(info);
+done:
+       if (latch_addr_data->done)
+               latch_addr_data->done(latch_addr_data->data);
+       return err;
+}
+
+static struct platform_driver latch_addr_flash_driver = {
+       .probe          = latch_addr_flash_probe,
+       .remove         = __devexit_p(latch_addr_flash_remove),
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init latch_addr_flash_init(void)
+{
+       return platform_driver_register(&latch_addr_flash_driver);
+}
+module_init(latch_addr_flash_init);
+
+static void __exit latch_addr_flash_exit(void)
+{
+       platform_driver_unregister(&latch_addr_flash_driver);
+}
+module_exit(latch_addr_flash_exit);
+
+MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
+               "address lines being set board specifically");
+MODULE_LICENSE("GPL v2");
index 4c18b98a3110872f8648fcf8526f46fd19c162f3..7522df4f71f1d67c302a290de2dc77ac1b98d63c 100644 (file)
@@ -59,10 +59,8 @@ static int physmap_flash_remove(struct platform_device *dev)
 #else
                del_mtd_device(info->cmtd);
 #endif
-#ifdef CONFIG_MTD_CONCAT
                if (info->cmtd != info->mtd[0])
                        mtd_concat_destroy(info->cmtd);
-#endif
        }
 
        for (i = 0; i < MAX_RESOURCES; i++) {
@@ -159,15 +157,9 @@ static int physmap_flash_probe(struct platform_device *dev)
                /*
                 * We detected multiple devices. Concatenate them together.
                 */
-#ifdef CONFIG_MTD_CONCAT
                info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev));
                if (info->cmtd == NULL)
                        err = -ENXIO;
-#else
-               printk(KERN_ERR "physmap-flash: multiple devices "
-                      "found but MTD concat support disabled.\n");
-               err = -ENXIO;
-#endif
        }
        if (err)
                goto err_out;
index 3db0cb083d312207f0ca3dd9446a448ddcc4399c..bd483f0c57e1ae31ca98c1336cd3f4bed248310b 100644 (file)
@@ -104,12 +104,10 @@ static int of_flash_remove(struct platform_device *dev)
                return 0;
        dev_set_drvdata(&dev->dev, NULL);
 
-#ifdef CONFIG_MTD_CONCAT
        if (info->cmtd != info->list[0].mtd) {
                del_mtd_device(info->cmtd);
                mtd_concat_destroy(info->cmtd);
        }
-#endif
 
        if (info->cmtd) {
                if (OF_FLASH_PARTS(info)) {
@@ -337,16 +335,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
                /*
                 * We detected multiple devices. Concatenate them together.
                 */
-#ifdef CONFIG_MTD_CONCAT
                info->cmtd = mtd_concat_create(mtd_list, info->list_size,
                                               dev_name(&dev->dev));
                if (info->cmtd == NULL)
                        err = -ENXIO;
-#else
-               printk(KERN_ERR "physmap_of: multiple devices "
-                      "found but MTD concat support disabled.\n");
-               err = -ENXIO;
-#endif
        }
        if (err)
                goto err_out;
index f3af87e08ecd8c8d2cd9839dc127f1565f4cdf7c..da875908ea8e04e20e08edb2785ecac37ef96a31 100644 (file)
@@ -232,10 +232,8 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
                else
                        del_mtd_partitions(info->mtd);
 #endif
-#ifdef CONFIG_MTD_CONCAT
                if (info->mtd != info->subdev[0].mtd)
                        mtd_concat_destroy(info->mtd);
-#endif
        }
 
        kfree(info->parts);
@@ -321,7 +319,6 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
                info->mtd = info->subdev[0].mtd;
                ret = 0;
        } else if (info->num_subdev > 1) {
-#ifdef CONFIG_MTD_CONCAT
                struct mtd_info *cdev[nr];
                /*
                 * We detected multiple devices.  Concatenate them together.
@@ -333,11 +330,6 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
                                              plat->name);
                if (info->mtd == NULL)
                        ret = -ENXIO;
-#else
-               printk(KERN_ERR "SA1100 flash: multiple devices "
-                      "found but MTD concat support disabled.\n");
-               ret = -ENXIO;
-#endif
        }
 
        if (ret == 0)
index e2147bf11c88948036c6d4d696b38f7952e62f01..e02dfa9d4ddd8279890ec3daf1c91c0a0af90190 100644 (file)
@@ -94,7 +94,6 @@ static int __init init_ts5500_map(void)
        return 0;
 
 err1:
-       map_destroy(mymtd);
        iounmap(ts5500_map.virt);
 err2:
        return rc;
index e0a2373bf0e2fe5ad6fc9423d5db19f96e25de5a..a534e1f0c34844b39c0fd03ce9ee070f88438a9b 100644 (file)
@@ -40,7 +40,7 @@
 static LIST_HEAD(blktrans_majors);
 static DEFINE_MUTEX(blktrans_ref_mutex);
 
-void blktrans_dev_release(struct kref *kref)
+static void blktrans_dev_release(struct kref *kref)
 {
        struct mtd_blktrans_dev *dev =
                container_of(kref, struct mtd_blktrans_dev, ref);
@@ -67,7 +67,7 @@ unlock:
        return dev;
 }
 
-void blktrans_dev_put(struct mtd_blktrans_dev *dev)
+static void blktrans_dev_put(struct mtd_blktrans_dev *dev)
 {
        mutex_lock(&blktrans_ref_mutex);
        kref_put(&dev->ref, blktrans_dev_release);
@@ -119,18 +119,43 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
        }
 }
 
+int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev)
+{
+       if (kthread_should_stop())
+               return 1;
+
+       return dev->bg_stop;
+}
+EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background);
+
 static int mtd_blktrans_thread(void *arg)
 {
        struct mtd_blktrans_dev *dev = arg;
+       struct mtd_blktrans_ops *tr = dev->tr;
        struct request_queue *rq = dev->rq;
        struct request *req = NULL;
+       int background_done = 0;
 
        spin_lock_irq(rq->queue_lock);
 
        while (!kthread_should_stop()) {
                int res;
 
+               dev->bg_stop = false;
                if (!req && !(req = blk_fetch_request(rq))) {
+                       if (tr->background && !background_done) {
+                               spin_unlock_irq(rq->queue_lock);
+                               mutex_lock(&dev->lock);
+                               tr->background(dev);
+                               mutex_unlock(&dev->lock);
+                               spin_lock_irq(rq->queue_lock);
+                               /*
+                                * Do background processing just once per idle
+                                * period.
+                                */
+                               background_done = !dev->bg_stop;
+                               continue;
+                       }
                        set_current_state(TASK_INTERRUPTIBLE);
 
                        if (kthread_should_stop())
@@ -152,6 +177,8 @@ static int mtd_blktrans_thread(void *arg)
 
                if (!__blk_end_request_cur(req, res))
                        req = NULL;
+
+               background_done = 0;
        }
 
        if (req)
@@ -172,8 +199,10 @@ static void mtd_blktrans_request(struct request_queue *rq)
        if (!dev)
                while ((req = blk_fetch_request(rq)) != NULL)
                        __blk_end_request_all(req, -ENODEV);
-       else
+       else {
+               dev->bg_stop = true;
                wake_up_process(dev->thread);
+       }
 }
 
 static int blktrans_open(struct block_device *bdev, fmode_t mode)
@@ -379,9 +408,10 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        new->rq->queuedata = new;
        blk_queue_logical_block_size(new->rq, tr->blksize);
 
-       if (tr->discard)
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
-                                       new->rq);
+       if (tr->discard) {
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
+               new->rq->limits.max_discard_sectors = UINT_MAX;
+       }
 
        gd->queue = new->rq;
 
index 5f5777bd3f75f9cb2c9849aa5004174cb1911184..5060e608ea5d40a1fc6307829c31922abb5199a9 100644 (file)
@@ -750,6 +750,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        struct mtd_concat *concat;
        uint32_t max_erasesize, curr_erasesize;
        int num_erase_region;
+       int max_writebufsize = 0;
 
        printk(KERN_NOTICE "Concatenating MTD devices:\n");
        for (i = 0; i < num_devs; i++)
@@ -776,7 +777,12 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],      /* subdevices to c
        concat->mtd.size = subdev[0]->size;
        concat->mtd.erasesize = subdev[0]->erasesize;
        concat->mtd.writesize = subdev[0]->writesize;
-       concat->mtd.writebufsize = subdev[0]->writebufsize;
+
+       for (i = 0; i < num_devs; i++)
+               if (max_writebufsize < subdev[i]->writebufsize)
+                       max_writebufsize = subdev[i]->writebufsize;
+       concat->mtd.writebufsize = max_writebufsize;
+
        concat->mtd.subpage_sft = subdev[0]->subpage_sft;
        concat->mtd.oobsize = subdev[0]->oobsize;
        concat->mtd.oobavail = subdev[0]->oobavail;
index 527cebf58da46e9586dcaede286f8d6e662e42cf..da69bc8a5a7d6f92c313fe2df32c644b9a0614f6 100644 (file)
@@ -43,7 +43,7 @@
  * backing device capabilities for non-mappable devices (such as NAND flash)
  * - permits private mappings, copies are taken of the data
  */
-struct backing_dev_info mtd_bdi_unmappable = {
+static struct backing_dev_info mtd_bdi_unmappable = {
        .capabilities   = BDI_CAP_MAP_COPY,
 };
 
@@ -52,7 +52,7 @@ struct backing_dev_info mtd_bdi_unmappable = {
  * - permits private mappings, copies are taken of the data
  * - permits non-writable shared mappings
  */
-struct backing_dev_info mtd_bdi_ro_mappable = {
+static struct backing_dev_info mtd_bdi_ro_mappable = {
        .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
                           BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
 };
@@ -62,7 +62,7 @@ struct backing_dev_info mtd_bdi_ro_mappable = {
  * - permits private mappings, copies are taken of the data
  * - permits non-writable shared mappings
  */
-struct backing_dev_info mtd_bdi_rw_mappable = {
+static struct backing_dev_info mtd_bdi_rw_mappable = {
        .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
                           BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
                           BDI_CAP_WRITE_MAP),
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c
new file mode 100644 (file)
index 0000000..237913c
--- /dev/null
@@ -0,0 +1,1587 @@
+/*
+ * Swap block device support for MTDs
+ * Turns an MTD device into a swap device with block wear leveling
+ *
+ * Copyright Â© 2007,2011 Nokia Corporation. All rights reserved.
+ *
+ * Authors: Jarkko Lavinen <jarkko.lavinen@nokia.com>
+ *
+ * Based on Richard Purdie's earlier implementation in 2007. Background
+ * support and lock-less operation written by Adrian Hunter.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/blktrans.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/genhd.h>
+#include <linux/swap.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/math64.h>
+
+#define MTDSWAP_PREFIX "mtdswap"
+
+/*
+ * The number of free eraseblocks when GC should stop
+ */
+#define CLEAN_BLOCK_THRESHOLD  20
+
+/*
+ * Number of free eraseblocks below which GC can also collect low frag
+ * blocks.
+ */
+#define LOW_FRAG_GC_TRESHOLD   5
+
+/*
+ * Wear level cost amortization. We want to do wear leveling on the background
+ * without disturbing gc too much. This is made by defining max GC frequency.
+ * Frequency value 6 means 1/6 of the GC passes will pick an erase block based
+ * on the biggest wear difference rather than the biggest dirtiness.
+ *
+ * The lower freq2 should be chosen so that it makes sure the maximum erase
+ * difference will decrease even if a malicious application is deliberately
+ * trying to make erase differences large.
+ */
+#define MAX_ERASE_DIFF         4000
+#define COLLECT_NONDIRTY_BASE  MAX_ERASE_DIFF
+#define COLLECT_NONDIRTY_FREQ1 6
+#define COLLECT_NONDIRTY_FREQ2 4
+
+#define PAGE_UNDEF             UINT_MAX
+#define BLOCK_UNDEF            UINT_MAX
+#define BLOCK_ERROR            (UINT_MAX - 1)
+#define BLOCK_MAX              (UINT_MAX - 2)
+
+#define EBLOCK_BAD             (1 << 0)
+#define EBLOCK_NOMAGIC         (1 << 1)
+#define EBLOCK_BITFLIP         (1 << 2)
+#define EBLOCK_FAILED          (1 << 3)
+#define EBLOCK_READERR         (1 << 4)
+#define EBLOCK_IDX_SHIFT       5
+
+struct swap_eb {
+       struct rb_node rb;
+       struct rb_root *root;
+
+       unsigned int flags;
+       unsigned int active_count;
+       unsigned int erase_count;
+       unsigned int pad;               /* speeds up pointer decremtnt */
+};
+
+#define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \
+                               rb)->erase_count)
+#define MTDSWAP_ECNT_MAX(rbroot) (rb_entry(rb_last(rbroot), struct swap_eb, \
+                               rb)->erase_count)
+
+struct mtdswap_tree {
+       struct rb_root root;
+       unsigned int count;
+};
+
+enum {
+       MTDSWAP_CLEAN,
+       MTDSWAP_USED,
+       MTDSWAP_LOWFRAG,
+       MTDSWAP_HIFRAG,
+       MTDSWAP_DIRTY,
+       MTDSWAP_BITFLIP,
+       MTDSWAP_FAILING,
+       MTDSWAP_TREE_CNT,
+};
+
+struct mtdswap_dev {
+       struct mtd_blktrans_dev *mbd_dev;
+       struct mtd_info *mtd;
+       struct device *dev;
+
+       unsigned int *page_data;
+       unsigned int *revmap;
+
+       unsigned int eblks;
+       unsigned int spare_eblks;
+       unsigned int pages_per_eblk;
+       unsigned int max_erase_count;
+       struct swap_eb *eb_data;
+
+       struct mtdswap_tree trees[MTDSWAP_TREE_CNT];
+
+       unsigned long long sect_read_count;
+       unsigned long long sect_write_count;
+       unsigned long long mtd_write_count;
+       unsigned long long mtd_read_count;
+       unsigned long long discard_count;
+       unsigned long long discard_page_count;
+
+       unsigned int curr_write_pos;
+       struct swap_eb *curr_write;
+
+       char *page_buf;
+       char *oob_buf;
+
+       struct dentry *debugfs_root;
+};
+
+struct mtdswap_oobdata {
+       __le16 magic;
+       __le32 count;
+} __attribute__((packed));
+
+#define MTDSWAP_MAGIC_CLEAN    0x2095
+#define MTDSWAP_MAGIC_DIRTY    (MTDSWAP_MAGIC_CLEAN + 1)
+#define MTDSWAP_TYPE_CLEAN     0
+#define MTDSWAP_TYPE_DIRTY     1
+#define MTDSWAP_OOBSIZE                sizeof(struct mtdswap_oobdata)
+
+#define MTDSWAP_ERASE_RETRIES  3 /* Before marking erase block bad */
+#define MTDSWAP_IO_RETRIES     3
+
+enum {
+       MTDSWAP_SCANNED_CLEAN,
+       MTDSWAP_SCANNED_DIRTY,
+       MTDSWAP_SCANNED_BITFLIP,
+       MTDSWAP_SCANNED_BAD,
+};
+
+/*
+ * In the worst case mtdswap_writesect() has allocated the last clean
+ * page from the current block and is then pre-empted by the GC
+ * thread. The thread can consume a full erase block when moving a
+ * block.
+ */
+#define MIN_SPARE_EBLOCKS      2
+#define MIN_ERASE_BLOCKS       (MIN_SPARE_EBLOCKS + 1)
+
+#define TREE_ROOT(d, name) (&d->trees[MTDSWAP_ ## name].root)
+#define TREE_EMPTY(d, name) (TREE_ROOT(d, name)->rb_node == NULL)
+#define TREE_NONEMPTY(d, name) (!TREE_EMPTY(d, name))
+#define TREE_COUNT(d, name) (d->trees[MTDSWAP_ ## name].count)
+
+#define MTDSWAP_MBD_TO_MTDSWAP(dev) ((struct mtdswap_dev *)dev->priv)
+
+static char partitions[128] = "";
+module_param_string(partitions, partitions, sizeof(partitions), 0444);
+MODULE_PARM_DESC(partitions, "MTD partition numbers to use as swap "
+               "partitions=\"1,3,5\"");
+
+static unsigned int spare_eblocks = 10;
+module_param(spare_eblocks, uint, 0444);
+MODULE_PARM_DESC(spare_eblocks, "Percentage of spare erase blocks for "
+               "garbage collection (default 10%)");
+
+static bool header; /* false */
+module_param(header, bool, 0444);
+MODULE_PARM_DESC(header,
+               "Include builtin swap header (default 0, without header)");
+
+static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background);
+
+static loff_t mtdswap_eb_offset(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       return (loff_t)(eb - d->eb_data) * d->mtd->erasesize;
+}
+
+static void mtdswap_eb_detach(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       unsigned int oldidx;
+       struct mtdswap_tree *tp;
+
+       if (eb->root) {
+               tp = container_of(eb->root, struct mtdswap_tree, root);
+               oldidx = tp - &d->trees[0];
+
+               d->trees[oldidx].count--;
+               rb_erase(&eb->rb, eb->root);
+       }
+}
+
+static void __mtdswap_rb_add(struct rb_root *root, struct swap_eb *eb)
+{
+       struct rb_node **p, *parent = NULL;
+       struct swap_eb *cur;
+
+       p = &root->rb_node;
+       while (*p) {
+               parent = *p;
+               cur = rb_entry(parent, struct swap_eb, rb);
+               if (eb->erase_count > cur->erase_count)
+                       p = &(*p)->rb_right;
+               else
+                       p = &(*p)->rb_left;
+       }
+
+       rb_link_node(&eb->rb, parent, p);
+       rb_insert_color(&eb->rb, root);
+}
+
+static void mtdswap_rb_add(struct mtdswap_dev *d, struct swap_eb *eb, int idx)
+{
+       struct rb_root *root;
+
+       if (eb->root == &d->trees[idx].root)
+               return;
+
+       mtdswap_eb_detach(d, eb);
+       root = &d->trees[idx].root;
+       __mtdswap_rb_add(root, eb);
+       eb->root = root;
+       d->trees[idx].count++;
+}
+
+static struct rb_node *mtdswap_rb_index(struct rb_root *root, unsigned int idx)
+{
+       struct rb_node *p;
+       unsigned int i;
+
+       p = rb_first(root);
+       i = 0;
+       while (i < idx && p) {
+               p = rb_next(p);
+               i++;
+       }
+
+       return p;
+}
+
+static int mtdswap_handle_badblock(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       int ret;
+       loff_t offset;
+
+       d->spare_eblks--;
+       eb->flags |= EBLOCK_BAD;
+       mtdswap_eb_detach(d, eb);
+       eb->root = NULL;
+
+       /* badblocks not supported */
+       if (!d->mtd->block_markbad)
+               return 1;
+
+       offset = mtdswap_eb_offset(d, eb);
+       dev_warn(d->dev, "Marking bad block at %08llx\n", offset);
+       ret = d->mtd->block_markbad(d->mtd, offset);
+
+       if (ret) {
+               dev_warn(d->dev, "Mark block bad failed for block at %08llx "
+                       "error %d\n", offset, ret);
+               return ret;
+       }
+
+       return 1;
+
+}
+
+static int mtdswap_handle_write_error(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       unsigned int marked = eb->flags & EBLOCK_FAILED;
+       struct swap_eb *curr_write = d->curr_write;
+
+       eb->flags |= EBLOCK_FAILED;
+       if (curr_write == eb) {
+               d->curr_write = NULL;
+
+               if (!marked && d->curr_write_pos != 0) {
+                       mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+                       return 0;
+               }
+       }
+
+       return mtdswap_handle_badblock(d, eb);
+}
+
+static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from,
+                       struct mtd_oob_ops *ops)
+{
+       int ret = d->mtd->read_oob(d->mtd, from, ops);
+
+       if (ret == -EUCLEAN)
+               return ret;
+
+       if (ret) {
+               dev_warn(d->dev, "Read OOB failed %d for block at %08llx\n",
+                       ret, from);
+               return ret;
+       }
+
+       if (ops->oobretlen < ops->ooblen) {
+               dev_warn(d->dev, "Read OOB return short read (%zd bytes not "
+                       "%zd) for block at %08llx\n",
+                       ops->oobretlen, ops->ooblen, from);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       struct mtdswap_oobdata *data, *data2;
+       int ret;
+       loff_t offset;
+       struct mtd_oob_ops ops;
+
+       offset = mtdswap_eb_offset(d, eb);
+
+       /* Check first if the block is bad. */
+       if (d->mtd->block_isbad && d->mtd->block_isbad(d->mtd, offset))
+               return MTDSWAP_SCANNED_BAD;
+
+       ops.ooblen = 2 * d->mtd->ecclayout->oobavail;
+       ops.oobbuf = d->oob_buf;
+       ops.ooboffs = 0;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_AUTO;
+
+       ret = mtdswap_read_oob(d, offset, &ops);
+
+       if (ret && ret != -EUCLEAN)
+               return ret;
+
+       data = (struct mtdswap_oobdata *)d->oob_buf;
+       data2 = (struct mtdswap_oobdata *)
+               (d->oob_buf + d->mtd->ecclayout->oobavail);
+
+       if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) {
+               eb->erase_count = le32_to_cpu(data->count);
+               if (ret == -EUCLEAN)
+                       ret = MTDSWAP_SCANNED_BITFLIP;
+               else {
+                       if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY)
+                               ret = MTDSWAP_SCANNED_DIRTY;
+                       else
+                               ret = MTDSWAP_SCANNED_CLEAN;
+               }
+       } else {
+               eb->flags |= EBLOCK_NOMAGIC;
+               ret = MTDSWAP_SCANNED_DIRTY;
+       }
+
+       return ret;
+}
+
+static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
+                               u16 marker)
+{
+       struct mtdswap_oobdata n;
+       int ret;
+       loff_t offset;
+       struct mtd_oob_ops ops;
+
+       ops.ooboffs = 0;
+       ops.oobbuf = (uint8_t *)&n;
+       ops.mode = MTD_OOB_AUTO;
+       ops.datbuf = NULL;
+
+       if (marker == MTDSWAP_TYPE_CLEAN) {
+               n.magic = cpu_to_le16(MTDSWAP_MAGIC_CLEAN);
+               n.count = cpu_to_le32(eb->erase_count);
+               ops.ooblen = MTDSWAP_OOBSIZE;
+               offset = mtdswap_eb_offset(d, eb);
+       } else {
+               n.magic = cpu_to_le16(MTDSWAP_MAGIC_DIRTY);
+               ops.ooblen = sizeof(n.magic);
+               offset = mtdswap_eb_offset(d, eb) + d->mtd->writesize;
+       }
+
+       ret = d->mtd->write_oob(d->mtd, offset , &ops);
+
+       if (ret) {
+               dev_warn(d->dev, "Write OOB failed for block at %08llx "
+                       "error %d\n", offset, ret);
+               if (ret == -EIO || ret == -EBADMSG)
+                       mtdswap_handle_write_error(d, eb);
+               return ret;
+       }
+
+       if (ops.oobretlen != ops.ooblen) {
+               dev_warn(d->dev, "Short OOB write for block at %08llx: "
+                       "%zd not %zd\n",
+                       offset, ops.oobretlen, ops.ooblen);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Are there any erase blocks without MAGIC_CLEAN header, presumably
+ * because power was cut off after erase but before header write? We
+ * need to guestimate the erase count.
+ */
+static void mtdswap_check_counts(struct mtdswap_dev *d)
+{
+       struct rb_root hist_root = RB_ROOT;
+       struct rb_node *medrb;
+       struct swap_eb *eb;
+       unsigned int i, cnt, median;
+
+       cnt = 0;
+       for (i = 0; i < d->eblks; i++) {
+               eb = d->eb_data + i;
+
+               if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR))
+                       continue;
+
+               __mtdswap_rb_add(&hist_root, eb);
+               cnt++;
+       }
+
+       if (cnt == 0)
+               return;
+
+       medrb = mtdswap_rb_index(&hist_root, cnt / 2);
+       median = rb_entry(medrb, struct swap_eb, rb)->erase_count;
+
+       d->max_erase_count = MTDSWAP_ECNT_MAX(&hist_root);
+
+       for (i = 0; i < d->eblks; i++) {
+               eb = d->eb_data + i;
+
+               if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_READERR))
+                       eb->erase_count = median;
+
+               if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR))
+                       continue;
+
+               rb_erase(&eb->rb, &hist_root);
+       }
+}
+
+static void mtdswap_scan_eblks(struct mtdswap_dev *d)
+{
+       int status;
+       unsigned int i, idx;
+       struct swap_eb *eb;
+
+       for (i = 0; i < d->eblks; i++) {
+               eb = d->eb_data + i;
+
+               status = mtdswap_read_markers(d, eb);
+               if (status < 0)
+                       eb->flags |= EBLOCK_READERR;
+               else if (status == MTDSWAP_SCANNED_BAD) {
+                       eb->flags |= EBLOCK_BAD;
+                       continue;
+               }
+
+               switch (status) {
+               case MTDSWAP_SCANNED_CLEAN:
+                       idx = MTDSWAP_CLEAN;
+                       break;
+               case MTDSWAP_SCANNED_DIRTY:
+               case MTDSWAP_SCANNED_BITFLIP:
+                       idx = MTDSWAP_DIRTY;
+                       break;
+               default:
+                       idx = MTDSWAP_FAILING;
+               }
+
+               eb->flags |= (idx << EBLOCK_IDX_SHIFT);
+       }
+
+       mtdswap_check_counts(d);
+
+       for (i = 0; i < d->eblks; i++) {
+               eb = d->eb_data + i;
+
+               if (eb->flags & EBLOCK_BAD)
+                       continue;
+
+               idx = eb->flags >> EBLOCK_IDX_SHIFT;
+               mtdswap_rb_add(d, eb, idx);
+       }
+}
+
+/*
+ * Place eblk into a tree corresponding to its number of active blocks
+ * it contains.
+ */
+static void mtdswap_store_eb(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       unsigned int weight = eb->active_count;
+       unsigned int maxweight = d->pages_per_eblk;
+
+       if (eb == d->curr_write)
+               return;
+
+       if (eb->flags & EBLOCK_BITFLIP)
+               mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
+       else if (eb->flags & (EBLOCK_READERR | EBLOCK_FAILED))
+               mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+       if (weight == maxweight)
+               mtdswap_rb_add(d, eb, MTDSWAP_USED);
+       else if (weight == 0)
+               mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
+       else if (weight > (maxweight/2))
+               mtdswap_rb_add(d, eb, MTDSWAP_LOWFRAG);
+       else
+               mtdswap_rb_add(d, eb, MTDSWAP_HIFRAG);
+}
+
+
+static void mtdswap_erase_callback(struct erase_info *done)
+{
+       wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
+       wake_up(wait_q);
+}
+
+static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       struct mtd_info *mtd = d->mtd;
+       struct erase_info erase;
+       wait_queue_head_t wq;
+       unsigned int retries = 0;
+       int ret;
+
+       eb->erase_count++;
+       if (eb->erase_count > d->max_erase_count)
+               d->max_erase_count = eb->erase_count;
+
+retry:
+       init_waitqueue_head(&wq);
+       memset(&erase, 0, sizeof(struct erase_info));
+
+       erase.mtd       = mtd;
+       erase.callback  = mtdswap_erase_callback;
+       erase.addr      = mtdswap_eb_offset(d, eb);
+       erase.len       = mtd->erasesize;
+       erase.priv      = (u_long)&wq;
+
+       ret = mtd->erase(mtd, &erase);
+       if (ret) {
+               if (retries++ < MTDSWAP_ERASE_RETRIES) {
+                       dev_warn(d->dev,
+                               "erase of erase block %#llx on %s failed",
+                               erase.addr, mtd->name);
+                       yield();
+                       goto retry;
+               }
+
+               dev_err(d->dev, "Cannot erase erase block %#llx on %s\n",
+                       erase.addr, mtd->name);
+
+               mtdswap_handle_badblock(d, eb);
+               return -EIO;
+       }
+
+       ret = wait_event_interruptible(wq, erase.state == MTD_ERASE_DONE ||
+                                          erase.state == MTD_ERASE_FAILED);
+       if (ret) {
+               dev_err(d->dev, "Interrupted erase block %#llx erassure on %s",
+                       erase.addr, mtd->name);
+               return -EINTR;
+       }
+
+       if (erase.state == MTD_ERASE_FAILED) {
+               if (retries++ < MTDSWAP_ERASE_RETRIES) {
+                       dev_warn(d->dev,
+                               "erase of erase block %#llx on %s failed",
+                               erase.addr, mtd->name);
+                       yield();
+                       goto retry;
+               }
+
+               mtdswap_handle_badblock(d, eb);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,
+                               unsigned int *block)
+{
+       int ret;
+       struct swap_eb *old_eb = d->curr_write;
+       struct rb_root *clean_root;
+       struct swap_eb *eb;
+
+       if (old_eb == NULL || d->curr_write_pos >= d->pages_per_eblk) {
+               do {
+                       if (TREE_EMPTY(d, CLEAN))
+                               return -ENOSPC;
+
+                       clean_root = TREE_ROOT(d, CLEAN);
+                       eb = rb_entry(rb_first(clean_root), struct swap_eb, rb);
+                       rb_erase(&eb->rb, clean_root);
+                       eb->root = NULL;
+                       TREE_COUNT(d, CLEAN)--;
+
+                       ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY);
+               } while (ret == -EIO || ret == -EBADMSG);
+
+               if (ret)
+                       return ret;
+
+               d->curr_write_pos = 0;
+               d->curr_write = eb;
+               if (old_eb)
+                       mtdswap_store_eb(d, old_eb);
+       }
+
+       *block = (d->curr_write - d->eb_data) * d->pages_per_eblk +
+               d->curr_write_pos;
+
+       d->curr_write->active_count++;
+       d->revmap[*block] = page;
+       d->curr_write_pos++;
+
+       return 0;
+}
+
+static unsigned int mtdswap_free_page_cnt(struct mtdswap_dev *d)
+{
+       return TREE_COUNT(d, CLEAN) * d->pages_per_eblk +
+               d->pages_per_eblk - d->curr_write_pos;
+}
+
+static unsigned int mtdswap_enough_free_pages(struct mtdswap_dev *d)
+{
+       return mtdswap_free_page_cnt(d) > d->pages_per_eblk;
+}
+
+static int mtdswap_write_block(struct mtdswap_dev *d, char *buf,
+                       unsigned int page, unsigned int *bp, int gc_context)
+{
+       struct mtd_info *mtd = d->mtd;
+       struct swap_eb *eb;
+       size_t retlen;
+       loff_t writepos;
+       int ret;
+
+retry:
+       if (!gc_context)
+               while (!mtdswap_enough_free_pages(d))
+                       if (mtdswap_gc(d, 0) > 0)
+                               return -ENOSPC;
+
+       ret = mtdswap_map_free_block(d, page, bp);
+       eb = d->eb_data + (*bp / d->pages_per_eblk);
+
+       if (ret == -EIO || ret == -EBADMSG) {
+               d->curr_write = NULL;
+               eb->active_count--;
+               d->revmap[*bp] = PAGE_UNDEF;
+               goto retry;
+       }
+
+       if (ret < 0)
+               return ret;
+
+       writepos = (loff_t)*bp << PAGE_SHIFT;
+       ret =  mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf);
+       if (ret == -EIO || ret == -EBADMSG) {
+               d->curr_write_pos--;
+               eb->active_count--;
+               d->revmap[*bp] = PAGE_UNDEF;
+               mtdswap_handle_write_error(d, eb);
+               goto retry;
+       }
+
+       if (ret < 0) {
+               dev_err(d->dev, "Write to MTD device failed: %d (%zd written)",
+                       ret, retlen);
+               goto err;
+       }
+
+       if (retlen != PAGE_SIZE) {
+               dev_err(d->dev, "Short write to MTD device: %zd written",
+                       retlen);
+               ret = -EIO;
+               goto err;
+       }
+
+       return ret;
+
+err:
+       d->curr_write_pos--;
+       eb->active_count--;
+       d->revmap[*bp] = PAGE_UNDEF;
+
+       return ret;
+}
+
+static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock,
+               unsigned int *newblock)
+{
+       struct mtd_info *mtd = d->mtd;
+       struct swap_eb *eb, *oldeb;
+       int ret;
+       size_t retlen;
+       unsigned int page, retries;
+       loff_t readpos;
+
+       page = d->revmap[oldblock];
+       readpos = (loff_t) oldblock << PAGE_SHIFT;
+       retries = 0;
+
+retry:
+       ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf);
+
+       if (ret < 0 && ret != -EUCLEAN) {
+               oldeb = d->eb_data + oldblock / d->pages_per_eblk;
+               oldeb->flags |= EBLOCK_READERR;
+
+               dev_err(d->dev, "Read Error: %d (block %u)\n", ret,
+                       oldblock);
+               retries++;
+               if (retries < MTDSWAP_IO_RETRIES)
+                       goto retry;
+
+               goto read_error;
+       }
+
+       if (retlen != PAGE_SIZE) {
+               dev_err(d->dev, "Short read: %zd (block %u)\n", retlen,
+                      oldblock);
+               ret = -EIO;
+               goto read_error;
+       }
+
+       ret = mtdswap_write_block(d, d->page_buf, page, newblock, 1);
+       if (ret < 0) {
+               d->page_data[page] = BLOCK_ERROR;
+               dev_err(d->dev, "Write error: %d\n", ret);
+               return ret;
+       }
+
+       eb = d->eb_data + *newblock / d->pages_per_eblk;
+       d->page_data[page] = *newblock;
+       d->revmap[oldblock] = PAGE_UNDEF;
+       eb = d->eb_data + oldblock / d->pages_per_eblk;
+       eb->active_count--;
+
+       return 0;
+
+read_error:
+       d->page_data[page] = BLOCK_ERROR;
+       d->revmap[oldblock] = PAGE_UNDEF;
+       return ret;
+}
+
+static int mtdswap_gc_eblock(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+       unsigned int i, block, eblk_base, newblock;
+       int ret, errcode;
+
+       errcode = 0;
+       eblk_base = (eb - d->eb_data) * d->pages_per_eblk;
+
+       for (i = 0; i < d->pages_per_eblk; i++) {
+               if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+                       return -ENOSPC;
+
+               block = eblk_base + i;
+               if (d->revmap[block] == PAGE_UNDEF)
+                       continue;
+
+               ret = mtdswap_move_block(d, block, &newblock);
+               if (ret < 0 && !errcode)
+                       errcode = ret;
+       }
+
+       return errcode;
+}
+
+static int __mtdswap_choose_gc_tree(struct mtdswap_dev *d)
+{
+       int idx, stopat;
+
+       if (TREE_COUNT(d, CLEAN) < LOW_FRAG_GC_TRESHOLD)
+               stopat = MTDSWAP_LOWFRAG;
+       else
+               stopat = MTDSWAP_HIFRAG;
+
+       for (idx = MTDSWAP_BITFLIP; idx >= stopat; idx--)
+               if (d->trees[idx].root.rb_node != NULL)
+                       return idx;
+
+       return -1;
+}
+
+static int mtdswap_wlfreq(unsigned int maxdiff)
+{
+       unsigned int h, x, y, dist, base;
+
+       /*
+        * Calculate linear ramp down from f1 to f2 when maxdiff goes from
+        * MAX_ERASE_DIFF to MAX_ERASE_DIFF + COLLECT_NONDIRTY_BASE.  Similar
+        * to triangle with height f1 - f1 and width COLLECT_NONDIRTY_BASE.
+        */
+
+       dist = maxdiff - MAX_ERASE_DIFF;
+       if (dist > COLLECT_NONDIRTY_BASE)
+               dist = COLLECT_NONDIRTY_BASE;
+
+       /*
+        * Modelling the slop as right angular triangle with base
+        * COLLECT_NONDIRTY_BASE and height freq1 - freq2. The ratio y/x is
+        * equal to the ratio h/base.
+        */
+       h = COLLECT_NONDIRTY_FREQ1 - COLLECT_NONDIRTY_FREQ2;
+       base = COLLECT_NONDIRTY_BASE;
+
+       x = dist - base;
+       y = (x * h + base / 2) / base;
+
+       return COLLECT_NONDIRTY_FREQ2 + y;
+}
+
+static int mtdswap_choose_wl_tree(struct mtdswap_dev *d)
+{
+       static unsigned int pick_cnt;
+       unsigned int i, idx = -1, wear, max;
+       struct rb_root *root;
+
+       max = 0;
+       for (i = 0; i <= MTDSWAP_DIRTY; i++) {
+               root = &d->trees[i].root;
+               if (root->rb_node == NULL)
+                       continue;
+
+               wear = d->max_erase_count - MTDSWAP_ECNT_MIN(root);
+               if (wear > max) {
+                       max = wear;
+                       idx = i;
+               }
+       }
+
+       if (max > MAX_ERASE_DIFF && pick_cnt >= mtdswap_wlfreq(max) - 1) {
+               pick_cnt = 0;
+               return idx;
+       }
+
+       pick_cnt++;
+       return -1;
+}
+
+static int mtdswap_choose_gc_tree(struct mtdswap_dev *d,
+                               unsigned int background)
+{
+       int idx;
+
+       if (TREE_NONEMPTY(d, FAILING) &&
+               (background || (TREE_EMPTY(d, CLEAN) && TREE_EMPTY(d, DIRTY))))
+               return MTDSWAP_FAILING;
+
+       idx = mtdswap_choose_wl_tree(d);
+       if (idx >= MTDSWAP_CLEAN)
+               return idx;
+
+       return __mtdswap_choose_gc_tree(d);
+}
+
+static struct swap_eb *mtdswap_pick_gc_eblk(struct mtdswap_dev *d,
+                                       unsigned int background)
+{
+       struct rb_root *rp = NULL;
+       struct swap_eb *eb = NULL;
+       int idx;
+
+       if (background && TREE_COUNT(d, CLEAN) > CLEAN_BLOCK_THRESHOLD &&
+               TREE_EMPTY(d, DIRTY) && TREE_EMPTY(d, FAILING))
+               return NULL;
+
+       idx = mtdswap_choose_gc_tree(d, background);
+       if (idx < 0)
+               return NULL;
+
+       rp = &d->trees[idx].root;
+       eb = rb_entry(rb_first(rp), struct swap_eb, rb);
+
+       rb_erase(&eb->rb, rp);
+       eb->root = NULL;
+       d->trees[idx].count--;
+       return eb;
+}
+
+static unsigned int mtdswap_test_patt(unsigned int i)
+{
+       return i % 2 ? 0x55555555 : 0xAAAAAAAA;
+}
+
+static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
+                                       struct swap_eb *eb)
+{
+       struct mtd_info *mtd = d->mtd;
+       unsigned int test, i, j, patt, mtd_pages;
+       loff_t base, pos;
+       unsigned int *p1 = (unsigned int *)d->page_buf;
+       unsigned char *p2 = (unsigned char *)d->oob_buf;
+       struct mtd_oob_ops ops;
+       int ret;
+
+       ops.mode = MTD_OOB_AUTO;
+       ops.len = mtd->writesize;
+       ops.ooblen = mtd->ecclayout->oobavail;
+       ops.ooboffs = 0;
+       ops.datbuf = d->page_buf;
+       ops.oobbuf = d->oob_buf;
+       base = mtdswap_eb_offset(d, eb);
+       mtd_pages = d->pages_per_eblk * PAGE_SIZE / mtd->writesize;
+
+       for (test = 0; test < 2; test++) {
+               pos = base;
+               for (i = 0; i < mtd_pages; i++) {
+                       patt = mtdswap_test_patt(test + i);
+                       memset(d->page_buf, patt, mtd->writesize);
+                       memset(d->oob_buf, patt, mtd->ecclayout->oobavail);
+                       ret = mtd->write_oob(mtd, pos, &ops);
+                       if (ret)
+                               goto error;
+
+                       pos += mtd->writesize;
+               }
+
+               pos = base;
+               for (i = 0; i < mtd_pages; i++) {
+                       ret = mtd->read_oob(mtd, pos, &ops);
+                       if (ret)
+                               goto error;
+
+                       patt = mtdswap_test_patt(test + i);
+                       for (j = 0; j < mtd->writesize/sizeof(int); j++)
+                               if (p1[j] != patt)
+                                       goto error;
+
+                       for (j = 0; j < mtd->ecclayout->oobavail; j++)
+                               if (p2[j] != (unsigned char)patt)
+                                       goto error;
+
+                       pos += mtd->writesize;
+               }
+
+               ret = mtdswap_erase_block(d, eb);
+               if (ret)
+                       goto error;
+       }
+
+       eb->flags &= ~EBLOCK_READERR;
+       return 1;
+
+error:
+       mtdswap_handle_badblock(d, eb);
+       return 0;
+}
+
+static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)
+{
+       struct swap_eb *eb;
+       int ret;
+
+       if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+               return 1;
+
+       eb = mtdswap_pick_gc_eblk(d, background);
+       if (!eb)
+               return 1;
+
+       ret = mtdswap_gc_eblock(d, eb);
+       if (ret == -ENOSPC)
+               return 1;
+
+       if (eb->flags & EBLOCK_FAILED) {
+               mtdswap_handle_badblock(d, eb);
+               return 0;
+       }
+
+       eb->flags &= ~EBLOCK_BITFLIP;
+       ret = mtdswap_erase_block(d, eb);
+       if ((eb->flags & EBLOCK_READERR) &&
+               (ret || !mtdswap_eblk_passes(d, eb)))
+               return 0;
+
+       if (ret == 0)
+               ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_CLEAN);
+
+       if (ret == 0)
+               mtdswap_rb_add(d, eb, MTDSWAP_CLEAN);
+       else if (ret != -EIO && ret != -EBADMSG)
+               mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
+
+       return 0;
+}
+
+static void mtdswap_background(struct mtd_blktrans_dev *dev)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+       int ret;
+
+       while (1) {
+               ret = mtdswap_gc(d, 1);
+               if (ret || mtd_blktrans_cease_background(dev))
+                       return;
+       }
+}
+
+static void mtdswap_cleanup(struct mtdswap_dev *d)
+{
+       vfree(d->eb_data);
+       vfree(d->revmap);
+       vfree(d->page_data);
+       kfree(d->oob_buf);
+       kfree(d->page_buf);
+}
+
+static int mtdswap_flush(struct mtd_blktrans_dev *dev)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+
+       if (d->mtd->sync)
+               d->mtd->sync(d->mtd);
+       return 0;
+}
+
+static unsigned int mtdswap_badblocks(struct mtd_info *mtd, uint64_t size)
+{
+       loff_t offset;
+       unsigned int badcnt;
+
+       badcnt = 0;
+
+       if (mtd->block_isbad)
+               for (offset = 0; offset < size; offset += mtd->erasesize)
+                       if (mtd->block_isbad(mtd, offset))
+                               badcnt++;
+
+       return badcnt;
+}
+
+static int mtdswap_writesect(struct mtd_blktrans_dev *dev,
+                       unsigned long page, char *buf)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+       unsigned int newblock, mapped;
+       struct swap_eb *eb;
+       int ret;
+
+       d->sect_write_count++;
+
+       if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+               return -ENOSPC;
+
+       if (header) {
+               /* Ignore writes to the header page */
+               if (unlikely(page == 0))
+                       return 0;
+
+               page--;
+       }
+
+       mapped = d->page_data[page];
+       if (mapped <= BLOCK_MAX) {
+               eb = d->eb_data + (mapped / d->pages_per_eblk);
+               eb->active_count--;
+               mtdswap_store_eb(d, eb);
+               d->page_data[page] = BLOCK_UNDEF;
+               d->revmap[mapped] = PAGE_UNDEF;
+       }
+
+       ret = mtdswap_write_block(d, buf, page, &newblock, 0);
+       d->mtd_write_count++;
+
+       if (ret < 0)
+               return ret;
+
+       eb = d->eb_data + (newblock / d->pages_per_eblk);
+       d->page_data[page] = newblock;
+
+       return 0;
+}
+
+/* Provide a dummy swap header for the kernel */
+static int mtdswap_auto_header(struct mtdswap_dev *d, char *buf)
+{
+       union swap_header *hd = (union swap_header *)(buf);
+
+       memset(buf, 0, PAGE_SIZE - 10);
+
+       hd->info.version = 1;
+       hd->info.last_page = d->mbd_dev->size - 1;
+       hd->info.nr_badpages = 0;
+
+       memcpy(buf + PAGE_SIZE - 10, "SWAPSPACE2", 10);
+
+       return 0;
+}
+
+static int mtdswap_readsect(struct mtd_blktrans_dev *dev,
+                       unsigned long page, char *buf)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+       struct mtd_info *mtd = d->mtd;
+       unsigned int realblock, retries;
+       loff_t readpos;
+       struct swap_eb *eb;
+       size_t retlen;
+       int ret;
+
+       d->sect_read_count++;
+
+       if (header) {
+               if (unlikely(page == 0))
+                       return mtdswap_auto_header(d, buf);
+
+               page--;
+       }
+
+       realblock = d->page_data[page];
+       if (realblock > BLOCK_MAX) {
+               memset(buf, 0x0, PAGE_SIZE);
+               if (realblock == BLOCK_UNDEF)
+                       return 0;
+               else
+                       return -EIO;
+       }
+
+       eb = d->eb_data + (realblock / d->pages_per_eblk);
+       BUG_ON(d->revmap[realblock] == PAGE_UNDEF);
+
+       readpos = (loff_t)realblock << PAGE_SHIFT;
+       retries = 0;
+
+retry:
+       ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf);
+
+       d->mtd_read_count++;
+       if (ret == -EUCLEAN) {
+               eb->flags |= EBLOCK_BITFLIP;
+               mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
+               ret = 0;
+       }
+
+       if (ret < 0) {
+               dev_err(d->dev, "Read error %d\n", ret);
+               eb->flags |= EBLOCK_READERR;
+               mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+               retries++;
+               if (retries < MTDSWAP_IO_RETRIES)
+                       goto retry;
+
+               return ret;
+       }
+
+       if (retlen != PAGE_SIZE) {
+               dev_err(d->dev, "Short read %zd\n", retlen);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mtdswap_discard(struct mtd_blktrans_dev *dev, unsigned long first,
+                       unsigned nr_pages)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+       unsigned long page;
+       struct swap_eb *eb;
+       unsigned int mapped;
+
+       d->discard_count++;
+
+       for (page = first; page < first + nr_pages; page++) {
+               mapped = d->page_data[page];
+               if (mapped <= BLOCK_MAX) {
+                       eb = d->eb_data + (mapped / d->pages_per_eblk);
+                       eb->active_count--;
+                       mtdswap_store_eb(d, eb);
+                       d->page_data[page] = BLOCK_UNDEF;
+                       d->revmap[mapped] = PAGE_UNDEF;
+                       d->discard_page_count++;
+               } else if (mapped == BLOCK_ERROR) {
+                       d->page_data[page] = BLOCK_UNDEF;
+                       d->discard_page_count++;
+               }
+       }
+
+       return 0;
+}
+
+static int mtdswap_show(struct seq_file *s, void *data)
+{
+       struct mtdswap_dev *d = (struct mtdswap_dev *) s->private;
+       unsigned long sum;
+       unsigned int count[MTDSWAP_TREE_CNT];
+       unsigned int min[MTDSWAP_TREE_CNT];
+       unsigned int max[MTDSWAP_TREE_CNT];
+       unsigned int i, cw = 0, cwp = 0, cwecount = 0, bb_cnt, mapped, pages;
+       uint64_t use_size;
+       char *name[] = {"clean", "used", "low", "high", "dirty", "bitflip",
+                       "failing"};
+
+       mutex_lock(&d->mbd_dev->lock);
+
+       for (i = 0; i < MTDSWAP_TREE_CNT; i++) {
+               struct rb_root *root = &d->trees[i].root;
+
+               if (root->rb_node) {
+                       count[i] = d->trees[i].count;
+                       min[i] = rb_entry(rb_first(root), struct swap_eb,
+                                       rb)->erase_count;
+                       max[i] = rb_entry(rb_last(root), struct swap_eb,
+                                       rb)->erase_count;
+               } else
+                       count[i] = 0;
+       }
+
+       if (d->curr_write) {
+               cw = 1;
+               cwp = d->curr_write_pos;
+               cwecount = d->curr_write->erase_count;
+       }
+
+       sum = 0;
+       for (i = 0; i < d->eblks; i++)
+               sum += d->eb_data[i].erase_count;
+
+       use_size = (uint64_t)d->eblks * d->mtd->erasesize;
+       bb_cnt = mtdswap_badblocks(d->mtd, use_size);
+
+       mapped = 0;
+       pages = d->mbd_dev->size;
+       for (i = 0; i < pages; i++)
+               if (d->page_data[i] != BLOCK_UNDEF)
+                       mapped++;
+
+       mutex_unlock(&d->mbd_dev->lock);
+
+       for (i = 0; i < MTDSWAP_TREE_CNT; i++) {
+               if (!count[i])
+                       continue;
+
+               if (min[i] != max[i])
+                       seq_printf(s, "%s:\t%5d erase blocks, erased min %d, "
+                               "max %d times\n",
+                               name[i], count[i], min[i], max[i]);
+               else
+                       seq_printf(s, "%s:\t%5d erase blocks, all erased %d "
+                               "times\n", name[i], count[i], min[i]);
+       }
+
+       if (bb_cnt)
+               seq_printf(s, "bad:\t%5u erase blocks\n", bb_cnt);
+
+       if (cw)
+               seq_printf(s, "current erase block: %u pages used, %u free, "
+                       "erased %u times\n",
+                       cwp, d->pages_per_eblk - cwp, cwecount);
+
+       seq_printf(s, "total erasures: %lu\n", sum);
+
+       seq_printf(s, "\n");
+
+       seq_printf(s, "mtdswap_readsect count: %llu\n", d->sect_read_count);
+       seq_printf(s, "mtdswap_writesect count: %llu\n", d->sect_write_count);
+       seq_printf(s, "mtdswap_discard count: %llu\n", d->discard_count);
+       seq_printf(s, "mtd read count: %llu\n", d->mtd_read_count);
+       seq_printf(s, "mtd write count: %llu\n", d->mtd_write_count);
+       seq_printf(s, "discarded pages count: %llu\n", d->discard_page_count);
+
+       seq_printf(s, "\n");
+       seq_printf(s, "total pages: %u\n", pages);
+       seq_printf(s, "pages mapped: %u\n", mapped);
+
+       return 0;
+}
+
+static int mtdswap_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mtdswap_show, inode->i_private);
+}
+
+static const struct file_operations mtdswap_fops = {
+       .open           = mtdswap_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int mtdswap_add_debugfs(struct mtdswap_dev *d)
+{
+       struct gendisk *gd = d->mbd_dev->disk;
+       struct device *dev = disk_to_dev(gd);
+
+       struct dentry *root;
+       struct dentry *dent;
+
+       root = debugfs_create_dir(gd->disk_name, NULL);
+       if (IS_ERR(root))
+               return 0;
+
+       if (!root) {
+               dev_err(dev, "failed to initialize debugfs\n");
+               return -1;
+       }
+
+       d->debugfs_root = root;
+
+       dent = debugfs_create_file("stats", S_IRUSR, root, d,
+                               &mtdswap_fops);
+       if (!dent) {
+               dev_err(d->dev, "debugfs_create_file failed\n");
+               debugfs_remove_recursive(root);
+               d->debugfs_root = NULL;
+               return -1;
+       }
+
+       return 0;
+}
+
+static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
+                       unsigned int spare_cnt)
+{
+       struct mtd_info *mtd = d->mbd_dev->mtd;
+       unsigned int i, eblk_bytes, pages, blocks;
+       int ret = -ENOMEM;
+
+       d->mtd = mtd;
+       d->eblks = eblocks;
+       d->spare_eblks = spare_cnt;
+       d->pages_per_eblk = mtd->erasesize >> PAGE_SHIFT;
+
+       pages = d->mbd_dev->size;
+       blocks = eblocks * d->pages_per_eblk;
+
+       for (i = 0; i < MTDSWAP_TREE_CNT; i++)
+               d->trees[i].root = RB_ROOT;
+
+       d->page_data = vmalloc(sizeof(int)*pages);
+       if (!d->page_data)
+               goto page_data_fail;
+
+       d->revmap = vmalloc(sizeof(int)*blocks);
+       if (!d->revmap)
+               goto revmap_fail;
+
+       eblk_bytes = sizeof(struct swap_eb)*d->eblks;
+       d->eb_data = vmalloc(eblk_bytes);
+       if (!d->eb_data)
+               goto eb_data_fail;
+
+       memset(d->eb_data, 0, eblk_bytes);
+       for (i = 0; i < pages; i++)
+               d->page_data[i] = BLOCK_UNDEF;
+
+       for (i = 0; i < blocks; i++)
+               d->revmap[i] = PAGE_UNDEF;
+
+       d->page_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!d->page_buf)
+               goto page_buf_fail;
+
+       d->oob_buf = kmalloc(2 * mtd->ecclayout->oobavail, GFP_KERNEL);
+       if (!d->oob_buf)
+               goto oob_buf_fail;
+
+       mtdswap_scan_eblks(d);
+
+       return 0;
+
+oob_buf_fail:
+       kfree(d->page_buf);
+page_buf_fail:
+       vfree(d->eb_data);
+eb_data_fail:
+       vfree(d->revmap);
+revmap_fail:
+       vfree(d->page_data);
+page_data_fail:
+       printk(KERN_ERR "%s: init failed (%d)\n", MTDSWAP_PREFIX, ret);
+       return ret;
+}
+
+static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
+{
+       struct mtdswap_dev *d;
+       struct mtd_blktrans_dev *mbd_dev;
+       char *parts;
+       char *this_opt;
+       unsigned long part;
+       unsigned int eblocks, eavailable, bad_blocks, spare_cnt;
+       uint64_t swap_size, use_size, size_limit;
+       struct nand_ecclayout *oinfo;
+       int ret;
+
+       parts = &partitions[0];
+       if (!*parts)
+               return;
+
+       while ((this_opt = strsep(&parts, ",")) != NULL) {
+               if (strict_strtoul(this_opt, 0, &part) < 0)
+                       return;
+
+               if (mtd->index == part)
+                       break;
+       }
+
+       if (mtd->index != part)
+               return;
+
+       if (mtd->erasesize < PAGE_SIZE || mtd->erasesize % PAGE_SIZE) {
+               printk(KERN_ERR "%s: Erase size %u not multiple of PAGE_SIZE "
+                       "%lu\n", MTDSWAP_PREFIX, mtd->erasesize, PAGE_SIZE);
+               return;
+       }
+
+       if (PAGE_SIZE % mtd->writesize || mtd->writesize > PAGE_SIZE) {
+               printk(KERN_ERR "%s: PAGE_SIZE %lu not multiple of write size"
+                       " %u\n", MTDSWAP_PREFIX, PAGE_SIZE, mtd->writesize);
+               return;
+       }
+
+       oinfo = mtd->ecclayout;
+       if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) {
+               printk(KERN_ERR "%s: Not enough free bytes in OOB, "
+                       "%d available, %lu needed.\n",
+                       MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE);
+               return;
+       }
+
+       if (spare_eblocks > 100)
+               spare_eblocks = 100;
+
+       use_size = mtd->size;
+       size_limit = (uint64_t) BLOCK_MAX * PAGE_SIZE;
+
+       if (mtd->size > size_limit) {
+               printk(KERN_WARNING "%s: Device too large. Limiting size to "
+                       "%llu bytes\n", MTDSWAP_PREFIX, size_limit);
+               use_size = size_limit;
+       }
+
+       eblocks = mtd_div_by_eb(use_size, mtd);
+       use_size = eblocks * mtd->erasesize;
+       bad_blocks = mtdswap_badblocks(mtd, use_size);
+       eavailable = eblocks - bad_blocks;
+
+       if (eavailable < MIN_ERASE_BLOCKS) {
+               printk(KERN_ERR "%s: Not enough erase blocks. %u available, "
+                       "%d needed\n", MTDSWAP_PREFIX, eavailable,
+                       MIN_ERASE_BLOCKS);
+               return;
+       }
+
+       spare_cnt = div_u64((uint64_t)eavailable * spare_eblocks, 100);
+
+       if (spare_cnt < MIN_SPARE_EBLOCKS)
+               spare_cnt = MIN_SPARE_EBLOCKS;
+
+       if (spare_cnt > eavailable - 1)
+               spare_cnt = eavailable - 1;
+
+       swap_size = (uint64_t)(eavailable - spare_cnt) * mtd->erasesize +
+               (header ? PAGE_SIZE : 0);
+
+       printk(KERN_INFO "%s: Enabling MTD swap on device %lu, size %llu KB, "
+               "%u spare, %u bad blocks\n",
+               MTDSWAP_PREFIX, part, swap_size / 1024, spare_cnt, bad_blocks);
+
+       d = kzalloc(sizeof(struct mtdswap_dev), GFP_KERNEL);
+       if (!d)
+               return;
+
+       mbd_dev = kzalloc(sizeof(struct mtd_blktrans_dev), GFP_KERNEL);
+       if (!mbd_dev) {
+               kfree(d);
+               return;
+       }
+
+       d->mbd_dev = mbd_dev;
+       mbd_dev->priv = d;
+
+       mbd_dev->mtd = mtd;
+       mbd_dev->devnum = mtd->index;
+       mbd_dev->size = swap_size >> PAGE_SHIFT;
+       mbd_dev->tr = tr;
+
+       if (!(mtd->flags & MTD_WRITEABLE))
+               mbd_dev->readonly = 1;
+
+       if (mtdswap_init(d, eblocks, spare_cnt) < 0)
+               goto init_failed;
+
+       if (add_mtd_blktrans_dev(mbd_dev) < 0)
+               goto cleanup;
+
+       d->dev = disk_to_dev(mbd_dev->disk);
+
+       ret = mtdswap_add_debugfs(d);
+       if (ret < 0)
+               goto debugfs_failed;
+
+       return;
+
+debugfs_failed:
+       del_mtd_blktrans_dev(mbd_dev);
+
+cleanup:
+       mtdswap_cleanup(d);
+
+init_failed:
+       kfree(mbd_dev);
+       kfree(d);
+}
+
+static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
+{
+       struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+
+       debugfs_remove_recursive(d->debugfs_root);
+       del_mtd_blktrans_dev(dev);
+       mtdswap_cleanup(d);
+       kfree(d);
+}
+
+static struct mtd_blktrans_ops mtdswap_ops = {
+       .name           = "mtdswap",
+       .major          = 0,
+       .part_bits      = 0,
+       .blksize        = PAGE_SIZE,
+       .flush          = mtdswap_flush,
+       .readsect       = mtdswap_readsect,
+       .writesect      = mtdswap_writesect,
+       .discard        = mtdswap_discard,
+       .background     = mtdswap_background,
+       .add_mtd        = mtdswap_add_mtd,
+       .remove_dev     = mtdswap_remove_dev,
+       .owner          = THIS_MODULE,
+};
+
+static int __init mtdswap_modinit(void)
+{
+       return register_mtd_blktrans(&mtdswap_ops);
+}
+
+static void __exit mtdswap_modexit(void)
+{
+       deregister_mtd_blktrans(&mtdswap_ops);
+}
+
+module_init(mtdswap_modinit);
+module_exit(mtdswap_modexit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
+MODULE_DESCRIPTION("Block device access to an MTD suitable for using as "
+               "swap space");
index 4f6c06f1632843ac20e7882c0cc7a346747355cc..a92054e945e1c2788559c3d2e80f47f7878e0a46 100644 (file)
@@ -31,6 +31,21 @@ config MTD_NAND_VERIFY_WRITE
          device thinks the write was successful, a bit could have been
          flipped accidentally due to device wear or something else.
 
+config MTD_NAND_BCH
+       tristate
+       select BCH
+       depends on MTD_NAND_ECC_BCH
+       default MTD_NAND
+
+config MTD_NAND_ECC_BCH
+       bool "Support software BCH ECC"
+       default n
+       help
+         This enables support for software BCH error correction. Binary BCH
+         codes are more powerful and cpu intensive than traditional Hamming
+         ECC codes. They are used with NAND devices requiring more than 1 bit
+         of error correction.
+
 config MTD_SM_COMMON
        tristate
        default n
index 8ad6faec72cb315bacc6897616a35c4a5f7154fd..5745d831168e4e6f581deb1e12bb3a5b77f456fd 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_MTD_NAND)                 += nand.o
 obj-$(CONFIG_MTD_NAND_ECC)             += nand_ecc.o
+obj-$(CONFIG_MTD_NAND_BCH)             += nand_bch.o
 obj-$(CONFIG_MTD_NAND_IDS)             += nand_ids.o
 obj-$(CONFIG_MTD_SM_COMMON)            += sm_common.o
 
index ccce0f03b5dcf50b300f621e36200d76e0e273c3..6fae04b3fc6da19a1adad5c261157b62e89fe4b2 100644 (file)
@@ -48,6 +48,9 @@
 #define no_ecc         0
 #endif
 
+static int use_dma = 1;
+module_param(use_dma, int, 0);
+
 static int on_flash_bbt = 0;
 module_param(on_flash_bbt, int, 0);
 
@@ -89,11 +92,20 @@ struct atmel_nand_host {
        struct nand_chip        nand_chip;
        struct mtd_info         mtd;
        void __iomem            *io_base;
+       dma_addr_t              io_phys;
        struct atmel_nand_data  *board;
        struct device           *dev;
        void __iomem            *ecc;
+
+       struct completion       comp;
+       struct dma_chan         *dma_chan;
 };
 
+static int cpu_has_dma(void)
+{
+       return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
+}
+
 /*
  * Enable NAND.
  */
@@ -150,7 +162,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
 /*
  * Minimal-overhead PIO for data access.
  */
-static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
 {
        struct nand_chip        *nand_chip = mtd->priv;
 
@@ -164,7 +176,7 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
        __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
 }
 
-static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
 {
        struct nand_chip        *nand_chip = mtd->priv;
 
@@ -178,6 +190,121 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
        __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
 }
 
+static void dma_complete_func(void *completion)
+{
+       complete(completion);
+}
+
+static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
+                              int is_read)
+{
+       struct dma_device *dma_dev;
+       enum dma_ctrl_flags flags;
+       dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
+       struct dma_async_tx_descriptor *tx = NULL;
+       dma_cookie_t cookie;
+       struct nand_chip *chip = mtd->priv;
+       struct atmel_nand_host *host = chip->priv;
+       void *p = buf;
+       int err = -EIO;
+       enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       if (buf >= high_memory) {
+               struct page *pg;
+
+               if (((size_t)buf & PAGE_MASK) !=
+                   ((size_t)(buf + len - 1) & PAGE_MASK)) {
+                       dev_warn(host->dev, "Buffer not fit in one page\n");
+                       goto err_buf;
+               }
+
+               pg = vmalloc_to_page(buf);
+               if (pg == 0) {
+                       dev_err(host->dev, "Failed to vmalloc_to_page\n");
+                       goto err_buf;
+               }
+               p = page_address(pg) + ((size_t)buf & ~PAGE_MASK);
+       }
+
+       dma_dev = host->dma_chan->device;
+
+       flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP |
+               DMA_COMPL_SKIP_DEST_UNMAP;
+
+       phys_addr = dma_map_single(dma_dev->dev, p, len, dir);
+       if (dma_mapping_error(dma_dev->dev, phys_addr)) {
+               dev_err(host->dev, "Failed to dma_map_single\n");
+               goto err_buf;
+       }
+
+       if (is_read) {
+               dma_src_addr = host->io_phys;
+               dma_dst_addr = phys_addr;
+       } else {
+               dma_src_addr = phys_addr;
+               dma_dst_addr = host->io_phys;
+       }
+
+       tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
+                                            dma_src_addr, len, flags);
+       if (!tx) {
+               dev_err(host->dev, "Failed to prepare DMA memcpy\n");
+               goto err_dma;
+       }
+
+       init_completion(&host->comp);
+       tx->callback = dma_complete_func;
+       tx->callback_param = &host->comp;
+
+       cookie = tx->tx_submit(tx);
+       if (dma_submit_error(cookie)) {
+               dev_err(host->dev, "Failed to do DMA tx_submit\n");
+               goto err_dma;
+       }
+
+       dma_async_issue_pending(host->dma_chan);
+       wait_for_completion(&host->comp);
+
+       err = 0;
+
+err_dma:
+       dma_unmap_single(dma_dev->dev, phys_addr, len, dir);
+err_buf:
+       if (err != 0)
+               dev_warn(host->dev, "Fall back to CPU I/O\n");
+       return err;
+}
+
+static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct atmel_nand_host *host = chip->priv;
+
+       if (use_dma && len >= mtd->oobsize)
+               if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
+                       return;
+
+       if (host->board->bus_width_16)
+               atmel_read_buf16(mtd, buf, len);
+       else
+               atmel_read_buf8(mtd, buf, len);
+}
+
+static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct atmel_nand_host *host = chip->priv;
+
+       if (use_dma && len >= mtd->oobsize)
+               if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
+                       return;
+
+       if (host->board->bus_width_16)
+               atmel_write_buf16(mtd, buf, len);
+       else
+               atmel_write_buf8(mtd, buf, len);
+}
+
 /*
  * Calculate HW ECC
  *
@@ -398,6 +525,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       host->io_phys = (dma_addr_t)mem->start;
+
        host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
        if (host->io_base == NULL) {
                printk(KERN_ERR "atmel_nand: ioremap failed\n");
@@ -448,14 +577,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
        nand_chip->chip_delay = 20;             /* 20us command delay time */
 
-       if (host->board->bus_width_16) {        /* 16-bit bus width */
+       if (host->board->bus_width_16)  /* 16-bit bus width */
                nand_chip->options |= NAND_BUSWIDTH_16;
-               nand_chip->read_buf = atmel_read_buf16;
-               nand_chip->write_buf = atmel_write_buf16;
-       } else {
-               nand_chip->read_buf = atmel_read_buf;
-               nand_chip->write_buf = atmel_write_buf;
-       }
+
+       nand_chip->read_buf = atmel_read_buf;
+       nand_chip->write_buf = atmel_write_buf;
 
        platform_set_drvdata(pdev, host);
        atmel_nand_enable(host);
@@ -473,6 +599,22 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                nand_chip->options |= NAND_USE_FLASH_BBT;
        }
 
+       if (cpu_has_dma() && use_dma) {
+               dma_cap_mask_t mask;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_MEMCPY, mask);
+               host->dma_chan = dma_request_channel(mask, 0, NULL);
+               if (!host->dma_chan) {
+                       dev_err(host->dev, "Failed to request DMA channel\n");
+                       use_dma = 0;
+               }
+       }
+       if (use_dma)
+               dev_info(host->dev, "Using DMA for NAND access.\n");
+       else
+               dev_info(host->dev, "No DMA support for NAND access.\n");
+
        /* first scan to find the device and get the page size */
        if (nand_scan_ident(mtd, 1, NULL)) {
                res = -ENXIO;
@@ -555,6 +697,8 @@ err_scan_ident:
 err_no_card:
        atmel_nand_disable(host);
        platform_set_drvdata(pdev, NULL);
+       if (host->dma_chan)
+               dma_release_channel(host->dma_chan);
        if (host->ecc)
                iounmap(host->ecc);
 err_ecc_ioremap:
@@ -578,6 +722,10 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
 
        if (host->ecc)
                iounmap(host->ecc);
+
+       if (host->dma_chan)
+               dma_release_channel(host->dma_chan);
+
        iounmap(host->io_base);
        kfree(host);
 
index a90fde3ede28ca40d992432123cca7e08318e017..aff3468867ac056cb81054fa4c17bfdb50022803 100644 (file)
@@ -37,9 +37,6 @@
 #include <mach/nand.h>
 #include <mach/aemif.h>
 
-#include <asm/mach-types.h>
-
-
 /*
  * This is a device driver for the NAND flash controller found on the
  * various DaVinci family chips.  It handles up to four SoC chipselects,
index c2f95437e5e920ebc105a2d62f86d420d9c3130a..0b81b5b499d1b434c2c09f02a22ec39887543668 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -757,9 +758,9 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 
        /* Enable NFC clock */
        prv->clk = clk_get(dev, "nfc_clk");
-       if (!prv->clk) {
+       if (IS_ERR(prv->clk)) {
                dev_err(dev, "Unable to acquire NFC clock!\n");
-               retval = -ENODEV;
+               retval = PTR_ERR(prv->clk);
                goto error;
        }
 
index 5ae1d9ee2cf1aa96c28c31ccb77ab476bd255074..42a95fb415047d37ed15e7b1df5a989cbd9af017 100644 (file)
@@ -211,6 +211,31 @@ static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
        }
 };
 
+/* OOB description for 4096 byte pages with 128 byte OOB */
+static struct nand_ecclayout nandv2_hw_eccoob_4k = {
+       .eccbytes = 8 * 9,
+       .eccpos = {
+               7,  8,  9, 10, 11, 12, 13, 14, 15,
+               23, 24, 25, 26, 27, 28, 29, 30, 31,
+               39, 40, 41, 42, 43, 44, 45, 46, 47,
+               55, 56, 57, 58, 59, 60, 61, 62, 63,
+               71, 72, 73, 74, 75, 76, 77, 78, 79,
+               87, 88, 89, 90, 91, 92, 93, 94, 95,
+               103, 104, 105, 106, 107, 108, 109, 110, 111,
+               119, 120, 121, 122, 123, 124, 125, 126, 127,
+       },
+       .oobfree = {
+               {.offset = 2, .length = 4},
+               {.offset = 16, .length = 7},
+               {.offset = 32, .length = 7},
+               {.offset = 48, .length = 7},
+               {.offset = 64, .length = 7},
+               {.offset = 80, .length = 7},
+               {.offset = 96, .length = 7},
+               {.offset = 112, .length = 7},
+       }
+};
+
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
 #endif
@@ -641,9 +666,9 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 
        n = min(n, len);
 
-       memcpy(buf, host->data_buf + col, len);
+       memcpy(buf, host->data_buf + col, n);
 
-       host->buf_start += len;
+       host->buf_start += n;
 }
 
 /* Used by the upper layer to verify the data in NAND Flash
@@ -1185,6 +1210,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 
        if (mtd->writesize == 2048)
                this->ecc.layout = oob_largepage;
+       if (nfc_is_v21() && mtd->writesize == 4096)
+               this->ecc.layout = &nandv2_hw_eccoob_4k;
 
        /* second phase scan */
        if (nand_scan_tail(mtd)) {
index a9c6ce745767a471520c952281809cd374891766..85cfc061d41cd7aec609de423cfdf9d6826451a8 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand_bch.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/leds.h>
@@ -2377,7 +2378,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                return -EINVAL;
        }
 
-       /* Do not allow reads past end of device */
+       /* Do not allow write past end of device */
        if (unlikely(to >= mtd->size ||
                     ops->ooboffs + ops->ooblen >
                        ((mtd->size >> chip->page_shift) -
@@ -3248,7 +3249,7 @@ int nand_scan_tail(struct mtd_info *mtd)
        /*
         * If no default placement scheme is given, select an appropriate one
         */
-       if (!chip->ecc.layout) {
+       if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
                switch (mtd->oobsize) {
                case 8:
                        chip->ecc.layout = &nand_oob_8;
@@ -3351,6 +3352,40 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->ecc.bytes = 3;
                break;
 
+       case NAND_ECC_SOFT_BCH:
+               if (!mtd_nand_has_bch()) {
+                       printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+                       BUG();
+               }
+               chip->ecc.calculate = nand_bch_calculate_ecc;
+               chip->ecc.correct = nand_bch_correct_data;
+               chip->ecc.read_page = nand_read_page_swecc;
+               chip->ecc.read_subpage = nand_read_subpage;
+               chip->ecc.write_page = nand_write_page_swecc;
+               chip->ecc.read_page_raw = nand_read_page_raw;
+               chip->ecc.write_page_raw = nand_write_page_raw;
+               chip->ecc.read_oob = nand_read_oob_std;
+               chip->ecc.write_oob = nand_write_oob_std;
+               /*
+                * Board driver should supply ecc.size and ecc.bytes values to
+                * select how many bits are correctable; see nand_bch_init()
+                * for details.
+                * Otherwise, default to 4 bits for large page devices
+                */
+               if (!chip->ecc.size && (mtd->oobsize >= 64)) {
+                       chip->ecc.size = 512;
+                       chip->ecc.bytes = 7;
+               }
+               chip->ecc.priv = nand_bch_init(mtd,
+                                              chip->ecc.size,
+                                              chip->ecc.bytes,
+                                              &chip->ecc.layout);
+               if (!chip->ecc.priv) {
+                       printk(KERN_WARNING "BCH ECC initialization failed!\n");
+                       BUG();
+               }
+               break;
+
        case NAND_ECC_NONE:
                printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
                       "This is not recommended !!\n");
@@ -3501,6 +3536,9 @@ void nand_release(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
 
+       if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
+               nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
+
 #ifdef CONFIG_MTD_PARTITIONS
        /* Deregister partitions */
        del_mtd_partitions(mtd);
index 6ebd869993aa9c976dadd1c4bb44160e9ec24843..a1e8b30078d9a6a0d6c2289f495d5b158d66aad0 100644 (file)
@@ -1101,12 +1101,16 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
        struct nand_chip *this = mtd->priv;
-       u32 pattern_len = bd->len;
-       u32 bits = bd->options & NAND_BBT_NRBITS_MSK;
+       u32 pattern_len;
+       u32 bits;
        u32 table_size;
 
        if (!bd)
                return;
+
+       pattern_len = bd->len;
+       bits = bd->options & NAND_BBT_NRBITS_MSK;
+
        BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) &&
                        !(this->options & NAND_USE_FLASH_BBT));
        BUG_ON(!bits);
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
new file mode 100644 (file)
index 0000000..0f931e7
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * This file provides ECC correction for more than 1 bit per block of data,
+ * using binary BCH codes. It relies on the generic BCH library lib/bch.c.
+ *
+ * Copyright Â© 2011 Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * This file 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 or (at your option) any
+ * later version.
+ *
+ * This file 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 file; 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_bch.h>
+#include <linux/bch.h>
+
+/**
+ * struct nand_bch_control - private NAND BCH control structure
+ * @bch:       BCH control structure
+ * @ecclayout: private ecc layout for this BCH configuration
+ * @errloc:    error location array
+ * @eccmask:   XOR ecc mask, allows erased pages to be decoded as valid
+ */
+struct nand_bch_control {
+       struct bch_control   *bch;
+       struct nand_ecclayout ecclayout;
+       unsigned int         *errloc;
+       unsigned char        *eccmask;
+};
+
+/**
+ * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block
+ * @mtd:       MTD block structure
+ * @buf:       input buffer with raw data
+ * @code:      output buffer with ECC
+ */
+int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+                          unsigned char *code)
+{
+       const struct nand_chip *chip = mtd->priv;
+       struct nand_bch_control *nbc = chip->ecc.priv;
+       unsigned int i;
+
+       memset(code, 0, chip->ecc.bytes);
+       encode_bch(nbc->bch, buf, chip->ecc.size, code);
+
+       /* apply mask so that an erased page is a valid codeword */
+       for (i = 0; i < chip->ecc.bytes; i++)
+               code[i] ^= nbc->eccmask[i];
+
+       return 0;
+}
+EXPORT_SYMBOL(nand_bch_calculate_ecc);
+
+/**
+ * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
+ * @mtd:       MTD block structure
+ * @buf:       raw data read from the chip
+ * @read_ecc:  ECC from the chip
+ * @calc_ecc:  the ECC calculated from raw data
+ *
+ * Detect and correct bit errors for a data byte block
+ */
+int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
+                         unsigned char *read_ecc, unsigned char *calc_ecc)
+{
+       const struct nand_chip *chip = mtd->priv;
+       struct nand_bch_control *nbc = chip->ecc.priv;
+       unsigned int *errloc = nbc->errloc;
+       int i, count;
+
+       count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
+                          NULL, errloc);
+       if (count > 0) {
+               for (i = 0; i < count; i++) {
+                       if (errloc[i] < (chip->ecc.size*8))
+                               /* error is located in data, correct it */
+                               buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
+                       /* else error in ecc, no action needed */
+
+                       DEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n",
+                             __func__, errloc[i]);
+               }
+       } else if (count < 0) {
+               printk(KERN_ERR "ecc unrecoverable error\n");
+               count = -1;
+       }
+       return count;
+}
+EXPORT_SYMBOL(nand_bch_correct_data);
+
+/**
+ * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
+ * @mtd:       MTD block structure
+ * @eccsize:   ecc block size in bytes
+ * @eccbytes:  ecc length in bytes
+ * @ecclayout: output default layout
+ *
+ * Returns:
+ *  a pointer to a new NAND BCH control structure, or NULL upon failure
+ *
+ * Initialize NAND BCH error correction. Parameters @eccsize and @eccbytes
+ * are used to compute BCH parameters m (Galois field order) and t (error
+ * correction capability). @eccbytes should be equal to the number of bytes
+ * required to store m*t bits, where m is such that 2^m-1 > @eccsize*8.
+ *
+ * Example: to configure 4 bit correction per 512 bytes, you should pass
+ * @eccsize = 512  (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
+ * @eccbytes = 7   (7 bytes are required to store m*t = 13*4 = 52 bits)
+ */
+struct nand_bch_control *
+nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
+             struct nand_ecclayout **ecclayout)
+{
+       unsigned int m, t, eccsteps, i;
+       struct nand_ecclayout *layout;
+       struct nand_bch_control *nbc = NULL;
+       unsigned char *erased_page;
+
+       if (!eccsize || !eccbytes) {
+               printk(KERN_WARNING "ecc parameters not supplied\n");
+               goto fail;
+       }
+
+       m = fls(1+8*eccsize);
+       t = (eccbytes*8)/m;
+
+       nbc = kzalloc(sizeof(*nbc), GFP_KERNEL);
+       if (!nbc)
+               goto fail;
+
+       nbc->bch = init_bch(m, t, 0);
+       if (!nbc->bch)
+               goto fail;
+
+       /* verify that eccbytes has the expected value */
+       if (nbc->bch->ecc_bytes != eccbytes) {
+               printk(KERN_WARNING "invalid eccbytes %u, should be %u\n",
+                      eccbytes, nbc->bch->ecc_bytes);
+               goto fail;
+       }
+
+       eccsteps = mtd->writesize/eccsize;
+
+       /* if no ecc placement scheme was provided, build one */
+       if (!*ecclayout) {
+
+               /* handle large page devices only */
+               if (mtd->oobsize < 64) {
+                       printk(KERN_WARNING "must provide an oob scheme for "
+                              "oobsize %d\n", mtd->oobsize);
+                       goto fail;
+               }
+
+               layout = &nbc->ecclayout;
+               layout->eccbytes = eccsteps*eccbytes;
+
+               /* reserve 2 bytes for bad block marker */
+               if (layout->eccbytes+2 > mtd->oobsize) {
+                       printk(KERN_WARNING "no suitable oob scheme available "
+                              "for oobsize %d eccbytes %u\n", mtd->oobsize,
+                              eccbytes);
+                       goto fail;
+               }
+               /* put ecc bytes at oob tail */
+               for (i = 0; i < layout->eccbytes; i++)
+                       layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i;
+
+               layout->oobfree[0].offset = 2;
+               layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
+
+               *ecclayout = layout;
+       }
+
+       /* sanity checks */
+       if (8*(eccsize+eccbytes) >= (1 << m)) {
+               printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
+               goto fail;
+       }
+       if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
+               printk(KERN_WARNING "invalid ecc layout\n");
+               goto fail;
+       }
+
+       nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
+       nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL);
+       if (!nbc->eccmask || !nbc->errloc)
+               goto fail;
+       /*
+        * compute and store the inverted ecc of an erased ecc block
+        */
+       erased_page = kmalloc(eccsize, GFP_KERNEL);
+       if (!erased_page)
+               goto fail;
+
+       memset(erased_page, 0xff, eccsize);
+       memset(nbc->eccmask, 0, eccbytes);
+       encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
+       kfree(erased_page);
+
+       for (i = 0; i < eccbytes; i++)
+               nbc->eccmask[i] ^= 0xff;
+
+       return nbc;
+fail:
+       nand_bch_free(nbc);
+       return NULL;
+}
+EXPORT_SYMBOL(nand_bch_init);
+
+/**
+ * nand_bch_free - [NAND Interface] Release NAND BCH ECC resources
+ * @nbc:       NAND BCH control structure
+ */
+void nand_bch_free(struct nand_bch_control *nbc)
+{
+       if (nbc) {
+               free_bch(nbc->bch);
+               kfree(nbc->errloc);
+               kfree(nbc->eccmask);
+               kfree(nbc);
+       }
+}
+EXPORT_SYMBOL(nand_bch_free);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
+MODULE_DESCRIPTION("NAND software BCH ECC support");
index a5aa99f014baced88b637de9e3aa61e32e6c6925..213181be0d9a727efd7870163b90886f7f5f3029 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/nand_bch.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/list.h>
@@ -108,6 +109,7 @@ static unsigned int rptwear = 0;
 static unsigned int overridesize = 0;
 static char *cache_file = NULL;
 static unsigned int bbt;
+static unsigned int bch;
 
 module_param(first_id_byte,  uint, 0400);
 module_param(second_id_byte, uint, 0400);
@@ -132,6 +134,7 @@ module_param(rptwear,        uint, 0400);
 module_param(overridesize,   uint, 0400);
 module_param(cache_file,     charp, 0400);
 module_param(bbt,           uint, 0400);
+module_param(bch,           uint, 0400);
 
 MODULE_PARM_DESC(first_id_byte,  "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
 MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
@@ -165,6 +168,8 @@ MODULE_PARM_DESC(overridesize,   "Specifies the NAND Flash size overriding the I
                                 " e.g. 5 means a size of 32 erase blocks");
 MODULE_PARM_DESC(cache_file,     "File to use to cache nand pages instead of memory");
 MODULE_PARM_DESC(bbt,           "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area");
+MODULE_PARM_DESC(bch,           "Enable BCH ecc and set how many bits should "
+                                "be correctable in 512-byte blocks");
 
 /* The largest possible page size */
 #define NS_LARGEST_PAGE_SIZE   4096
@@ -2309,7 +2314,43 @@ static int __init ns_init_module(void)
        if ((retval = parse_gravepages()) != 0)
                goto error;
 
-       if ((retval = nand_scan(nsmtd, 1)) != 0) {
+       retval = nand_scan_ident(nsmtd, 1, NULL);
+       if (retval) {
+               NS_ERR("cannot scan NAND Simulator device\n");
+               if (retval > 0)
+                       retval = -ENXIO;
+               goto error;
+       }
+
+       if (bch) {
+               unsigned int eccsteps, eccbytes;
+               if (!mtd_nand_has_bch()) {
+                       NS_ERR("BCH ECC support is disabled\n");
+                       retval = -EINVAL;
+                       goto error;
+               }
+               /* use 512-byte ecc blocks */
+               eccsteps = nsmtd->writesize/512;
+               eccbytes = (bch*13+7)/8;
+               /* do not bother supporting small page devices */
+               if ((nsmtd->oobsize < 64) || !eccsteps) {
+                       NS_ERR("bch not available on small page devices\n");
+                       retval = -EINVAL;
+                       goto error;
+               }
+               if ((eccbytes*eccsteps+2) > nsmtd->oobsize) {
+                       NS_ERR("invalid bch value %u\n", bch);
+                       retval = -EINVAL;
+                       goto error;
+               }
+               chip->ecc.mode = NAND_ECC_SOFT_BCH;
+               chip->ecc.size = 512;
+               chip->ecc.bytes = eccbytes;
+               NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
+       }
+
+       retval = nand_scan_tail(nsmtd);
+       if (retval) {
                NS_ERR("can't register NAND Simulator\n");
                if (retval > 0)
                        retval = -ENXIO;
index 7b8f1fffc5286bb96341471054589c70c22f9cde..da9a351c9d79f55b1dae9afa7b8cbd9ba117da9c 100644 (file)
@@ -668,6 +668,8 @@ static void gen_true_ecc(u8 *ecc_buf)
  *
  * This function compares two ECC's and indicates if there is an error.
  * If the error can be corrected it will be corrected to the buffer.
+ * If there is no error, %0 is returned. If there is an error but it
+ * was corrected, %1 is returned. Otherwise, %-1 is returned.
  */
 static int omap_compare_ecc(u8 *ecc_data1,     /* read from NAND memory */
                            u8 *ecc_data2,      /* read from register */
@@ -773,7 +775,7 @@ static int omap_compare_ecc(u8 *ecc_data1,  /* read from NAND memory */
 
                page_data[find_byte] ^= (1 << find_bit);
 
-               return 0;
+               return 1;
        default:
                if (isEccFF) {
                        if (ecc_data2[0] == 0 &&
@@ -794,8 +796,11 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
  * @calc_ecc: ecc read from HW ECC registers
  *
  * Compares the ecc read from nand spare area with ECC registers values
- * and if ECC's mismached, it will call 'omap_compare_ecc' for error detection
- * and correction.
+ * and if ECC's mismatched, it will call 'omap_compare_ecc' for error
+ * detection and correction. If there are no errors, %0 is returned. If
+ * there were errors and all of the errors were corrected, the number of
+ * corrected errors is returned. If uncorrectable errors exist, %-1 is
+ * returned.
  */
 static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
                                u_char *read_ecc, u_char *calc_ecc)
@@ -803,6 +808,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                        mtd);
        int blockCnt = 0, i = 0, ret = 0;
+       int stat = 0;
 
        /* Ex NAND_ECC_HW12_2048 */
        if ((info->nand.ecc.mode == NAND_ECC_HW) &&
@@ -816,12 +822,14 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
                        ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
                        if (ret < 0)
                                return ret;
+                       /* keep track of the number of corrected errors */
+                       stat += ret;
                }
                read_ecc += 3;
                calc_ecc += 3;
                dat      += 512;
        }
-       return 0;
+       return stat;
 }
 
 /**
index ea2c288df3f6b31490f536202d737c323189c43c..ab7f4c33ced60c96d983be04a644dab0d7d1d015 100644 (file)
@@ -27,6 +27,8 @@
 #include <plat/pxa3xx_nand.h>
 
 #define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
+#define NAND_STOP_DELAY                (2 * HZ/50)
+#define PAGE_CHUNK_SIZE                (2048)
 
 /* registers and bit definitions */
 #define NDCR           (0x00) /* Control register */
 #define NDCR_ND_MODE           (0x3 << 21)
 #define NDCR_NAND_MODE         (0x0)
 #define NDCR_CLR_PG_CNT                (0x1 << 20)
-#define NDCR_CLR_ECC           (0x1 << 19)
+#define NDCR_STOP_ON_UNCOR     (0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK    (0x7 << 16)
 #define NDCR_RD_ID_CNT(x)      (((x) << 16) & NDCR_RD_ID_CNT_MASK)
 
 #define NDCR_RA_START          (0x1 << 15)
 #define NDCR_PG_PER_BLK                (0x1 << 14)
 #define NDCR_ND_ARB_EN         (0x1 << 12)
+#define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK              (0xfff)
-#define NDSR_RDY               (0x1 << 11)
+#define NDSR_RDY                (0x1 << 12)
+#define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED         (0x1 << 10)
 #define NDSR_CS1_PAGED         (0x1 << 9)
 #define NDSR_CS0_CMDD          (0x1 << 8)
@@ -74,6 +78,7 @@
 #define NDSR_RDDREQ            (0x1 << 1)
 #define NDSR_WRCMDREQ          (0x1)
 
+#define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS          (0x1 << 25)
 #define NDCB0_CSEL             (0x1 << 24)
 #define NDCB0_CMD_TYPE_MASK    (0x7 << 21)
@@ -104,18 +109,21 @@ enum {
 };
 
 enum {
-       STATE_READY     = 0,
+       STATE_IDLE = 0,
        STATE_CMD_HANDLE,
        STATE_DMA_READING,
        STATE_DMA_WRITING,
        STATE_DMA_DONE,
        STATE_PIO_READING,
        STATE_PIO_WRITING,
+       STATE_CMD_DONE,
+       STATE_READY,
 };
 
 struct pxa3xx_nand_info {
        struct nand_chip        nand_chip;
 
+       struct nand_hw_control  controller;
        struct platform_device   *pdev;
        struct pxa3xx_nand_cmdset *cmdset;
 
@@ -126,6 +134,7 @@ struct pxa3xx_nand_info {
        unsigned int            buf_start;
        unsigned int            buf_count;
 
+       struct mtd_info         *mtd;
        /* DMA information */
        int                     drcmr_dat;
        int                     drcmr_cmd;
@@ -149,6 +158,7 @@ struct pxa3xx_nand_info {
 
        int                     use_ecc;        /* use HW ECC ? */
        int                     use_dma;        /* use DMA ? */
+       int                     is_ready;
 
        unsigned int            page_size;      /* page size of attached chip */
        unsigned int            data_size;      /* data size in FIFO */
@@ -201,20 +211,22 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-       {      0,   0, 2048,  8,  8,    0, &default_cmdset, &timing[0] },
-       { 0x46ec,  32,  512, 16, 16, 4096, &default_cmdset, &timing[1] },
-       { 0xdaec,  64, 2048,  8,  8, 2048, &default_cmdset, &timing[1] },
-       { 0xd7ec, 128, 4096,  8,  8, 8192, &default_cmdset, &timing[1] },
-       { 0xa12c,  64, 2048,  8,  8, 1024, &default_cmdset, &timing[2] },
-       { 0xb12c,  64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
-       { 0xdc2c,  64, 2048,  8,  8, 4096, &default_cmdset, &timing[2] },
-       { 0xcc2c,  64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
-       { 0xba20,  64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
+{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
 };
 
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
+const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
 #define NDTR0_tCH(c)   (min((c), 7) << 19)
 #define NDTR0_tCS(c)   (min((c), 7) << 16)
 #define NDTR0_tWH(c)   (min((c), 7) << 11)
@@ -252,25 +264,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-#define WAIT_EVENT_TIMEOUT     10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
-       int timeout = WAIT_EVENT_TIMEOUT;
-       uint32_t ndsr;
-
-       while (timeout--) {
-               ndsr = nand_readl(info, NDSR) & NDSR_MASK;
-               if (ndsr & event) {
-                       nand_writel(info, NDSR, ndsr);
-                       return 0;
-               }
-               udelay(10);
-       }
-
-       return -ETIMEDOUT;
-}
-
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
        int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -291,69 +284,45 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
        }
 }
 
-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-               uint16_t cmd, int column, int page_addr)
+/**
+ * NOTE: it is a must to set ND_RUN firstly, then write
+ * command buffer, otherwise, it does not work.
+ * We enable all the interrupt at the same time, and
+ * let pxa3xx_nand_irq to handle all logic.
+ */
+static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
-       const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-       pxa3xx_set_datasize(info);
-
-       /* generate values for NDCBx registers */
-       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-       info->ndcb1 = 0;
-       info->ndcb2 = 0;
-       info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
-       if (info->col_addr_cycles == 2) {
-               /* large block, 2 cycles for column address
-                * row address starts from 3rd cycle
-                */
-               info->ndcb1 |= page_addr << 16;
-               if (info->row_addr_cycles == 3)
-                       info->ndcb2 = (page_addr >> 16) & 0xff;
-       } else
-               /* small block, 1 cycles for column address
-                * row address starts from 2nd cycle
-                */
-               info->ndcb1 = page_addr << 8;
-
-       if (cmd == cmdset->program)
-               info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
+       uint32_t ndcr;
 
-       return 0;
-}
+       ndcr = info->reg_ndcr;
+       ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
+       ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
+       ndcr |= NDCR_ND_RUN;
 
-static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
-                       uint16_t cmd, int page_addr)
-{
-       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-       info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
-       info->ndcb1 = page_addr;
-       info->ndcb2 = 0;
-       return 0;
+       /* clear status bits and run */
+       nand_writel(info, NDCR, 0);
+       nand_writel(info, NDSR, NDSR_MASK);
+       nand_writel(info, NDCR, ndcr);
 }
 
-static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
+static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
 {
-       const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
-       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-       info->ndcb1 = 0;
-       info->ndcb2 = 0;
+       uint32_t ndcr;
+       int timeout = NAND_STOP_DELAY;
 
-       info->oob_size = 0;
-       if (cmd == cmdset->read_id) {
-               info->ndcb0 |= NDCB0_CMD_TYPE(3);
-               info->data_size = 8;
-       } else if (cmd == cmdset->read_status) {
-               info->ndcb0 |= NDCB0_CMD_TYPE(4);
-               info->data_size = 8;
-       } else if (cmd == cmdset->reset || cmd == cmdset->lock ||
-                  cmd == cmdset->unlock) {
-               info->ndcb0 |= NDCB0_CMD_TYPE(5);
-       } else
-               return -EINVAL;
+       /* wait RUN bit in NDCR become 0 */
+       ndcr = nand_readl(info, NDCR);
+       while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
+               ndcr = nand_readl(info, NDCR);
+               udelay(1);
+       }
 
-       return 0;
+       if (timeout <= 0) {
+               ndcr &= ~NDCR_ND_RUN;
+               nand_writel(info, NDCR, ndcr);
+       }
+       /* clear status bits */
+       nand_writel(info, NDSR, NDSR_MASK);
 }
 
 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
@@ -372,39 +341,8 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
        nand_writel(info, NDCR, ndcr | int_mask);
 }
 
-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
-       uint32_t ndcr;
-
-       /* clear status bits and run */
-       nand_writel(info, NDSR, NDSR_MASK);
-
-       ndcr = info->reg_ndcr;
-
-       ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-       ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
-       ndcr |= NDCR_ND_RUN;
-
-       nand_writel(info, NDCR, ndcr);
-
-       if (wait_for_event(info, NDSR_WRCMDREQ)) {
-               printk(KERN_ERR "timed out writing command\n");
-               return -ETIMEDOUT;
-       }
-
-       nand_writel(info, NDCB0, info->ndcb0);
-       nand_writel(info, NDCB0, info->ndcb1);
-       nand_writel(info, NDCB0, info->ndcb2);
-       return 0;
-}
-
-static int handle_data_pio(struct pxa3xx_nand_info *info)
-{
-       int ret, timeout = CHIP_DELAY_TIMEOUT;
-
        switch (info->state) {
        case STATE_PIO_WRITING:
                __raw_writesl(info->mmio_base + NDDB, info->data_buff,
@@ -412,14 +350,6 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
                if (info->oob_size > 0)
                        __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
                                        DIV_ROUND_UP(info->oob_size, 4));
-
-               enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-
-               ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-               if (!ret) {
-                       printk(KERN_ERR "program command time out\n");
-                       return -1;
-               }
                break;
        case STATE_PIO_READING:
                __raw_readsl(info->mmio_base + NDDB, info->data_buff,
@@ -431,14 +361,11 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
        default:
                printk(KERN_ERR "%s: invalid state %d\n", __func__,
                                info->state);
-               return -EINVAL;
+               BUG();
        }
-
-       info->state = STATE_READY;
-       return 0;
 }
 
-static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+static void start_data_dma(struct pxa3xx_nand_info *info)
 {
        struct pxa_dma_desc *desc = info->data_desc;
        int dma_len = ALIGN(info->data_size + info->oob_size, 32);
@@ -446,14 +373,21 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
        desc->ddadr = DDADR_STOP;
        desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
 
-       if (dir_out) {
+       switch (info->state) {
+       case STATE_DMA_WRITING:
                desc->dsadr = info->data_buff_phys;
                desc->dtadr = info->mmio_phys + NDDB;
                desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
-       } else {
+               break;
+       case STATE_DMA_READING:
                desc->dtadr = info->data_buff_phys;
                desc->dsadr = info->mmio_phys + NDDB;
                desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+               break;
+       default:
+               printk(KERN_ERR "%s: invalid state %d\n", __func__,
+                               info->state);
+               BUG();
        }
 
        DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
@@ -471,93 +405,62 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data)
 
        if (dcsr & DCSR_BUSERR) {
                info->retcode = ERR_DMABUSERR;
-               complete(&info->cmd_complete);
        }
 
-       if (info->state == STATE_DMA_WRITING) {
-               info->state = STATE_DMA_DONE;
-               enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-       } else {
-               info->state = STATE_READY;
-               complete(&info->cmd_complete);
-       }
+       info->state = STATE_DMA_DONE;
+       enable_int(info, NDCR_INT_MASK);
+       nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }
 
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
-       unsigned int status;
+       unsigned int status, is_completed = 0;
 
        status = nand_readl(info, NDSR);
 
-       if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) {
-               if (status & NDSR_DBERR)
-                       info->retcode = ERR_DBERR;
-               else if (status & NDSR_SBERR)
-                       info->retcode = ERR_SBERR;
-
-               disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
-               if (info->use_dma) {
-                       info->state = STATE_DMA_READING;
-                       start_data_dma(info, 0);
-               } else {
-                       info->state = STATE_PIO_READING;
-                       complete(&info->cmd_complete);
-               }
-       } else if (status & NDSR_WRDREQ) {
-               disable_int(info, NDSR_WRDREQ);
+       if (status & NDSR_DBERR)
+               info->retcode = ERR_DBERR;
+       if (status & NDSR_SBERR)
+               info->retcode = ERR_SBERR;
+       if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
+               /* whether use dma to transfer data */
                if (info->use_dma) {
-                       info->state = STATE_DMA_WRITING;
-                       start_data_dma(info, 1);
+                       disable_int(info, NDCR_INT_MASK);
+                       info->state = (status & NDSR_RDDREQ) ?
+                                     STATE_DMA_READING : STATE_DMA_WRITING;
+                       start_data_dma(info);
+                       goto NORMAL_IRQ_EXIT;
                } else {
-                       info->state = STATE_PIO_WRITING;
-                       complete(&info->cmd_complete);
+                       info->state = (status & NDSR_RDDREQ) ?
+                                     STATE_PIO_READING : STATE_PIO_WRITING;
+                       handle_data_pio(info);
                }
-       } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
-               if (status & NDSR_CS0_BBD)
-                       info->retcode = ERR_BBERR;
-
-               disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-               info->state = STATE_READY;
-               complete(&info->cmd_complete);
        }
-       nand_writel(info, NDSR, status);
-       return IRQ_HANDLED;
-}
-
-static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
-{
-       uint32_t ndcr;
-       int ret, timeout = CHIP_DELAY_TIMEOUT;
-
-       if (write_cmd(info)) {
-               info->retcode = ERR_SENDCMD;
-               goto fail_stop;
+       if (status & NDSR_CS0_CMDD) {
+               info->state = STATE_CMD_DONE;
+               is_completed = 1;
        }
-
-       info->state = STATE_CMD_HANDLE;
-
-       enable_int(info, event);
-
-       ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-       if (!ret) {
-               printk(KERN_ERR "command execution timed out\n");
-               info->retcode = ERR_SENDCMD;
-               goto fail_stop;
+       if (status & NDSR_FLASH_RDY) {
+               info->is_ready = 1;
+               info->state = STATE_READY;
        }
 
-       if (info->use_dma == 0 && info->data_size > 0)
-               if (handle_data_pio(info))
-                       goto fail_stop;
-
-       return 0;
+       if (status & NDSR_WRCMDREQ) {
+               nand_writel(info, NDSR, NDSR_WRCMDREQ);
+               status &= ~NDSR_WRCMDREQ;
+               info->state = STATE_CMD_HANDLE;
+               nand_writel(info, NDCB0, info->ndcb0);
+               nand_writel(info, NDCB0, info->ndcb1);
+               nand_writel(info, NDCB0, info->ndcb2);
+       }
 
-fail_stop:
-       ndcr = nand_readl(info, NDCR);
-       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-       udelay(10);
-       return -ETIMEDOUT;
+       /* clear NDSR to let the controller exit the IRQ */
+       nand_writel(info, NDSR, status);
+       if (is_completed)
+               complete(&info->cmd_complete);
+NORMAL_IRQ_EXIT:
+       return IRQ_HANDLED;
 }
 
 static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
@@ -574,125 +477,218 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
        return 1;
 }
 
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-                               int column, int page_addr)
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+               uint16_t column, int page_addr)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
-       const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-       int ret;
+       uint16_t cmd;
+       int addr_cycle, exec_cmd, ndcb0;
+       struct mtd_info *mtd = info->mtd;
+
+       ndcb0 = 0;
+       addr_cycle = 0;
+       exec_cmd = 1;
+
+       /* reset data and oob column point to handle data */
+       info->buf_start         = 0;
+       info->buf_count         = 0;
+       info->oob_size          = 0;
+       info->use_ecc           = 0;
+       info->is_ready          = 0;
+       info->retcode           = ERR_NONE;
 
-       info->use_dma = (use_dma) ? 1 : 0;
-       info->use_ecc = 0;
-       info->data_size = 0;
-       info->state = STATE_READY;
+       switch (command) {
+       case NAND_CMD_READ0:
+       case NAND_CMD_PAGEPROG:
+               info->use_ecc = 1;
+       case NAND_CMD_READOOB:
+               pxa3xx_set_datasize(info);
+               break;
+       case NAND_CMD_SEQIN:
+               exec_cmd = 0;
+               break;
+       default:
+               info->ndcb1 = 0;
+               info->ndcb2 = 0;
+               break;
+       }
 
-       init_completion(&info->cmd_complete);
+       info->ndcb0 = ndcb0;
+       addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+                                   + info->col_addr_cycles);
 
        switch (command) {
        case NAND_CMD_READOOB:
-               /* disable HW ECC to get all the OOB data */
-               info->buf_count = mtd->writesize + mtd->oobsize;
-               info->buf_start = mtd->writesize + column;
-               memset(info->data_buff, 0xFF, info->buf_count);
+       case NAND_CMD_READ0:
+               cmd = info->cmdset->read1;
+               if (command == NAND_CMD_READOOB)
+                       info->buf_start = mtd->writesize + column;
+               else
+                       info->buf_start = column;
 
-               if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-                       break;
+               if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0)
+                                       | addr_cycle
+                                       | (cmd & NDCB0_CMD1_MASK);
+               else
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0)
+                                       | NDCB0_DBC
+                                       | addr_cycle
+                                       | cmd;
 
-               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
+       case NAND_CMD_SEQIN:
+               /* small page addr setting */
+               if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+                       info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+                                       | (column & 0xFF);
 
-               /* We only are OOB, so if the data has error, does not matter */
-               if (info->retcode == ERR_DBERR)
-                       info->retcode = ERR_NONE;
-               break;
+                       info->ndcb2 = 0;
+               } else {
+                       info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+                                       | (column & 0xFFFF);
+
+                       if (page_addr & 0xFF0000)
+                               info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+                       else
+                               info->ndcb2 = 0;
+               }
 
-       case NAND_CMD_READ0:
-               info->use_ecc = 1;
-               info->retcode = ERR_NONE;
-               info->buf_start = column;
                info->buf_count = mtd->writesize + mtd->oobsize;
                memset(info->data_buff, 0xFF, info->buf_count);
 
-               if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
+               break;
+
+       case NAND_CMD_PAGEPROG:
+               if (is_buf_blank(info->data_buff,
+                                       (mtd->writesize + mtd->oobsize))) {
+                       exec_cmd = 0;
                        break;
+               }
 
-               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
+               cmd = info->cmdset->program;
+               info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                               | NDCB0_AUTO_RS
+                               | NDCB0_ST_ROW_EN
+                               | NDCB0_DBC
+                               | cmd
+                               | addr_cycle;
+               break;
 
-               if (info->retcode == ERR_DBERR) {
-                       /* for blank page (all 0xff), HW will calculate its ECC as
-                        * 0, which is different from the ECC information within
-                        * OOB, ignore such double bit errors
-                        */
-                       if (is_buf_blank(info->data_buff, mtd->writesize))
-                               info->retcode = ERR_NONE;
-               }
+       case NAND_CMD_READID:
+               cmd = info->cmdset->read_id;
+               info->buf_count = info->read_id_bytes;
+               info->ndcb0 |= NDCB0_CMD_TYPE(3)
+                               | NDCB0_ADDR_CYC(1)
+                               | cmd;
+
+               info->data_size = 8;
                break;
-       case NAND_CMD_SEQIN:
-               info->buf_start = column;
-               info->buf_count = mtd->writesize + mtd->oobsize;
-               memset(info->data_buff, 0xff, info->buf_count);
+       case NAND_CMD_STATUS:
+               cmd = info->cmdset->read_status;
+               info->buf_count = 1;
+               info->ndcb0 |= NDCB0_CMD_TYPE(4)
+                               | NDCB0_ADDR_CYC(1)
+                               | cmd;
 
-               /* save column/page_addr for next CMD_PAGEPROG */
-               info->seqin_column = column;
-               info->seqin_page_addr = page_addr;
+               info->data_size = 8;
                break;
-       case NAND_CMD_PAGEPROG:
-               info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
 
-               if (prepare_read_prog_cmd(info, cmdset->program,
-                               info->seqin_column, info->seqin_page_addr))
-                       break;
+       case NAND_CMD_ERASE1:
+               cmd = info->cmdset->erase;
+               info->ndcb0 |= NDCB0_CMD_TYPE(2)
+                               | NDCB0_AUTO_RS
+                               | NDCB0_ADDR_CYC(3)
+                               | NDCB0_DBC
+                               | cmd;
+               info->ndcb1 = page_addr;
+               info->ndcb2 = 0;
 
-               pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
                break;
-       case NAND_CMD_ERASE1:
-               if (prepare_erase_cmd(info, cmdset->erase, page_addr))
-                       break;
+       case NAND_CMD_RESET:
+               cmd = info->cmdset->reset;
+               info->ndcb0 |= NDCB0_CMD_TYPE(5)
+                               | cmd;
 
-               pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
                break;
+
        case NAND_CMD_ERASE2:
+               exec_cmd = 0;
                break;
-       case NAND_CMD_READID:
-       case NAND_CMD_STATUS:
-               info->use_dma = 0;      /* force PIO read */
-               info->buf_start = 0;
-               info->buf_count = (command == NAND_CMD_READID) ?
-                               info->read_id_bytes : 1;
-
-               if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-                               cmdset->read_id : cmdset->read_status))
-                       break;
 
-               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
+       default:
+               exec_cmd = 0;
+               printk(KERN_ERR "pxa3xx-nand: non-supported"
+                       " command %x\n", command);
                break;
-       case NAND_CMD_RESET:
-               if (prepare_other_cmd(info, cmdset->reset))
-                       break;
+       }
 
-               ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
-               if (ret == 0) {
-                       int timeout = 2;
-                       uint32_t ndcr;
+       return exec_cmd;
+}
 
-                       while (timeout--) {
-                               if (nand_readl(info, NDSR) & NDSR_RDY)
-                                       break;
-                               msleep(10);
-                       }
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+                               int column, int page_addr)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       int ret, exec_cmd;
 
-                       ndcr = nand_readl(info, NDCR);
-                       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
+       /*
+        * if this is a x16 device ,then convert the input
+        * "byte" address into a "word" address appropriate
+        * for indexing a word-oriented device
+        */
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
+               column /= 2;
+
+       exec_cmd = prepare_command_pool(info, command, column, page_addr);
+       if (exec_cmd) {
+               init_completion(&info->cmd_complete);
+               pxa3xx_nand_start(info);
+
+               ret = wait_for_completion_timeout(&info->cmd_complete,
+                               CHIP_DELAY_TIMEOUT);
+               if (!ret) {
+                       printk(KERN_ERR "Wait time out!!!\n");
+                       /* Stop State Machine for next command cycle */
+                       pxa3xx_nand_stop(info);
                }
-               break;
-       default:
-               printk(KERN_ERR "non-supported command.\n");
-               break;
+               info->state = STATE_IDLE;
        }
+}
+
+static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+               struct nand_chip *chip, const uint8_t *buf)
+{
+       chip->write_buf(mtd, buf, mtd->writesize);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
 
-       if (info->retcode == ERR_DBERR) {
-               printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-               info->retcode = ERR_NONE;
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+               struct nand_chip *chip, uint8_t *buf, int page)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+
+       chip->read_buf(mtd, buf, mtd->writesize);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       if (info->retcode == ERR_SBERR) {
+               switch (info->use_ecc) {
+               case 1:
+                       mtd->ecc_stats.corrected++;
+                       break;
+               case 0:
+               default:
+                       break;
+               }
+       } else if (info->retcode == ERR_DBERR) {
+               /*
+                * for blank page (all 0xff), HW will calculate its ECC as
+                * 0, which is different from the ECC information within
+                * OOB, ignore such double bit errors
+                */
+               if (is_buf_blank(buf, mtd->writesize))
+                       mtd->ecc_stats.failed++;
        }
+
+       return 0;
 }
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
@@ -769,73 +765,12 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
        return 0;
 }
 
-static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
-{
-       return;
-}
-
-static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
-               const uint8_t *dat, uint8_t *ecc_code)
-{
-       return 0;
-}
-
-static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
-               uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
-{
-       struct pxa3xx_nand_info *info = mtd->priv;
-       /*
-        * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
-        * consider it as a ecc error which will tell the caller the
-        * read fail We have distinguish all the errors, but the
-        * nand_read_ecc only check this function return value
-        *
-        * Corrected (single-bit) errors must also be noted.
-        */
-       if (info->retcode == ERR_SBERR)
-               return 1;
-       else if (info->retcode != ERR_NONE)
-               return -1;
-
-       return 0;
-}
-
-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
-       const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-       uint32_t ndcr;
-       uint8_t  id_buff[8];
-
-       if (prepare_other_cmd(info, cmdset->read_id)) {
-               printk(KERN_ERR "failed to prepare command\n");
-               return -EINVAL;
-       }
-
-       /* Send command */
-       if (write_cmd(info))
-               goto fail_timeout;
-
-       /* Wait for CMDDM(command done successfully) */
-       if (wait_for_event(info, NDSR_RDDREQ))
-               goto fail_timeout;
-
-       __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
-       *id = id_buff[0] | (id_buff[1] << 8);
-       return 0;
-
-fail_timeout:
-       ndcr = nand_readl(info, NDCR);
-       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-       udelay(10);
-       return -ETIMEDOUT;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
                                    const struct pxa3xx_nand_flash *f)
 {
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
-       uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
+       uint32_t ndcr = 0x0; /* enable all interrupts */
 
        if (f->page_size != 2048 && f->page_size != 512)
                return -EINVAL;
@@ -844,9 +779,8 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
                return -EINVAL;
 
        /* calculate flash information */
-       info->cmdset = f->cmdset;
+       info->cmdset = &default_cmdset;
        info->page_size = f->page_size;
-       info->oob_buff = info->data_buff + f->page_size;
        info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
@@ -876,87 +810,18 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
        uint32_t ndcr = nand_readl(info, NDCR);
-       struct nand_flash_dev *type = NULL;
-       uint32_t id = -1, page_per_block, num_blocks;
-       int i;
-
-       page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
        info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-       /* set info fields needed to __readid */
+       /* set info fields needed to read id */
        info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
        info->reg_ndcr = ndcr;
        info->cmdset = &default_cmdset;
 
-       if (__readid(info, &id))
-               return -ENODEV;
-
-       /* Lookup the flash id */
-       id = (id >> 8) & 0xff;          /* device id is byte 2 */
-       for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-               if (id == nand_flash_ids[i].id) {
-                       type =  &nand_flash_ids[i];
-                       break;
-               }
-       }
-
-       if (!type)
-               return -ENODEV;
-
-       /* fill the missing flash information */
-       i = __ffs(page_per_block * info->page_size);
-       num_blocks = type->chipsize << (20 - i);
-
-       /* calculate addressing information */
-       info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
-       if (num_blocks * page_per_block > 65536)
-               info->row_addr_cycles = 3;
-       else
-               info->row_addr_cycles = 2;
-
        info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
        info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
        return 0;
 }
 
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
-                                   const struct pxa3xx_nand_platform_data *pdata)
-{
-       const struct pxa3xx_nand_flash *f;
-       uint32_t id = -1;
-       int i;
-
-       if (pdata->keep_config)
-               if (pxa3xx_nand_detect_config(info) == 0)
-                       return 0;
-
-       /* we use default timing to detect id */
-       f = DEFAULT_FLASH_TYPE;
-       pxa3xx_nand_config_flash(info, f);
-       if (__readid(info, &id))
-               goto fail_detect;
-
-       for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
-               /* we first choose the flash definition from platfrom */
-               if (i < pdata->num_flash)
-                       f = pdata->flash + i;
-               else
-                       f = &builtin_flash_types[i - pdata->num_flash + 1];
-               if (f->chip_id == id) {
-                       dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
-                       pxa3xx_nand_config_flash(info, f);
-                       return 0;
-               }
-       }
-
-       dev_warn(&info->pdev->dev,
-                "failed to detect configured nand flash; found %04x instead of\n",
-                id);
-fail_detect:
-       return -ENODEV;
-}
-
 /* the maximum possible buffer size for large page with OOB data
  * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
  * data buffer and the DMA descriptor
@@ -998,82 +863,144 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
        return 0;
 }
 
-static struct nand_ecclayout hw_smallpage_ecclayout = {
-       .eccbytes = 6,
-       .eccpos = {8, 9, 10, 11, 12, 13 },
-       .oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+{
+       struct mtd_info *mtd = info->mtd;
+       struct nand_chip *chip = mtd->priv;
 
-static struct nand_ecclayout hw_largepage_ecclayout = {
-       .eccbytes = 24,
-       .eccpos = {
-               40, 41, 42, 43, 44, 45, 46, 47,
-               48, 49, 50, 51, 52, 53, 54, 55,
-               56, 57, 58, 59, 60, 61, 62, 63},
-       .oobfree = { {2, 38} }
-};
+       /* use the common timing to make a try */
+       pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       if (info->is_ready)
+               return 1;
+       else
+               return 0;
+}
 
-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
-                                struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-       struct nand_chip *this = &info->nand_chip;
-
-       this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
-
-       this->waitfunc          = pxa3xx_nand_waitfunc;
-       this->select_chip       = pxa3xx_nand_select_chip;
-       this->dev_ready         = pxa3xx_nand_dev_ready;
-       this->cmdfunc           = pxa3xx_nand_cmdfunc;
-       this->read_word         = pxa3xx_nand_read_word;
-       this->read_byte         = pxa3xx_nand_read_byte;
-       this->read_buf          = pxa3xx_nand_read_buf;
-       this->write_buf         = pxa3xx_nand_write_buf;
-       this->verify_buf        = pxa3xx_nand_verify_buf;
-
-       this->ecc.mode          = NAND_ECC_HW;
-       this->ecc.hwctl         = pxa3xx_nand_ecc_hwctl;
-       this->ecc.calculate     = pxa3xx_nand_ecc_calculate;
-       this->ecc.correct       = pxa3xx_nand_ecc_correct;
-       this->ecc.size          = info->page_size;
-
-       if (info->page_size == 2048)
-               this->ecc.layout = &hw_largepage_ecclayout;
+       struct pxa3xx_nand_info *info = mtd->priv;
+       struct platform_device *pdev = info->pdev;
+       struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+       struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
+       const struct pxa3xx_nand_flash *f = NULL;
+       struct nand_chip *chip = mtd->priv;
+       uint32_t id = -1;
+       uint64_t chipsize;
+       int i, ret, num;
+
+       if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
+               goto KEEP_CONFIG;
+
+       ret = pxa3xx_nand_sensing(info);
+       if (!ret) {
+               kfree(mtd);
+               info->mtd = NULL;
+               printk(KERN_INFO "There is no nand chip on cs 0!\n");
+
+               return -EINVAL;
+       }
+
+       chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+       id = *((uint16_t *)(info->data_buff));
+       if (id != 0)
+               printk(KERN_INFO "Detect a flash id %x\n", id);
+       else {
+               kfree(mtd);
+               info->mtd = NULL;
+               printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+               return -EINVAL;
+       }
+
+       num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
+       for (i = 0; i < num; i++) {
+               if (i < pdata->num_flash)
+                       f = pdata->flash + i;
+               else
+                       f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+               /* find the chip in default list */
+               if (f->chip_id == id)
+                       break;
+       }
+
+       if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
+               kfree(mtd);
+               info->mtd = NULL;
+               printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+               return -EINVAL;
+       }
+
+       pxa3xx_nand_config_flash(info, f);
+       pxa3xx_flash_ids[0].name = f->name;
+       pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+       pxa3xx_flash_ids[0].pagesize = f->page_size;
+       chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+       pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+       pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+       if (f->flash_width == 16)
+               pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
+KEEP_CONFIG:
+       if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+               return -ENODEV;
+       /* calculate addressing information */
+       info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+       info->oob_buff = info->data_buff + mtd->writesize;
+       if ((mtd->size >> chip->page_shift) > 65536)
+               info->row_addr_cycles = 3;
        else
-               this->ecc.layout = &hw_smallpage_ecclayout;
+               info->row_addr_cycles = 2;
+       mtd->name = mtd_names[0];
+       chip->ecc.mode = NAND_ECC_HW;
+       chip->ecc.size = f->page_size;
+
+       chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+       chip->options |= NAND_NO_AUTOINCR;
+       chip->options |= NAND_NO_READRDY;
 
-       this->chip_delay = 25;
+       return nand_scan_tail(mtd);
 }
 
-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static
+struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 {
-       struct pxa3xx_nand_platform_data *pdata;
        struct pxa3xx_nand_info *info;
-       struct nand_chip *this;
+       struct nand_chip *chip;
        struct mtd_info *mtd;
        struct resource *r;
-       int ret = 0, irq;
-
-       pdata = pdev->dev.platform_data;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data defined\n");
-               return -ENODEV;
-       }
+       int ret, irq;
 
        mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
                        GFP_KERNEL);
        if (!mtd) {
                dev_err(&pdev->dev, "failed to allocate memory\n");
-               return -ENOMEM;
+               return NULL;
        }
 
        info = (struct pxa3xx_nand_info *)(&mtd[1]);
+       chip = (struct nand_chip *)(&mtd[1]);
        info->pdev = pdev;
-
-       this = &info->nand_chip;
+       info->mtd = mtd;
        mtd->priv = info;
        mtd->owner = THIS_MODULE;
 
+       chip->ecc.read_page     = pxa3xx_nand_read_page_hwecc;
+       chip->ecc.write_page    = pxa3xx_nand_write_page_hwecc;
+       chip->controller        = &info->controller;
+       chip->waitfunc          = pxa3xx_nand_waitfunc;
+       chip->select_chip       = pxa3xx_nand_select_chip;
+       chip->dev_ready         = pxa3xx_nand_dev_ready;
+       chip->cmdfunc           = pxa3xx_nand_cmdfunc;
+       chip->read_word         = pxa3xx_nand_read_word;
+       chip->read_byte         = pxa3xx_nand_read_byte;
+       chip->read_buf          = pxa3xx_nand_read_buf;
+       chip->write_buf         = pxa3xx_nand_write_buf;
+       chip->verify_buf        = pxa3xx_nand_verify_buf;
+
+       spin_lock_init(&chip->controller->lock);
+       init_waitqueue_head(&chip->controller->wq);
        info->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(info->clk)) {
                dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1141,43 +1068,12 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
                goto fail_free_buf;
        }
 
-       ret = pxa3xx_nand_detect_flash(info, pdata);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to detect flash\n");
-               ret = -ENODEV;
-               goto fail_free_irq;
-       }
-
-       pxa3xx_nand_init_mtd(mtd, info);
-
-       platform_set_drvdata(pdev, mtd);
-
-       if (nand_scan(mtd, 1)) {
-               dev_err(&pdev->dev, "failed to scan nand\n");
-               ret = -ENXIO;
-               goto fail_free_irq;
-       }
-
-#ifdef CONFIG_MTD_PARTITIONS
-       if (mtd_has_cmdlinepart()) {
-               static const char *probes[] = { "cmdlinepart", NULL };
-               struct mtd_partition *parts;
-               int nr_parts;
-
-               nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
-               if (nr_parts)
-                       return add_mtd_partitions(mtd, parts, nr_parts);
-       }
+       platform_set_drvdata(pdev, info);
 
-       return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-#else
-       return 0;
-#endif
+       return info;
 
-fail_free_irq:
-       free_irq(irq, info);
 fail_free_buf:
+       free_irq(irq, info);
        if (use_dma) {
                pxa_free_dma(info->data_dma_ch);
                dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1193,22 +1089,18 @@ fail_put_clk:
        clk_put(info->clk);
 fail_free_mtd:
        kfree(mtd);
-       return ret;
+       return NULL;
 }
 
 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-       struct mtd_info *mtd = platform_get_drvdata(pdev);
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+       struct mtd_info *mtd = info->mtd;
        struct resource *r;
        int irq;
 
        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);
@@ -1226,17 +1118,62 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        clk_disable(info->clk);
        clk_put(info->clk);
 
-       kfree(mtd);
+       if (mtd) {
+               del_mtd_device(mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+               del_mtd_partitions(mtd);
+#endif
+               kfree(mtd);
+       }
        return 0;
 }
 
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+       struct pxa3xx_nand_platform_data *pdata;
+       struct pxa3xx_nand_info *info;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               return -ENODEV;
+       }
+
+       info = alloc_nand_resource(pdev);
+       if (info == NULL)
+               return -ENOMEM;
+
+       if (pxa3xx_nand_scan(info->mtd)) {
+               dev_err(&pdev->dev, "failed to scan nand\n");
+               pxa3xx_nand_remove(pdev);
+               return -ENODEV;
+       }
+
+#ifdef CONFIG_MTD_PARTITIONS
+       if (mtd_has_cmdlinepart()) {
+               const char *probes[] = { "cmdlinepart", NULL };
+               struct mtd_partition *parts;
+               int nr_parts;
+
+               nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+               if (nr_parts)
+                       return add_mtd_partitions(info->mtd, parts, nr_parts);
+       }
+
+       return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+#else
+       return 0;
+#endif
+}
+
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+       struct mtd_info *mtd = info->mtd;
 
-       if (info->state != STATE_READY) {
+       if (info->state) {
                dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
                return -EAGAIN;
        }
@@ -1246,8 +1183,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-       struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+       struct mtd_info *mtd = info->mtd;
 
        nand_writel(info, NDTR0CS0, info->ndtr0cs0);
        nand_writel(info, NDTR1CS0, info->ndtr1cs0);
index 14a49abe057eb4f095d46690e91a132003718f86..f591f615d3f620ba0ee497873d06a4bfebf7a15b 100644 (file)
@@ -629,6 +629,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 {
        struct omap_onenand_platform_data *pdata;
        struct omap2_onenand *c;
+       struct onenand_chip *this;
        int r;
 
        pdata = pdev->dev.platform_data;
@@ -726,9 +727,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 
        c->mtd.dev.parent = &pdev->dev;
 
+       this = &c->onenand;
        if (c->dma_channel >= 0) {
-               struct onenand_chip *this = &c->onenand;
-
                this->wait = omap2_onenand_wait;
                if (cpu_is_omap34xx()) {
                        this->read_bufferram = omap3_onenand_read_bufferram;
@@ -749,6 +749,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
                c->onenand.disable = omap2_onenand_disable;
        }
 
+       if (pdata->skip_initial_unlocking)
+               this->options |= ONENAND_SKIP_INITIAL_UNLOCKING;
+
        if ((r = onenand_scan(&c->mtd, 1)) < 0)
                goto err_release_regulator;
 
index bac41caa8df72d8967caf93fd4f2fc96309f07c7..56a8b2005bdace6eb51fe500a040dc13f38c24b8 100644 (file)
@@ -1132,6 +1132,8 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        onenand_update_bufferram(mtd, from, !ret);
                        if (ret == -EBADMSG)
                                ret = 0;
+                       if (ret)
+                               break;
                }
 
                this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
@@ -1646,11 +1648,10 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
        int ret = 0;
        int thislen, column;
 
+       column = addr & (this->writesize - 1);
+
        while (len != 0) {
-               thislen = min_t(int, this->writesize, len);
-               column = addr & (this->writesize - 1);
-               if (column + thislen > this->writesize)
-                       thislen = this->writesize - column;
+               thislen = min_t(int, this->writesize - column, len);
 
                this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
 
@@ -1664,12 +1665,13 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
 
                this->read_bufferram(mtd, ONENAND_DATARAM, this->verify_buf, 0, mtd->writesize);
 
-               if (memcmp(buf, this->verify_buf, thislen))
+               if (memcmp(buf, this->verify_buf + column, thislen))
                        return -EBADMSG;
 
                len -= thislen;
                buf += thislen;
                addr += thislen;
+               column = 0;
        }
 
        return 0;
@@ -4083,7 +4085,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        mtd->writebufsize = mtd->writesize;
 
        /* Unlock whole block */
-       this->unlock_all(mtd);
+       if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
+               this->unlock_all(mtd);
 
        ret = this->scan_bbt(mtd);
        if ((!FLEXONENAND(this)) || ret)
index ac0d6a8613b501d30dfe994bbc4e87e27cdc6e18..2b0daae4018deb07a128e31c0744283b6ff31f73 100644 (file)
@@ -64,12 +64,16 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
                                        SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET);
 
        char *vendor = kmalloc(vendor_len, GFP_KERNEL);
+       if (!vendor)
+               goto error1;
        memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len);
        vendor[vendor_len] = 0;
 
        /* Initialize sysfs attributes */
        vendor_attribute =
                kzalloc(sizeof(struct sm_sysfs_attribute), GFP_KERNEL);
+       if (!vendor_attribute)
+               goto error2;
 
        sysfs_attr_init(&vendor_attribute->dev_attr.attr);
 
@@ -83,12 +87,24 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
        /* Create array of pointers to the attributes */
        attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1),
                                                                GFP_KERNEL);
+       if (!attributes)
+               goto error3;
        attributes[0] = &vendor_attribute->dev_attr.attr;
 
        /* Finally create the attribute group */
        attr_group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+       if (!attr_group)
+               goto error4;
        attr_group->attrs = attributes;
        return attr_group;
+error4:
+       kfree(attributes);
+error3:
+       kfree(vendor_attribute);
+error2:
+       kfree(vendor);
+error1:
+       return NULL;
 }
 
 void sm_delete_sysfs_attributes(struct sm_ftl *ftl)
@@ -1178,6 +1194,8 @@ static void sm_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        }
 
        ftl->disk_attributes = sm_create_sysfs_attributes(ftl);
+       if (!ftl->disk_attributes)
+               goto error6;
        trans->disk_attributes = ftl->disk_attributes;
 
        sm_printk("Found %d MiB xD/SmartMedia FTL on mtd%d",
index 161feeb7b8b9dc299c2adfcc0f1bd13c8134e273..627d4e2466a3bccbedd3ca27c304f2b47bd414ca 100644 (file)
@@ -16,7 +16,7 @@
  *
  * Test read and write speed of a MTD device.
  *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ * Author: Adrian Hunter <adrian.hunter@nokia.com>
  */
 
 #include <linux/init.h>
@@ -33,6 +33,11 @@ static int dev;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
+static int count;
+module_param(count, int, S_IRUGO);
+MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use "
+                       "(0 means use all)");
+
 static struct mtd_info *mtd;
 static unsigned char *iobuf;
 static unsigned char *bbt;
@@ -89,6 +94,33 @@ static int erase_eraseblock(int ebnum)
        return 0;
 }
 
+static int multiblock_erase(int ebnum, int blocks)
+{
+       int err;
+       struct erase_info ei;
+       loff_t addr = ebnum * mtd->erasesize;
+
+       memset(&ei, 0, sizeof(struct erase_info));
+       ei.mtd  = mtd;
+       ei.addr = addr;
+       ei.len  = mtd->erasesize * blocks;
+
+       err = mtd->erase(mtd, &ei);
+       if (err) {
+               printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
+                      err, ebnum, blocks);
+               return err;
+       }
+
+       if (ei.state == MTD_ERASE_FAILED) {
+               printk(PRINT_PREF "some erase error occurred at EB %d,"
+                      "blocks %d\n", ebnum, blocks);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int erase_whole_device(void)
 {
        int err;
@@ -282,13 +314,16 @@ static inline void stop_timing(void)
 
 static long calc_speed(void)
 {
-       long ms, k, speed;
+       uint64_t k;
+       long ms;
 
        ms = (finish.tv_sec - start.tv_sec) * 1000 +
             (finish.tv_usec - start.tv_usec) / 1000;
-       k = goodebcnt * mtd->erasesize / 1024;
-       speed = (k * 1000) / ms;
-       return speed;
+       if (ms == 0)
+               return 0;
+       k = goodebcnt * (mtd->erasesize / 1024) * 1000;
+       do_div(k, ms);
+       return k;
 }
 
 static int scan_for_bad_eraseblocks(void)
@@ -320,13 +355,16 @@ out:
 
 static int __init mtd_speedtest_init(void)
 {
-       int err, i;
+       int err, i, blocks, j, k;
        long speed;
        uint64_t tmp;
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       if (count)
+               printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
+       else
+               printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
@@ -353,6 +391,9 @@ static int __init mtd_speedtest_init(void)
               (unsigned long long)mtd->size, mtd->erasesize,
               pgsize, ebcnt, pgcnt, mtd->oobsize);
 
+       if (count > 0 && count < ebcnt)
+               ebcnt = count;
+
        err = -ENOMEM;
        iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!iobuf) {
@@ -484,6 +525,31 @@ static int __init mtd_speedtest_init(void)
        speed = calc_speed();
        printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed);
 
+       /* Multi-block erase all eraseblocks */
+       for (k = 1; k < 7; k++) {
+               blocks = 1 << k;
+               printk(PRINT_PREF "Testing %dx multi-block erase speed\n",
+                      blocks);
+               start_timing();
+               for (i = 0; i < ebcnt; ) {
+                       for (j = 0; j < blocks && (i + j) < ebcnt; j++)
+                               if (bbt[i + j])
+                                       break;
+                       if (j < 1) {
+                               i++;
+                               continue;
+                       }
+                       err = multiblock_erase(i, j);
+                       if (err)
+                               goto out;
+                       cond_resched();
+                       i += j;
+               }
+               stop_timing();
+               speed = calc_speed();
+               printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n",
+                      blocks, speed);
+       }
        printk(PRINT_PREF "finished\n");
 out:
        kfree(iobuf);
index 11204e8aab5f33bb4bcb51c150ab30e63139f8f2..334eae53a3dba64a50ce117d83883434fa53cd91 100644 (file)
@@ -394,6 +394,11 @@ static int __init mtd_subpagetest_init(void)
        }
 
        subpgsize = mtd->writesize >> mtd->subpage_sft;
+       tmp = mtd->size;
+       do_div(tmp, mtd->erasesize);
+       ebcnt = tmp;
+       pgcnt = mtd->erasesize / mtd->writesize;
+
        printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
               "page size %u, subpage size %u, count of eraseblocks %u, "
               "pages per eraseblock %u, OOB size %u\n",
@@ -413,11 +418,6 @@ static int __init mtd_subpagetest_init(void)
                goto out;
        }
 
-       tmp = mtd->size;
-       do_div(tmp, mtd->erasesize);
-       ebcnt = tmp;
-       pgcnt = mtd->erasesize / mtd->writesize;
-
        err = scan_for_bad_eraseblocks();
        if (err)
                goto out;
index 22abfb39d8131f4f9685fd4a914c0aa2873b525a..68d45ba2d9b9a0844c0c1691a31e07bf7374168b 100644 (file)
@@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev)
 
        if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
                opmode |= RMII; /* For Now only 100MBit are supported */
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
-               opmode |= TE;
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
+               if (__SILICON_REVISION__ < 3) {
+                       /*
+                        * This isn't publicly documented (fun times!), but in
+                        * silicon <=0.2, the RX and TX pins are clocked together.
+                        * So in order to recv, we must enable the transmit side
+                        * as well.  This will cause a spurious TX interrupt too,
+                        * but we can easily consume that.
+                        */
+                       opmode |= TE;
+               }
 #endif
        }
 
index d1865cc973130d2674bb8a3b907fca36ed293008..8e6d618b53052139981cf5cc6df6720d11382a0c 100644 (file)
@@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
 #endif
 };
 
-static void inline vlan_features_add(struct net_device *dev, u32 flags)
+static inline void vlan_features_add(struct net_device *dev, u32 flags)
 {
        dev->vlan_features |= flags;
 }
index 110eda01843c6033de8d27afea9ada737da35996..31552959aed7baa4895ac386d390b0a331abde6e 100644 (file)
@@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev)
 {
        struct c_can_priv *priv = netdev_priv(dev);
 
-       if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
-               /* disable automatic retransmission */
-               priv->write_reg(priv, &priv->regs->control,
-                               CONTROL_DISABLE_AR);
-       else
-               /* enable automatic retransmission */
-               priv->write_reg(priv, &priv->regs->control,
-                               CONTROL_ENABLE_AR);
+       /* enable automatic retransmission */
+       priv->write_reg(priv, &priv->regs->control,
+                       CONTROL_ENABLE_AR);
 
        if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
                                        CAN_CTRLMODE_LOOPBACK)) {
@@ -704,7 +699,6 @@ static void c_can_do_tx(struct net_device *dev)
 
        for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
                msg_obj_no = get_tx_echo_msg_obj(priv);
-               c_can_inval_msg_object(dev, 0, msg_obj_no);
                val = c_can_read_reg32(priv, &priv->regs->txrqst1);
                if (!(val & (1 << msg_obj_no))) {
                        can_get_echo_skb(dev,
@@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev)
                                        &priv->regs->ifregs[0].msg_cntrl)
                                        & IF_MCONT_DLC_MASK;
                        stats->tx_packets++;
+                       c_can_inval_msg_object(dev, 0, msg_obj_no);
                }
        }
 
@@ -1112,8 +1107,7 @@ struct net_device *alloc_c_can_dev(void)
        priv->can.bittiming_const = &c_can_bittiming_const;
        priv->can.do_set_mode = c_can_set_mode;
        priv->can.do_get_berr_counter = c_can_get_berr_counter;
-       priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT |
-                                       CAN_CTRLMODE_LOOPBACK |
+       priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
                                        CAN_CTRLMODE_LISTENONLY |
                                        CAN_CTRLMODE_BERR_REPORTING;
 
index e629b961ae2d710292c624dda6519f8f2488c121..cc90824f2c9c2dc36ce8ab57f44741c307cd90bd 100644 (file)
@@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
        void __iomem *addr;
        struct net_device *dev;
        struct c_can_priv *priv;
-       struct resource *mem, *irq;
+       struct resource *mem;
+       int irq;
 #ifdef CONFIG_HAVE_CLK
        struct clk *clk;
 
@@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
 
        /* get the platform data */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!mem || (irq <= 0)) {
+       irq = platform_get_irq(pdev, 0);
+       if (!mem || irq <= 0) {
                ret = -ENODEV;
                goto exit_free_clk;
        }
@@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
 
        priv = netdev_priv(dev);
 
-       dev->irq = irq->start;
+       dev->irq = irq;
        priv->regs = addr;
 #ifdef CONFIG_HAVE_CLK
        priv->can.clock.freq = clk_get_rate(clk);
index 4d538a4e9d553389c99b95fdd02ce9170438766f..910893143295fbdba6d14651bf67b6ff5bc09e76 100644 (file)
@@ -1983,14 +1983,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
 {
        struct port_info *pi = netdev_priv(dev);
        struct adapter *adapter = pi->adapter;
-       struct qset_params *qsp = &adapter->params.sge.qset[0];
-       struct sge_qset *qs = &adapter->sge.qs[0];
+       struct qset_params *qsp;
+       struct sge_qset *qs;
+       int i;
 
        if (c->rx_coalesce_usecs * 10 > M_NEWTIMER)
                return -EINVAL;
 
-       qsp->coalesce_usecs = c->rx_coalesce_usecs;
-       t3_update_qset_coalesce(qs, qsp);
+       for (i = 0; i < pi->nqsets; i++) {
+               qsp = &adapter->params.sge.qset[i];
+               qs = &adapter->sge.qs[i];
+               qsp->coalesce_usecs = c->rx_coalesce_usecs;
+               t3_update_qset_coalesce(qs, qsp);
+       }
+
        return 0;
 }
 
index 3177081136017f5d1890a55c42dfb7eb34e2fe48..b7af5bab9937397d20aa54ceac349ac16e81988e 100644 (file)
@@ -621,9 +621,9 @@ static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
                /* change in wol state, update IRQ state */
 
                if (!dm->wake_state)
-                       set_irq_wake(dm->irq_wake, 1);
+                       irq_set_irq_wake(dm->irq_wake, 1);
                else if (dm->wake_state & !opts)
-                       set_irq_wake(dm->irq_wake, 0);
+                       irq_set_irq_wake(dm->irq_wake, 0);
        }
 
        dm->wake_state = opts;
@@ -1424,13 +1424,13 @@ dm9000_probe(struct platform_device *pdev)
                } else {
 
                        /* test to see if irq is really wakeup capable */
-                       ret = set_irq_wake(db->irq_wake, 1);
+                       ret = irq_set_irq_wake(db->irq_wake, 1);
                        if (ret) {
                                dev_err(db->dev, "irq %d cannot set wakeup (%d)\n",
                                        db->irq_wake, ret);
                                ret = 0;
                        } else {
-                               set_irq_wake(db->irq_wake, 0);
+                               irq_set_irq_wake(db->irq_wake, 0);
                                db->wake_supported = 1;
                        }
                }
index f690474f44092ae1cc1872053bf28bdd92669278..994c80939c7a5d6e6b6d27d79b812a3aaa560cd1 100644 (file)
@@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme)
 {
        jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
        pci_set_power_state(jme->pdev, PCI_D0);
-       pci_enable_wake(jme->pdev, PCI_D0, false);
+       device_set_wakeup_enable(&jme->pdev->dev, false);
 }
 
 static int
@@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev,
 
        jwrite32(jme, JME_PMCS, jme->reg_pmcs);
 
+       device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
+
        return 0;
 }
 
@@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int
-jme_suspend(struct pci_dev *pdev, pm_message_t state)
+static int jme_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct jme_adapter *jme = netdev_priv(netdev);
 
@@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
        tasklet_hi_enable(&jme->rxclean_task);
        tasklet_hi_enable(&jme->rxempty_task);
 
-       pci_save_state(pdev);
        jme_powersave_phy(jme);
-       pci_enable_wake(jme->pdev, PCI_D3hot, true);
-       pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
 }
 
-static int
-jme_resume(struct pci_dev *pdev)
+static int jme_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct jme_adapter *jme = netdev_priv(netdev);
 
-       jme_clear_pm(jme);
-       pci_restore_state(pdev);
+       jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
 
        jme_phy_on(jme);
        if (test_bit(JME_FLAG_SSET, &jme->flags))
@@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev)
 
        return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume);
+#define JME_PM_OPS (&jme_pm_ops)
+
+#else
+
+#define JME_PM_OPS NULL
 #endif
 
 static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
@@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = {
        .id_table       = jme_pci_tbl,
        .probe          = jme_init_one,
        .remove         = __devexit_p(jme_remove_one),
-#ifdef CONFIG_PM
-       .suspend        = jme_suspend,
-       .resume         = jme_resume,
-#endif /* CONFIG_PM */
        .shutdown       = jme_shutdown,
+       .driver.pm      = JME_PM_OPS,
 };
 
 static int __init
index 540a8dcbcc46d805885c8762eca46e3303d25e6e..7f7d5708a658b61d8979808c43e360896e57dfb0 100644 (file)
@@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
                                goto unlock;
                        }
                        skb_copy_and_csum_dev(org_skb, skb->data);
-                       org_skb->ip_summed = 0;
+                       org_skb->ip_summed = CHECKSUM_NONE;
                        skb->len = org_skb->len;
                        copy_old_skb(org_skb, skb);
                }
index 5762ebde44557dd194212454fb9d20cd828ea822..4f158baa0246be3022c7bb2843a0e4be2a834671 100644 (file)
@@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev)
                                  0, MLX4_PROT_ETH))
                mlx4_warn(mdev, "Failed Attaching Broadcast\n");
 
+       /* Must redo promiscuous mode setup. */
+       priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
+
        /* Schedule multicast task to populate multicast list */
        queue_work(mdev->workqueue, &priv->mcast_task);
 
index 1f4e8680a96a7c8b642e3e750d4132c0766ddc7e..673dc600c891fedabe7f63eaccd295b629c31364 100644 (file)
@@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
                                 * page into an skb */
 
 static inline int
-myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
-                int bytes, int len, __wsum csum)
+myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
+                int lro_enabled)
 {
        struct myri10ge_priv *mgp = ss->mgp;
        struct sk_buff *skb;
        struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
-       int i, idx, hlen, remainder;
+       struct myri10ge_rx_buf *rx;
+       int i, idx, hlen, remainder, bytes;
        struct pci_dev *pdev = mgp->pdev;
        struct net_device *dev = mgp->dev;
        u8 *va;
 
+       if (len <= mgp->small_bytes) {
+               rx = &ss->rx_small;
+               bytes = mgp->small_bytes;
+       } else {
+               rx = &ss->rx_big;
+               bytes = mgp->big_bytes;
+       }
+
        len += MXGEFW_PAD;
        idx = rx->cnt & rx->mask;
        va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
@@ -1341,7 +1350,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
                remainder -= MYRI10GE_ALLOC_SIZE;
        }
 
-       if (dev->features & NETIF_F_LRO) {
+       if (lro_enabled) {
                rx_frags[0].page_offset += MXGEFW_PAD;
                rx_frags[0].size -= MXGEFW_PAD;
                len -= MXGEFW_PAD;
@@ -1463,7 +1472,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
 {
        struct myri10ge_rx_done *rx_done = &ss->rx_done;
        struct myri10ge_priv *mgp = ss->mgp;
-       struct net_device *netdev = mgp->dev;
+
        unsigned long rx_bytes = 0;
        unsigned long rx_packets = 0;
        unsigned long rx_ok;
@@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
        u16 length;
        __wsum checksum;
 
+       /*
+        * Prevent compiler from generating more than one ->features memory
+        * access to avoid theoretical race condition with functions that
+        * change NETIF_F_LRO flag at runtime.
+        */
+       bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO;
+
        while (rx_done->entry[idx].length != 0 && work_done < budget) {
                length = ntohs(rx_done->entry[idx].length);
                rx_done->entry[idx].length = 0;
                checksum = csum_unfold(rx_done->entry[idx].checksum);
-               if (length <= mgp->small_bytes)
-                       rx_ok = myri10ge_rx_done(ss, &ss->rx_small,
-                                                mgp->small_bytes,
-                                                length, checksum);
-               else
-                       rx_ok = myri10ge_rx_done(ss, &ss->rx_big,
-                                                mgp->big_bytes,
-                                                length, checksum);
+               rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
                rx_packets += rx_ok;
                rx_bytes += rx_ok * (unsigned long)length;
                cnt++;
@@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
        ss->stats.rx_packets += rx_packets;
        ss->stats.rx_bytes += rx_bytes;
 
-       if (netdev->features & NETIF_F_LRO)
+       if (lro_enabled)
                lro_flush_all(&rx_done->lro_mgr);
 
        /* restock receive rings if needed */
index 653d308e0f5d2d4c3a292f1ba583e013472d837a..3bdcc803ec6822a62caf4e00878905fd4ad64f5f 100644 (file)
@@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
        struct netxen_adapter *adapter = netdev_priv(netdev);
        int hw_lro;
 
-       if (data & ~ETH_FLAG_LRO)
+       if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
                return -EINVAL;
 
        if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
index 4c14510e2a87ef04a10b66021d9a5f4eebb0486a..45b2755d6cba343a591fb3412437b765b17ab303 100644 (file)
@@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        int hw_lro;
 
-       if (data & ~ETH_FLAG_LRO)
+       if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
                return -EINVAL;
 
        if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
index 2ad6364103ea45db5c0f8094172d1a51c0401479..356e74d20b80f1d30f73650c23ef6acc1e7569ed 100644 (file)
@@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
        int rc = 0;
        int changed = 0;
 
-       if (data & ~ETH_FLAG_LRO)
+       if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
                return -EINVAL;
 
        if (data & ETH_FLAG_LRO) {
index ebec88882c3b07fdbfb37e312546b33431bf9b40..73c942d85f074fde4eaaf5cb7ab5f540fa4d25cd 100644 (file)
@@ -48,9 +48,9 @@
 #include <net/ip.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
@@ -13118,7 +13118,7 @@ done:
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
 
-static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+static inline void vlan_features_add(struct net_device *dev, unsigned long flags)
 {
        dev->vlan_features |= flags;
 }
index 81254be85b92629288e21f6f94ecbfe5f4ac5a1b..51f2ef142a5b635cca3f15239b830d2b554d6d6d 100644 (file)
@@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
        u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
        unsigned long flags;
 
-       if (data & ~ETH_FLAG_LRO)
-               return -EOPNOTSUPP;
+       if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
+               return -EINVAL;
 
        if (lro_requested ^ lro_present) {
                /* toggle the LRO feature*/
index 1dd3a21b3a4365110690f2ae3953185d361baba6..c5eb034107fdd10a908218203fe3332c902b1c66 100644 (file)
@@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data)
        struct vxgedev *vdev = netdev_priv(dev);
        enum vxge_hw_status status;
 
-       if (data & ~ETH_FLAG_RXHASH)
-               return -EOPNOTSUPP;
+       if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
+               return -EINVAL;
 
        if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
                return 0;
index 18d24b7b1e3475c7f42c70204fa6d45105e07b81..7ecc0bda57b350b591ea6a9a5bad2b93c145c9fc 100644 (file)
@@ -649,8 +649,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
                goto err_free_common;
        }
 
-       set_irq_type(gpio_to_irq(p54spi_gpio_irq),
-                    IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
 
        disable_irq(gpio_to_irq(p54spi_gpio_irq));
 
index d550b5e68d3cbea24ff262ea3766d01ef901f940..f51a0241a44044d17380ad8951f30d6ff5ad2fd2 100644 (file)
@@ -265,7 +265,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
                        goto disable;
                }
 
-               set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
                disable_irq(wl->irq);
 
                wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
index ac872b38960f7a1d47089ba9f754b5c37aa7e2f5..af6448c4d3e238554d154aeaab1a59c79e609bcf 100644 (file)
@@ -286,7 +286,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
                goto out_free;
        }
 
-       set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+       irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
 
        disable_irq(wl->irq);
 
index deeec32a5803c30834469819102f7efac98342ed..103095bbe8c09bd35b5c76e9faff6f62dfeab8a2 100644 (file)
@@ -340,7 +340,7 @@ static int __init eisa_probe(struct parisc_device *dev)
        /* Reserve IRQ2 */
        setup_irq(2, &irq2_action);
        for (i = 0; i < 16; i++) {
-               set_irq_chip_and_handler(i, &eisa_interrupt_type,
+               irq_set_chip_and_handler(i, &eisa_interrupt_type,
                                         handle_simple_irq);
        }
        
index ef31080cf5912323d31284fd3ddb2b0036158aea..1bab5a2cd359ffefbcff50b2e02f6e06e2f9ad86 100644 (file)
@@ -152,8 +152,8 @@ int gsc_assign_irq(struct irq_chip *type, void *data)
        if (irq > GSC_IRQ_MAX)
                return NO_IRQ;
 
-       set_irq_chip_and_handler(irq, type, handle_simple_irq);
-       set_irq_chip_data(irq, data);
+       irq_set_chip_and_handler(irq, type, handle_simple_irq);
+       irq_set_chip_data(irq, data);
 
        return irq++;
 }
index a4d8ff66a63901833ec06a6eb69830d6246d0d8e..e3b76d409dee7bc99b7f80af845e8b52ae5a18d5 100644 (file)
@@ -355,7 +355,8 @@ int superio_fixup_irq(struct pci_dev *pcidev)
 #endif
 
        for (i = 0; i < 16; i++) {
-               set_irq_chip_and_handler(i, &superio_interrupt_type, handle_simple_irq);
+               irq_set_chip_and_handler(i, &superio_interrupt_type,
+                                        handle_simple_irq);
        }
 
        /*
index 09933eb9126be48f154e809bdcfdc57292a4858a..12e02bf92c4ac81f8fce8b8c18e96dc298e05b2d 100644 (file)
@@ -1226,7 +1226,7 @@ const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
 
 void dmar_msi_unmask(struct irq_data *data)
 {
-       struct intel_iommu *iommu = irq_data_get_irq_data(data);
+       struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
        unsigned long flag;
 
        /* unmask it */
@@ -1240,7 +1240,7 @@ void dmar_msi_unmask(struct irq_data *data)
 void dmar_msi_mask(struct irq_data *data)
 {
        unsigned long flag;
-       struct intel_iommu *iommu = irq_data_get_irq_data(data);
+       struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
 
        /* mask it */
        spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1252,7 +1252,7 @@ void dmar_msi_mask(struct irq_data *data)
 
 void dmar_msi_write(int irq, struct msi_msg *msg)
 {
-       struct intel_iommu *iommu = get_irq_data(irq);
+       struct intel_iommu *iommu = irq_get_handler_data(irq);
        unsigned long flag;
 
        spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1264,7 +1264,7 @@ void dmar_msi_write(int irq, struct msi_msg *msg)
 
 void dmar_msi_read(int irq, struct msi_msg *msg)
 {
-       struct intel_iommu *iommu = get_irq_data(irq);
+       struct intel_iommu *iommu = irq_get_handler_data(irq);
        unsigned long flag;
 
        spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1382,12 +1382,12 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
                return -EINVAL;
        }
 
-       set_irq_data(irq, iommu);
+       irq_set_handler_data(irq, iommu);
        iommu->irq = irq;
 
        ret = arch_setup_dmar_msi(irq);
        if (ret) {
-               set_irq_data(irq, NULL);
+               irq_set_handler_data(irq, NULL);
                iommu->irq = 0;
                destroy_irq(irq);
                return ret;
index 834842aa5bbf7926b61810cce47c47cb158b1f83..db057b6fe0c8bccf12710cee1c488d77def872f9 100644 (file)
@@ -34,7 +34,7 @@ struct ht_irq_cfg {
 
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
-       struct ht_irq_cfg *cfg = get_irq_data(irq);
+       struct ht_irq_cfg *cfg = irq_get_handler_data(irq);
        unsigned long flags;
        spin_lock_irqsave(&ht_irq_lock, flags);
        if (cfg->msg.address_lo != msg->address_lo) {
@@ -53,13 +53,13 @@ void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
-       struct ht_irq_cfg *cfg = get_irq_data(irq);
+       struct ht_irq_cfg *cfg = irq_get_handler_data(irq);
        *msg = cfg->msg;
 }
 
 void mask_ht_irq(struct irq_data *data)
 {
-       struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+       struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data);
        struct ht_irq_msg msg = cfg->msg;
 
        msg.address_lo |= 1;
@@ -68,7 +68,7 @@ void mask_ht_irq(struct irq_data *data)
 
 void unmask_ht_irq(struct irq_data *data)
 {
-       struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+       struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data);
        struct ht_irq_msg msg = cfg->msg;
 
        msg.address_lo &= ~1;
@@ -126,7 +126,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
                kfree(cfg);
                return -EBUSY;
        }
-       set_irq_data(irq, cfg);
+       irq_set_handler_data(irq, cfg);
 
        if (arch_setup_ht_irq(irq, dev) < 0) {
                ht_destroy_irq(irq);
@@ -162,9 +162,9 @@ void ht_destroy_irq(unsigned int irq)
 {
        struct ht_irq_cfg *cfg;
 
-       cfg = get_irq_data(irq);
-       set_irq_chip(irq, NULL);
-       set_irq_data(irq, NULL);
+       cfg = irq_get_handler_data(irq);
+       irq_set_chip(irq, NULL);
+       irq_set_handler_data(irq, NULL);
        destroy_irq(irq);
 
        kfree(cfg);
index a4115f1afe1f206acbefa24fa3999a45a9704cb9..7da3bef60d8708c12f2cc421de27ef968b00eb1e 100644 (file)
@@ -1206,7 +1206,7 @@ void free_dmar_iommu(struct intel_iommu *iommu)
                iommu_disable_translation(iommu);
 
        if (iommu->irq) {
-               set_irq_data(iommu->irq, NULL);
+               irq_set_handler_data(iommu->irq, NULL);
                /* This will mask the irq */
                free_irq(iommu->irq, iommu);
                destroy_irq(iommu->irq);
index ec87cd66f3eb21b792381b52c6d8f1656beadede..a22557b20283de2e84c477dcaae07ed3872fc359 100644 (file)
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(irq_2_ir_lock);
 
 static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
-       struct irq_cfg *cfg = get_irq_chip_data(irq);
+       struct irq_cfg *cfg = irq_get_chip_data(irq);
        return cfg ? &cfg->irq_2_iommu : NULL;
 }
 
index 44b0aeee83e52c1bcbeeaa73417ec577681cfe0a..2f10328bf661234437c1e862f7d4e1a96afeabb3 100644 (file)
@@ -236,7 +236,7 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 
 void read_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_msi(irq);
+       struct msi_desc *entry = irq_get_msi_desc(irq);
 
        __read_msi_msg(entry, msg);
 }
@@ -253,7 +253,7 @@ void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 
 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_msi(irq);
+       struct msi_desc *entry = irq_get_msi_desc(irq);
 
        __get_cached_msi_msg(entry, msg);
 }
@@ -297,7 +297,7 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 
 void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_msi(irq);
+       struct msi_desc *entry = irq_get_msi_desc(irq);
 
        __write_msi_msg(entry, msg);
 }
@@ -354,7 +354,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
        if (!dev->msi_enabled)
                return;
 
-       entry = get_irq_msi(dev->irq);
+       entry = irq_get_msi_desc(dev->irq);
        pos = entry->msi_attrib.pos;
 
        pci_intx_for_msi(dev, 0);
@@ -519,7 +519,7 @@ static void msix_program_entries(struct pci_dev *dev,
                                                PCI_MSIX_ENTRY_VECTOR_CTRL;
 
                entries[i].vector = entry->irq;
-               set_irq_msi(entry->irq, entry);
+               irq_set_msi_desc(entry->irq, entry);
                entry->masked = readl(entry->mask_base + offset);
                msix_mask_irq(entry, 1);
                i++;
index eae9cbe37a3e5f4cddc9bf75bccc04b9bc886a33..49221395101e6ae8590fc09ac28af2552df1cbd4 100644 (file)
@@ -235,7 +235,7 @@ static int __devinit bfin_cf_probe(struct platform_device *pdev)
        cf->irq = irq;
        cf->socket.pci_irq = irq;
 
-       set_irq_type(irq, IRQF_TRIGGER_LOW);
+       irq_set_irq_type(irq, IRQF_TRIGGER_LOW);
 
        io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
index 27575e6378a1a6259410e3882004cbb68a716281..01757f18a2083fb19cd15018cc1af9bff16f7207 100644 (file)
@@ -181,7 +181,7 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
                /* all other (older) Db1x00 boards use a GPIO to show
                 * card detection status:  use both-edge triggers.
                 */
-               set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
+               irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
                ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
                                  0, "pcmcia_carddetect", sock);
 
index 3d2652e2f5ae03e7860e09c33f71cec17273f15d..93b9c9ba57c3a9cbe716038b8b9d473106151e3d 100644 (file)
@@ -86,7 +86,7 @@ static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
        GPDR &= ~nano_skts[i].input_pins;
        GPDR |= nano_skts[i].output_pins;
        GPCR = nano_skts[i].clear_outputs;
-       set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
        skt->socket.pci_irq = nano_skts[i].pci_irq;
 
        return soc_pcmcia_request_irqs(skt,
index 5a9a392eacdf18d1ba9de1237f11f0a3efefbf7d..768f9572a8c88cca0c91bf8a977060b638ceae6f 100644 (file)
@@ -155,11 +155,11 @@ static int soc_common_pcmcia_config_skt(
                 */
                if (skt->irq_state != 1 && state->io_irq) {
                        skt->irq_state = 1;
-                       set_irq_type(skt->socket.pci_irq,
-                               IRQ_TYPE_EDGE_FALLING);
+                       irq_set_irq_type(skt->socket.pci_irq,
+                                        IRQ_TYPE_EDGE_FALLING);
                } else if (skt->irq_state == 1 && state->io_irq == 0) {
                        skt->irq_state = 0;
-                       set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
+                       irq_set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
                }
 
                skt->cs_state = *state;
@@ -537,7 +537,7 @@ int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt,
                                  IRQF_DISABLED, irqs[i].str, skt);
                if (res)
                        break;
-               set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
+               irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
        }
 
        if (res) {
@@ -570,7 +570,7 @@ void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
 
        for (i = 0; i < nr; i++)
                if (irqs[i].sock == skt->nr)
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
+                       irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
 }
 EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
 
@@ -581,8 +581,8 @@ void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
 
        for (i = 0; i < nr; i++)
                if (irqs[i].sock == skt->nr) {
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
+                       irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
+                       irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
                }
 }
 EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
index 3b67a1b6a1972670c5c305c94b64c8677a720fb8..379f4218857d9446a82882e353d5300621254d99 100644 (file)
@@ -274,7 +274,7 @@ static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
         * edge detector.
         */
        irq = gpio_to_irq(GPIO_CDA);
-       set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+       irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
        ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
        if (ret) {
                dev_err(&pdev->dev, "cannot setup cd irq\n");
index 222dfb737b11a699d559c12c23e26a7577ab99de..2ee442c2a5db094df620a50bcbdf03072fc64336 100644 (file)
@@ -101,6 +101,19 @@ config DELL_WMI
          To compile this driver as a module, choose M here: the module will
          be called dell-wmi.
 
+config DELL_WMI_AIO
+       tristate "WMI Hotkeys for Dell All-In-One series"
+       depends on ACPI_WMI
+       depends on INPUT
+       select INPUT_SPARSEKMAP
+       ---help---
+         Say Y here if you want to support WMI-based hotkeys on Dell
+         All-In-One machines.
+
+         To compile this driver as a module, choose M here: the module will
+         be called dell-wmi.
+
+
 config FUJITSU_LAPTOP
        tristate "Fujitsu Laptop Extras"
        depends on ACPI
@@ -438,23 +451,53 @@ config EEEPC_LAPTOP
          Bluetooth, backlight and allows powering on/off some other
          devices.
 
-         If you have an Eee PC laptop, say Y or M here.
+         If you have an Eee PC laptop, say Y or M here. If this driver
+         doesn't work on your Eee PC, try eeepc-wmi instead.
 
-config EEEPC_WMI
-       tristate "Eee PC WMI Hotkey Driver (EXPERIMENTAL)"
+config ASUS_WMI
+       tristate "ASUS WMI Driver (EXPERIMENTAL)"
        depends on ACPI_WMI
        depends on INPUT
+       depends on HWMON
        depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
+       depends on HOTPLUG_PCI
        select INPUT_SPARSEKMAP
        select LEDS_CLASS
        select NEW_LEDS
        ---help---
-         Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
+         Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
+         Asus Notebooks).
 
          To compile this driver as a module, choose M here: the module will
-         be called eeepc-wmi.
+         be called asus-wmi.
+
+config ASUS_NB_WMI
+       tristate "Asus Notebook WMI Driver (EXPERIMENTAL)"
+       depends on ASUS_WMI
+       ---help---
+         This is a driver for newer Asus notebooks. It adds extra features
+         like wireless radio and bluetooth control, leds, hotkeys, backlight...
+
+         For more informations, see
+         <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
+
+         If you have an ACPI-WMI compatible Asus Notebook, say Y or M
+         here.
+
+config EEEPC_WMI
+       tristate "Eee PC WMI Driver (EXPERIMENTAL)"
+       depends on ASUS_WMI
+       ---help---
+         This is a driver for newer Eee PC laptops. It adds extra features
+         like wireless radio and bluetooth control, leds, hotkeys, backlight...
+
+         For more informations, see
+         <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
+
+         If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M
+         here.
 
 config ACPI_WMI
        tristate "WMI"
@@ -616,6 +659,21 @@ config GPIO_INTEL_PMIC
          Say Y here to support GPIO via the SCU IPC interface
          on Intel MID platforms.
 
+config INTEL_MID_POWER_BUTTON
+       tristate "power button driver for Intel MID platforms"
+       depends on INTEL_SCU_IPC && INPUT
+       help
+         This driver handles the power button on the Intel MID platforms.
+
+         If unsure, say N.
+
+config INTEL_MFLD_THERMAL
+       tristate "Thermal driver for Intel Medfield platform"
+       depends on INTEL_SCU_IPC && THERMAL
+       help
+         Say Y here to enable thermal driver support for the  Intel Medfield
+         platform.
+
 config RAR_REGISTER
        bool "Restricted Access Region Register Driver"
        depends on PCI && X86_MRST
@@ -672,4 +730,26 @@ config XO1_RFKILL
          Support for enabling/disabling the WLAN interface on the OLPC XO-1
          laptop.
 
+config XO15_EBOOK
+       tristate "OLPC XO-1.5 ebook switch"
+       depends on ACPI && INPUT
+       ---help---
+         Support for the ebook switch on the OLPC XO-1.5 laptop.
+
+         This switch is triggered as the screen is rotated and folded down to
+         convert the device into ebook form.
+
+config SAMSUNG_LAPTOP
+       tristate "Samsung Laptop driver"
+       depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
+       ---help---
+         This module implements a driver for a wide range of different
+         Samsung laptops.  It offers control over the different
+         function keys, wireless LED, LCD backlight level, and
+         sometimes provides a "performance_control" sysfs file to allow
+         the performance level of the laptop to be changed.
+
+         To compile this driver as a module, choose M here: the module
+         will be called samsung-laptop.
+
 endif # X86_PLATFORM_DEVICES
index 299aefb3e74ce222b0a146703b601fe73b1f933d..029e8861d086d19cbc5c28bafb15a449717a0af4 100644 (file)
@@ -3,6 +3,8 @@
 # x86 Platform-Specific Drivers
 #
 obj-$(CONFIG_ASUS_LAPTOP)      += asus-laptop.o
+obj-$(CONFIG_ASUS_WMI)         += asus-wmi.o
+obj-$(CONFIG_ASUS_NB_WMI)      += asus-nb-wmi.o
 obj-$(CONFIG_EEEPC_LAPTOP)     += eeepc-laptop.o
 obj-$(CONFIG_EEEPC_WMI)                += eeepc-wmi.o
 obj-$(CONFIG_MSI_LAPTOP)       += msi-laptop.o
@@ -10,6 +12,7 @@ obj-$(CONFIG_ACPI_CMPC)               += classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)    += compal-laptop.o
 obj-$(CONFIG_DELL_LAPTOP)      += dell-laptop.o
 obj-$(CONFIG_DELL_WMI)         += dell-wmi.o
+obj-$(CONFIG_DELL_WMI_AIO)     += dell-wmi-aio.o
 obj-$(CONFIG_ACER_WMI)         += acer-wmi.o
 obj-$(CONFIG_ACERHDF)          += acerhdf.o
 obj-$(CONFIG_HP_ACCEL)         += hp_accel.o
@@ -29,9 +32,13 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
 obj-$(CONFIG_TOSHIBA_BT_RFKILL)        += toshiba_bluetooth.o
 obj-$(CONFIG_INTEL_SCU_IPC)    += intel_scu_ipc.o
-obj-$(CONFIG_INTEL_SCU_IPC_UTIL)+= intel_scu_ipcutil.o
+obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
+obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
 obj-$(CONFIG_RAR_REGISTER)     += intel_rar_register.o
 obj-$(CONFIG_INTEL_IPS)                += intel_ips.o
 obj-$(CONFIG_GPIO_INTEL_PMIC)  += intel_pmic_gpio.o
 obj-$(CONFIG_XO1_RFKILL)       += xo1-rfkill.o
+obj-$(CONFIG_XO15_EBOOK)       += xo15-ebook.o
 obj-$(CONFIG_IBM_RTL)          += ibm_rtl.o
+obj-$(CONFIG_SAMSUNG_LAPTOP)   += samsung-laptop.o
+obj-$(CONFIG_INTEL_MFLD_THERMAL)       += intel_mid_thermal.o
index c9784705f6ac41ca63666b6d330cfb651c080b0b..5ea6c3477d17da4f17f3f07059329fdff1212da3 100644 (file)
@@ -22,6 +22,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -46,12 +48,6 @@ MODULE_AUTHOR("Carlos Corbacho");
 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
 MODULE_LICENSE("GPL");
 
-#define ACER_LOGPREFIX "acer-wmi: "
-#define ACER_ERR KERN_ERR ACER_LOGPREFIX
-#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
-#define ACER_INFO KERN_INFO ACER_LOGPREFIX
-#define ACER_WARNING KERN_WARNING ACER_LOGPREFIX
-
 /*
  * Magic Number
  * Meaning is unknown - this number is required for writing to ACPI for AMW0
@@ -84,7 +80,7 @@ MODULE_LICENSE("GPL");
 #define AMW0_GUID1             "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
 #define AMW0_GUID2             "431F16ED-0C2B-444C-B267-27DEB140CF9C"
 #define WMID_GUID1             "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
-#define WMID_GUID2             "95764E09-FB56-4e83-B31A-37761F60994A"
+#define WMID_GUID2             "95764E09-FB56-4E83-B31A-37761F60994A"
 #define WMID_GUID3             "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
 
 /*
@@ -93,7 +89,7 @@ MODULE_LICENSE("GPL");
 #define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
 
 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
-MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3");
+MODULE_ALIAS("wmi:6AF4F258-B401-42Fd-BE91-3D4AC2D7C0D3");
 MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
 
 enum acer_wmi_event_ids {
@@ -108,7 +104,7 @@ static const struct key_entry acer_wmi_keymap[] = {
        {KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
        {KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
        {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
-       {KE_KEY, 0x82, {KEY_F22} },      /* Touch Pad On/Off */
+       {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
        {KE_END, 0}
 };
 
@@ -221,6 +217,7 @@ struct acer_debug {
 static struct rfkill *wireless_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *threeg_rfkill;
+static bool rfkill_inited;
 
 /* Each low-level interface must define at least some of the following */
 struct wmi_interface {
@@ -845,7 +842,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
        has_type_aa = true;
        type_aa = (struct hotkey_function_type_aa *) header;
 
-       printk(ACER_INFO "Function bitmap for Communication Button: 0x%x\n",
+       pr_info("Function bitmap for Communication Button: 0x%x\n",
                type_aa->commun_func_bitmap);
 
        if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
@@ -991,6 +988,7 @@ static int __devinit acer_led_init(struct device *dev)
 
 static void acer_led_exit(void)
 {
+       set_u32(LED_OFF, ACER_CAP_MAILLED);
        led_classdev_unregister(&mail_led);
 }
 
@@ -1036,7 +1034,7 @@ static int __devinit acer_backlight_init(struct device *dev)
        bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
                                       &props);
        if (IS_ERR(bd)) {
-               printk(ACER_ERR "Could not register Acer backlight device\n");
+               pr_err("Could not register Acer backlight device\n");
                acer_backlight_device = NULL;
                return PTR_ERR(bd);
        }
@@ -1083,8 +1081,7 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
                return AE_ERROR;
        }
        if (obj->buffer.length != 8) {
-               printk(ACER_WARNING "Unknown buffer length %d\n",
-                       obj->buffer.length);
+               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1093,7 +1090,7 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
        kfree(obj);
 
        if (return_value.error_code || return_value.ec_return_value)
-               printk(ACER_WARNING "Get Device Status failed: "
+               pr_warning("Get Device Status failed: "
                        "0x%x - 0x%x\n", return_value.error_code,
                        return_value.ec_return_value);
        else
@@ -1161,9 +1158,13 @@ static int acer_rfkill_set(void *data, bool blocked)
 {
        acpi_status status;
        u32 cap = (unsigned long)data;
-       status = set_u32(!blocked, cap);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
+
+       if (rfkill_inited) {
+               status = set_u32(!blocked, cap);
+               if (ACPI_FAILURE(status))
+                       return -ENODEV;
+       }
+
        return 0;
 }
 
@@ -1187,14 +1188,16 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
                return ERR_PTR(-ENOMEM);
 
        status = get_device_status(&state, cap);
-       if (ACPI_SUCCESS(status))
-               rfkill_init_sw_state(rfkill_dev, !state);
 
        err = rfkill_register(rfkill_dev);
        if (err) {
                rfkill_destroy(rfkill_dev);
                return ERR_PTR(err);
        }
+
+       if (ACPI_SUCCESS(status))
+               rfkill_set_sw_state(rfkill_dev, !state);
+
        return rfkill_dev;
 }
 
@@ -1229,14 +1232,19 @@ static int acer_rfkill_init(struct device *dev)
                }
        }
 
-       schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
+       rfkill_inited = true;
+
+       if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+               schedule_delayed_work(&acer_rfkill_work,
+                       round_jiffies_relative(HZ));
 
        return 0;
 }
 
 static void acer_rfkill_exit(void)
 {
-       cancel_delayed_work_sync(&acer_rfkill_work);
+       if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+               cancel_delayed_work_sync(&acer_rfkill_work);
 
        rfkill_unregister(wireless_rfkill);
        rfkill_destroy(wireless_rfkill);
@@ -1309,7 +1317,7 @@ static void acer_wmi_notify(u32 value, void *context)
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
-               printk(ACER_WARNING "bad event status 0x%x\n", status);
+               pr_warning("bad event status 0x%x\n", status);
                return;
        }
 
@@ -1318,14 +1326,12 @@ static void acer_wmi_notify(u32 value, void *context)
        if (!obj)
                return;
        if (obj->type != ACPI_TYPE_BUFFER) {
-               printk(ACER_WARNING "Unknown response received %d\n",
-                       obj->type);
+               pr_warning("Unknown response received %d\n", obj->type);
                kfree(obj);
                return;
        }
        if (obj->buffer.length != 8) {
-               printk(ACER_WARNING "Unknown buffer length %d\n",
-                       obj->buffer.length);
+               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return;
        }
@@ -1335,13 +1341,26 @@ static void acer_wmi_notify(u32 value, void *context)
 
        switch (return_value.function) {
        case WMID_HOTKEY_EVENT:
+               if (return_value.device_state) {
+                       u16 device_state = return_value.device_state;
+                       pr_debug("deivces states: 0x%x\n", device_state);
+                       if (has_cap(ACER_CAP_WIRELESS))
+                               rfkill_set_sw_state(wireless_rfkill,
+                               !(device_state & ACER_WMID3_GDS_WIRELESS));
+                       if (has_cap(ACER_CAP_BLUETOOTH))
+                               rfkill_set_sw_state(bluetooth_rfkill,
+                               !(device_state & ACER_WMID3_GDS_BLUETOOTH));
+                       if (has_cap(ACER_CAP_THREEG))
+                               rfkill_set_sw_state(threeg_rfkill,
+                               !(device_state & ACER_WMID3_GDS_THREEG));
+               }
                if (!sparse_keymap_report_event(acer_wmi_input_dev,
                                return_value.key_num, 1, true))
-                       printk(ACER_WARNING "Unknown key number - 0x%x\n",
+                       pr_warning("Unknown key number - 0x%x\n",
                                return_value.key_num);
                break;
        default:
-               printk(ACER_WARNING "Unknown function number - %d - %d\n",
+               pr_warning("Unknown function number - %d - %d\n",
                        return_value.function, return_value.key_num);
                break;
        }
@@ -1370,8 +1389,7 @@ wmid3_set_lm_mode(struct lm_input_params *params,
                return AE_ERROR;
        }
        if (obj->buffer.length != 4) {
-               printk(ACER_WARNING "Unknown buffer length %d\n",
-                      obj->buffer.length);
+               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1396,11 +1414,11 @@ static int acer_wmi_enable_ec_raw(void)
        status = wmid3_set_lm_mode(&params, &return_value);
 
        if (return_value.error_code || return_value.ec_return_value)
-               printk(ACER_WARNING "Enabling EC raw mode failed: "
+               pr_warning("Enabling EC raw mode failed: "
                       "0x%x - 0x%x\n", return_value.error_code,
                       return_value.ec_return_value);
        else
-               printk(ACER_INFO "Enabled EC raw mode");
+               pr_info("Enabled EC raw mode");
 
        return status;
 }
@@ -1419,7 +1437,7 @@ static int acer_wmi_enable_lm(void)
        status = wmid3_set_lm_mode(&params, &return_value);
 
        if (return_value.error_code || return_value.ec_return_value)
-               printk(ACER_WARNING "Enabling Launch Manager failed: "
+               pr_warning("Enabling Launch Manager failed: "
                       "0x%x - 0x%x\n", return_value.error_code,
                       return_value.ec_return_value);
 
@@ -1553,6 +1571,7 @@ pm_message_t state)
 
        if (has_cap(ACER_CAP_MAILLED)) {
                get_u32(&value, ACER_CAP_MAILLED);
+               set_u32(LED_OFF, ACER_CAP_MAILLED);
                data->mailled = value;
        }
 
@@ -1580,6 +1599,17 @@ static int acer_platform_resume(struct platform_device *device)
        return 0;
 }
 
+static void acer_platform_shutdown(struct platform_device *device)
+{
+       struct acer_data *data = &interface->data;
+
+       if (!data)
+               return;
+
+       if (has_cap(ACER_CAP_MAILLED))
+               set_u32(LED_OFF, ACER_CAP_MAILLED);
+}
+
 static struct platform_driver acer_platform_driver = {
        .driver = {
                .name = "acer-wmi",
@@ -1589,6 +1619,7 @@ static struct platform_driver acer_platform_driver = {
        .remove = acer_platform_remove,
        .suspend = acer_platform_suspend,
        .resume = acer_platform_resume,
+       .shutdown = acer_platform_shutdown,
 };
 
 static struct platform_device *acer_platform_device;
@@ -1636,7 +1667,7 @@ static int create_debugfs(void)
 {
        interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
        if (!interface->debug.root) {
-               printk(ACER_ERR "Failed to create debugfs directory");
+               pr_err("Failed to create debugfs directory");
                return -ENOMEM;
        }
 
@@ -1657,11 +1688,10 @@ static int __init acer_wmi_init(void)
 {
        int err;
 
-       printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
+       pr_info("Acer Laptop ACPI-WMI Extras\n");
 
        if (dmi_check_system(acer_blacklist)) {
-               printk(ACER_INFO "Blacklisted hardware detected - "
-                               "not loading\n");
+               pr_info("Blacklisted hardware detected - not loading\n");
                return -ENODEV;
        }
 
@@ -1678,12 +1708,11 @@ static int __init acer_wmi_init(void)
 
        if (wmi_has_guid(WMID_GUID2) && interface) {
                if (ACPI_FAILURE(WMID_set_capabilities())) {
-                       printk(ACER_ERR "Unable to detect available WMID "
-                                       "devices\n");
+                       pr_err("Unable to detect available WMID devices\n");
                        return -ENODEV;
                }
        } else if (!wmi_has_guid(WMID_GUID2) && interface) {
-               printk(ACER_ERR "No WMID device detection method found\n");
+               pr_err("No WMID device detection method found\n");
                return -ENODEV;
        }
 
@@ -1691,8 +1720,7 @@ static int __init acer_wmi_init(void)
                interface = &AMW0_interface;
 
                if (ACPI_FAILURE(AMW0_set_capabilities())) {
-                       printk(ACER_ERR "Unable to detect available AMW0 "
-                                       "devices\n");
+                       pr_err("Unable to detect available AMW0 devices\n");
                        return -ENODEV;
                }
        }
@@ -1701,8 +1729,7 @@ static int __init acer_wmi_init(void)
                AMW0_find_mailled();
 
        if (!interface) {
-               printk(ACER_INFO "No or unsupported WMI interface, unable to "
-                               "load\n");
+               pr_err("No or unsupported WMI interface, unable to load\n");
                return -ENODEV;
        }
 
@@ -1710,22 +1737,22 @@ static int __init acer_wmi_init(void)
 
        if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
                interface->capability &= ~ACER_CAP_BRIGHTNESS;
-               printk(ACER_INFO "Brightness must be controlled by "
+               pr_info("Brightness must be controlled by "
                       "generic video driver\n");
        }
 
        if (wmi_has_guid(WMID_GUID3)) {
                if (ec_raw_mode) {
                        if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
-                               printk(ACER_ERR "Cannot enable EC raw mode\n");
+                               pr_err("Cannot enable EC raw mode\n");
                                return -ENODEV;
                        }
                } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
-                       printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+                       pr_err("Cannot enable Launch Manager mode\n");
                        return -ENODEV;
                }
        } else if (ec_raw_mode) {
-               printk(ACER_INFO "No WMID EC raw mode enable method\n");
+               pr_info("No WMID EC raw mode enable method\n");
        }
 
        if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
@@ -1736,7 +1763,7 @@ static int __init acer_wmi_init(void)
 
        err = platform_driver_register(&acer_platform_driver);
        if (err) {
-               printk(ACER_ERR "Unable to register platform driver.\n");
+               pr_err("Unable to register platform driver.\n");
                goto error_platform_register;
        }
 
@@ -1791,7 +1818,7 @@ static void __exit acer_wmi_exit(void)
        platform_device_unregister(acer_platform_device);
        platform_driver_unregister(&acer_platform_driver);
 
-       printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n");
+       pr_info("Acer Laptop WMI Extras unloaded\n");
        return;
 }
 
index 5a6f7d7575d61605e92c8e6bbf826ed9c2fcc6d2..c53b3ff7978a52cd339db953f65a307c128f66a7 100644 (file)
@@ -29,7 +29,7 @@
  *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
  *  Eric Burghard  - LED display support for W1N
  *  Josh Green     - Light Sens support
- *  Thomas Tuttle  - His first patch for led support was very helpfull
+ *  Thomas Tuttle  - His first patch for led support was very helpful
  *  Sam Lin        - GPS support
  */
 
@@ -50,6 +50,7 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/rfkill.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 
@@ -157,46 +158,9 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
 #define METHOD_BRIGHTNESS_SET  "SPLV"
 #define METHOD_BRIGHTNESS_GET  "GPLV"
 
-/* Backlight */
-static acpi_handle lcd_switch_handle;
-static char *lcd_switch_paths[] = {
-  "\\_SB.PCI0.SBRG.EC0._Q10",  /* All new models */
-  "\\_SB.PCI0.ISA.EC0._Q10",   /* A1x */
-  "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
-  "\\_SB.PCI0.PX40.EC0.Q10",   /* M1A */
-  "\\_SB.PCI0.LPCB.EC0._Q10",  /* P30 */
-  "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
-  "\\_SB.PCI0.PX40.Q10",       /* S1x */
-  "\\Q10"};            /* A2x, L2D, L3D, M2E */
-
 /* Display */
 #define METHOD_SWITCH_DISPLAY  "SDSP"
 
-static acpi_handle display_get_handle;
-static char *display_get_paths[] = {
-  /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
-  "\\_SB.PCI0.P0P1.VGA.GETD",
-  /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
-  "\\_SB.PCI0.P0P2.VGA.GETD",
-  /* A6V A6Q */
-  "\\_SB.PCI0.P0P3.VGA.GETD",
-  /* A6T, A6M */
-  "\\_SB.PCI0.P0PA.VGA.GETD",
-  /* L3C */
-  "\\_SB.PCI0.PCI1.VGAC.NMAP",
-  /* Z96F */
-  "\\_SB.PCI0.VGA.GETD",
-  /* A2D */
-  "\\ACTD",
-  /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
-  "\\ADVG",
-  /* P30 */
-  "\\DNXT",
-  /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
-  "\\INFB",
-  /* A3F A6F A3N A3L M6N W3N W6A */
-  "\\SSTE"};
-
 #define METHOD_ALS_CONTROL     "ALSC" /* Z71A Z71V */
 #define METHOD_ALS_LEVEL       "ALSL" /* Z71A Z71V */
 
@@ -246,7 +210,6 @@ struct asus_laptop {
 
        int wireless_status;
        bool have_rsts;
-       int lcd_state;
 
        struct rfkill *gps_rfkill;
 
@@ -559,48 +522,6 @@ error:
 /*
  * Backlight device
  */
-static int asus_lcd_status(struct asus_laptop *asus)
-{
-       return asus->lcd_state;
-}
-
-static int asus_lcd_set(struct asus_laptop *asus, int value)
-{
-       int lcd = 0;
-       acpi_status status = 0;
-
-       lcd = !!value;
-
-       if (lcd == asus_lcd_status(asus))
-               return 0;
-
-       if (!lcd_switch_handle)
-               return -ENODEV;
-
-       status = acpi_evaluate_object(lcd_switch_handle,
-                                     NULL, NULL, NULL);
-
-       if (ACPI_FAILURE(status)) {
-               pr_warning("Error switching LCD\n");
-               return -ENODEV;
-       }
-
-       asus->lcd_state = lcd;
-       return 0;
-}
-
-static void lcd_blank(struct asus_laptop *asus, int blank)
-{
-       struct backlight_device *bd = asus->backlight_device;
-
-       asus->lcd_state = (blank == FB_BLANK_UNBLANK);
-
-       if (bd) {
-               bd->props.power = blank;
-               backlight_update_status(bd);
-       }
-}
-
 static int asus_read_brightness(struct backlight_device *bd)
 {
        struct asus_laptop *asus = bl_get_data(bd);
@@ -628,16 +549,9 @@ static int asus_set_brightness(struct backlight_device *bd, int value)
 
 static int update_bl_status(struct backlight_device *bd)
 {
-       struct asus_laptop *asus = bl_get_data(bd);
-       int rv;
        int value = bd->props.brightness;
 
-       rv = asus_set_brightness(bd, value);
-       if (rv)
-               return rv;
-
-       value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
-       return asus_lcd_set(asus, value);
+       return asus_set_brightness(bd, value);
 }
 
 static const struct backlight_ops asusbl_ops = {
@@ -661,8 +575,7 @@ static int asus_backlight_init(struct asus_laptop *asus)
        struct backlight_properties props;
 
        if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
-           acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
-           !lcd_switch_handle)
+           acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL))
                return 0;
 
        memset(&props, 0, sizeof(struct backlight_properties));
@@ -971,41 +884,6 @@ static void asus_set_display(struct asus_laptop *asus, int value)
        return;
 }
 
-static int read_display(struct asus_laptop *asus)
-{
-       unsigned long long value = 0;
-       acpi_status rv = AE_OK;
-
-       /*
-        * In most of the case, we know how to set the display, but sometime
-        * we can't read it
-        */
-       if (display_get_handle) {
-               rv = acpi_evaluate_integer(display_get_handle, NULL,
-                                          NULL, &value);
-               if (ACPI_FAILURE(rv))
-                       pr_warning("Error reading display status\n");
-       }
-
-       value &= 0x0F; /* needed for some models, shouldn't hurt others */
-
-       return value;
-}
-
-/*
- * Now, *this* one could be more user-friendly, but so far, no-one has
- * complained. The significance of bits is the same as in store_disp()
- */
-static ssize_t show_disp(struct device *dev,
-                        struct device_attribute *attr, char *buf)
-{
-       struct asus_laptop *asus = dev_get_drvdata(dev);
-
-       if (!display_get_handle)
-               return -ENODEV;
-       return sprintf(buf, "%d\n", read_display(asus));
-}
-
 /*
  * Experimental support for display switching. As of now: 1 should activate
  * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI.
@@ -1247,15 +1125,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
        struct asus_laptop *asus = acpi_driver_data(device);
        u16 count;
 
-       /*
-        * We need to tell the backlight device when the backlight power is
-        * switched
-        */
-       if (event == ATKD_LCD_ON)
-               lcd_blank(asus, FB_BLANK_UNBLANK);
-       else if (event == ATKD_LCD_OFF)
-               lcd_blank(asus, FB_BLANK_POWERDOWN);
-
        /* TODO Find a better way to handle events count. */
        count = asus->event_count[event % 128]++;
        acpi_bus_generate_proc_event(asus->device, event, count);
@@ -1282,7 +1151,7 @@ static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
                   show_bluetooth, store_bluetooth);
 static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
 static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
-static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
+static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
 static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
@@ -1393,26 +1262,6 @@ static struct platform_driver platform_driver = {
        }
 };
 
-static int asus_handle_init(char *name, acpi_handle * handle,
-                           char **paths, int num_paths)
-{
-       int i;
-       acpi_status status;
-
-       for (i = 0; i < num_paths; i++) {
-               status = acpi_get_handle(NULL, paths[i], handle);
-               if (ACPI_SUCCESS(status))
-                       return 0;
-       }
-
-       *handle = NULL;
-       return -ENODEV;
-}
-
-#define ASUS_HANDLE_INIT(object)                                       \
-       asus_handle_init(#object, &object##_handle, object##_paths,     \
-                        ARRAY_SIZE(object##_paths))
-
 /*
  * This function is used to initialize the context with right values. In this
  * method, we can make all the detection we want, and modify the asus_laptop
@@ -1498,10 +1347,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
        if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
                asus->have_rsts = true;
 
-       /* Scheduled for removal */
-       ASUS_HANDLE_INIT(lcd_switch);
-       ASUS_HANDLE_INIT(display_get);
-
        kfree(model);
 
        return AE_OK;
@@ -1553,10 +1398,23 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
                asus_als_level(asus, asus->light_level);
        }
 
-       asus->lcd_state = 1; /* LCD should be on when the module load */
        return result;
 }
 
+static void __devinit asus_dmi_check(void)
+{
+       const char *model;
+
+       model = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (!model)
+               return;
+
+       /* On L1400B WLED control the sound card, don't mess with it ... */
+       if (strncmp(model, "L1400B", 6) == 0) {
+               wlan_status = -1;
+       }
+}
+
 static bool asus_device_present;
 
 static int __devinit asus_acpi_add(struct acpi_device *device)
@@ -1575,6 +1433,8 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
        device->driver_data = asus;
        asus->device = device;
 
+       asus_dmi_check();
+
        result = asus_acpi_init(asus);
        if (result)
                goto fail_platform;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
new file mode 100644 (file)
index 0000000..0580d99
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Asus Notebooks WMI hotkey driver
+ *
+ * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+
+#include "asus-wmi.h"
+
+#define        ASUS_NB_WMI_FILE        "asus-nb-wmi"
+
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
+MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
+
+MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
+
+static const struct key_entry asus_nb_wmi_keymap[] = {
+       { KE_KEY, 0x30, { KEY_VOLUMEUP } },
+       { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x32, { KEY_MUTE } },
+       { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
+       { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
+       { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+       { KE_KEY, 0x41, { KEY_NEXTSONG } },
+       { KE_KEY, 0x43, { KEY_STOPCD } },
+       { KE_KEY, 0x45, { KEY_PLAYPAUSE } },
+       { KE_KEY, 0x4c, { KEY_MEDIA } },
+       { KE_KEY, 0x50, { KEY_EMAIL } },
+       { KE_KEY, 0x51, { KEY_WWW } },
+       { KE_KEY, 0x55, { KEY_CALC } },
+       { KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
+       { KE_KEY, 0x5D, { KEY_WLAN } },
+       { KE_KEY, 0x5E, { KEY_WLAN } },
+       { KE_KEY, 0x5F, { KEY_WLAN } },
+       { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
+       { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
+       { KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+       { KE_KEY, 0x82, { KEY_CAMERA } },
+       { KE_KEY, 0x88, { KEY_RFKILL  } },
+       { KE_KEY, 0x8A, { KEY_PROG1 } },
+       { KE_KEY, 0x95, { KEY_MEDIA } },
+       { KE_KEY, 0x99, { KEY_PHONE } },
+       { KE_KEY, 0xb5, { KEY_CALC } },
+       { KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
+       { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+       { KE_END, 0},
+};
+
+static struct asus_wmi_driver asus_nb_wmi_driver = {
+       .name = ASUS_NB_WMI_FILE,
+       .owner = THIS_MODULE,
+       .event_guid = ASUS_NB_WMI_EVENT_GUID,
+       .keymap = asus_nb_wmi_keymap,
+       .input_name = "Asus WMI hotkeys",
+       .input_phys = ASUS_NB_WMI_FILE "/input0",
+};
+
+
+static int __init asus_nb_wmi_init(void)
+{
+       return asus_wmi_register_driver(&asus_nb_wmi_driver);
+}
+
+static void __exit asus_nb_wmi_exit(void)
+{
+       asus_wmi_unregister_driver(&asus_nb_wmi_driver);
+}
+
+module_init(asus_nb_wmi_init);
+module_exit(asus_nb_wmi_exit);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
new file mode 100644 (file)
index 0000000..efc776c
--- /dev/null
@@ -0,0 +1,1656 @@
+/*
+ * Asus PC WMI hotkey driver
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ *  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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/rfkill.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#include "asus-wmi.h"
+
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
+             "Yong Wang <yong.y.wang@intel.com>");
+MODULE_DESCRIPTION("Asus Generic WMI Driver");
+MODULE_LICENSE("GPL");
+
+#define to_platform_driver(drv)                                        \
+       (container_of((drv), struct platform_driver, driver))
+
+#define to_asus_wmi_driver(pdrv)                                       \
+       (container_of((pdrv), struct asus_wmi_driver, platform_driver))
+
+#define ASUS_WMI_MGMT_GUID     "97845ED0-4E6D-11DE-8A39-0800200C9A66"
+
+#define NOTIFY_BRNUP_MIN               0x11
+#define NOTIFY_BRNUP_MAX               0x1f
+#define NOTIFY_BRNDOWN_MIN             0x20
+#define NOTIFY_BRNDOWN_MAX             0x2e
+
+/* WMI Methods */
+#define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
+#define ASUS_WMI_METHODID_SFBD         0x44424653 /* Set First Boot Device */
+#define ASUS_WMI_METHODID_GLCD         0x44434C47 /* Get LCD status */
+#define ASUS_WMI_METHODID_GPID         0x44495047 /* Get Panel ID?? (Resol) */
+#define ASUS_WMI_METHODID_QMOD         0x444F4D51 /* Quiet MODe */
+#define ASUS_WMI_METHODID_SPLV         0x4C425053 /* Set Panel Light Value */
+#define ASUS_WMI_METHODID_SFUN         0x4E554653 /* FUNCtionalities */
+#define ASUS_WMI_METHODID_SDSP         0x50534453 /* Set DiSPlay output */
+#define ASUS_WMI_METHODID_GDSP         0x50534447 /* Get DiSPlay output */
+#define ASUS_WMI_METHODID_DEVP         0x50564544 /* DEVice Policy */
+#define ASUS_WMI_METHODID_OSVR         0x5256534F /* OS VeRsion */
+#define ASUS_WMI_METHODID_DSTS         0x53544344 /* Device STatuS */
+#define ASUS_WMI_METHODID_DSTS2                0x53545344 /* Device STatuS #2*/
+#define ASUS_WMI_METHODID_BSTS         0x53545342 /* Bios STatuS ? */
+#define ASUS_WMI_METHODID_DEVS         0x53564544 /* DEVice Set */
+#define ASUS_WMI_METHODID_CFVS         0x53564643 /* CPU Frequency Volt Set */
+#define ASUS_WMI_METHODID_KBFT         0x5446424B /* KeyBoard FilTer */
+#define ASUS_WMI_METHODID_INIT         0x54494E49 /* INITialize */
+#define ASUS_WMI_METHODID_HKEY         0x59454B48 /* Hot KEY ?? */
+
+#define ASUS_WMI_UNSUPPORTED_METHOD    0xFFFFFFFE
+
+/* Wireless */
+#define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
+#define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
+#define ASUS_WMI_DEVID_WLAN            0x00010011
+#define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
+#define ASUS_WMI_DEVID_GPS             0x00010015
+#define ASUS_WMI_DEVID_WIMAX           0x00010017
+#define ASUS_WMI_DEVID_WWAN3G          0x00010019
+#define ASUS_WMI_DEVID_UWB             0x00010021
+
+/* Leds */
+/* 0x000200XX and 0x000400XX */
+
+/* Backlight and Brightness */
+#define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
+#define ASUS_WMI_DEVID_BRIGHTNESS      0x00050012
+#define ASUS_WMI_DEVID_KBD_BACKLIGHT   0x00050021
+#define ASUS_WMI_DEVID_LIGHT_SENSOR    0x00050022 /* ?? */
+
+/* Misc */
+#define ASUS_WMI_DEVID_CAMERA          0x00060013
+
+/* Storage */
+#define ASUS_WMI_DEVID_CARDREADER      0x00080013
+
+/* Input */
+#define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
+#define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
+
+/* Fan, Thermal */
+#define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
+#define ASUS_WMI_DEVID_FAN_CTRL                0x00110012
+
+/* Power */
+#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
+
+/* DSTS masks */
+#define ASUS_WMI_DSTS_STATUS_BIT       0x00000001
+#define ASUS_WMI_DSTS_UNKNOWN_BIT      0x00000002
+#define ASUS_WMI_DSTS_PRESENCE_BIT     0x00010000
+#define ASUS_WMI_DSTS_USER_BIT         0x00020000
+#define ASUS_WMI_DSTS_BIOS_BIT         0x00040000
+#define ASUS_WMI_DSTS_BRIGHTNESS_MASK  0x000000FF
+#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK  0x0000FF00
+
+struct bios_args {
+       u32 arg0;
+       u32 arg1;
+} __packed;
+
+/*
+ * <platform>/    - debugfs root directory
+ *   dev_id      - current dev_id
+ *   ctrl_param  - current ctrl_param
+ *   method_id   - current method_id
+ *   devs        - call DEVS(dev_id, ctrl_param) and print result
+ *   dsts        - call DSTS(dev_id)  and print result
+ *   call        - call method_id(dev_id, ctrl_param) and print result
+ */
+struct asus_wmi_debug {
+       struct dentry *root;
+       u32 method_id;
+       u32 dev_id;
+       u32 ctrl_param;
+};
+
+struct asus_rfkill {
+       struct asus_wmi *asus;
+       struct rfkill *rfkill;
+       u32 dev_id;
+};
+
+struct asus_wmi {
+       int dsts_id;
+       int spec;
+       int sfun;
+
+       struct input_dev *inputdev;
+       struct backlight_device *backlight_device;
+       struct device *hwmon_device;
+       struct platform_device *platform_device;
+
+       struct led_classdev tpd_led;
+       int tpd_led_wk;
+       struct workqueue_struct *led_workqueue;
+       struct work_struct tpd_led_work;
+
+       struct asus_rfkill wlan;
+       struct asus_rfkill bluetooth;
+       struct asus_rfkill wimax;
+       struct asus_rfkill wwan3g;
+
+       struct hotplug_slot *hotplug_slot;
+       struct mutex hotplug_lock;
+       struct mutex wmi_lock;
+       struct workqueue_struct *hotplug_workqueue;
+       struct work_struct hotplug_work;
+
+       struct asus_wmi_debug debug;
+
+       struct asus_wmi_driver *driver;
+};
+
+static int asus_wmi_input_init(struct asus_wmi *asus)
+{
+       int err;
+
+       asus->inputdev = input_allocate_device();
+       if (!asus->inputdev)
+               return -ENOMEM;
+
+       asus->inputdev->name = asus->driver->input_phys;
+       asus->inputdev->phys = asus->driver->input_name;
+       asus->inputdev->id.bustype = BUS_HOST;
+       asus->inputdev->dev.parent = &asus->platform_device->dev;
+
+       err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
+       if (err)
+               goto err_free_dev;
+
+       err = input_register_device(asus->inputdev);
+       if (err)
+               goto err_free_keymap;
+
+       return 0;
+
+err_free_keymap:
+       sparse_keymap_free(asus->inputdev);
+err_free_dev:
+       input_free_device(asus->inputdev);
+       return err;
+}
+
+static void asus_wmi_input_exit(struct asus_wmi *asus)
+{
+       if (asus->inputdev) {
+               sparse_keymap_free(asus->inputdev);
+               input_unregister_device(asus->inputdev);
+       }
+
+       asus->inputdev = NULL;
+}
+
+static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+                                   u32 *retval)
+{
+       struct bios_args args = {
+               .arg0 = arg0,
+               .arg1 = arg1,
+       };
+       struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       acpi_status status;
+       union acpi_object *obj;
+       u32 tmp;
+
+       status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
+                                    &input, &output);
+
+       if (ACPI_FAILURE(status))
+               goto exit;
+
+       obj = (union acpi_object *)output.pointer;
+       if (obj && obj->type == ACPI_TYPE_INTEGER)
+               tmp = (u32) obj->integer.value;
+       else
+               tmp = 0;
+
+       if (retval)
+               *retval = tmp;
+
+       kfree(obj);
+
+exit:
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
+{
+       return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
+}
+
+static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
+                                u32 *retval)
+{
+       return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
+                                       ctrl_param, retval);
+}
+
+/* Helper for special devices with magic return codes */
+static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
+                                     u32 dev_id, u32 mask)
+{
+       u32 retval = 0;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, dev_id, &retval);
+
+       if (err < 0)
+               return err;
+
+       if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
+               return -ENODEV;
+
+       if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
+               if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
+                       return -ENODEV;
+       }
+
+       return retval & mask;
+}
+
+static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
+{
+       return asus_wmi_get_devstate_bits(asus, dev_id,
+                                         ASUS_WMI_DSTS_STATUS_BIT);
+}
+
+/*
+ * LEDs
+ */
+/*
+ * These functions actually update the LED's, and are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
+static void tpd_led_update(struct work_struct *work)
+{
+       int ctrl_param;
+       struct asus_wmi *asus;
+
+       asus = container_of(work, struct asus_wmi, tpd_led_work);
+
+       ctrl_param = asus->tpd_led_wk;
+       asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
+}
+
+static void tpd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(led_cdev, struct asus_wmi, tpd_led);
+
+       asus->tpd_led_wk = !!value;
+       queue_work(asus->led_workqueue, &asus->tpd_led_work);
+}
+
+static int read_tpd_led_state(struct asus_wmi *asus)
+{
+       return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
+}
+
+static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(led_cdev, struct asus_wmi, tpd_led);
+
+       return read_tpd_led_state(asus);
+}
+
+static int asus_wmi_led_init(struct asus_wmi *asus)
+{
+       int rv;
+
+       if (read_tpd_led_state(asus) < 0)
+               return 0;
+
+       asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!asus->led_workqueue)
+               return -ENOMEM;
+       INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+
+       asus->tpd_led.name = "asus::touchpad";
+       asus->tpd_led.brightness_set = tpd_led_set;
+       asus->tpd_led.brightness_get = tpd_led_get;
+       asus->tpd_led.max_brightness = 1;
+
+       rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
+       if (rv) {
+               destroy_workqueue(asus->led_workqueue);
+               return rv;
+       }
+
+       return 0;
+}
+
+static void asus_wmi_led_exit(struct asus_wmi *asus)
+{
+       if (asus->tpd_led.dev)
+               led_classdev_unregister(&asus->tpd_led);
+       if (asus->led_workqueue)
+               destroy_workqueue(asus->led_workqueue);
+}
+
+/*
+ * PCI hotplug (for wlan rfkill)
+ */
+static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
+{
+       int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+
+       if (result < 0)
+               return false;
+       return !result;
+}
+
+static void asus_rfkill_hotplug(struct asus_wmi *asus)
+{
+       struct pci_dev *dev;
+       struct pci_bus *bus;
+       bool blocked;
+       bool absent;
+       u32 l;
+
+       mutex_lock(&asus->wmi_lock);
+       blocked = asus_wlan_rfkill_blocked(asus);
+       mutex_unlock(&asus->wmi_lock);
+
+       mutex_lock(&asus->hotplug_lock);
+
+       if (asus->wlan.rfkill)
+               rfkill_set_sw_state(asus->wlan.rfkill, blocked);
+
+       if (asus->hotplug_slot) {
+               bus = pci_find_bus(0, 1);
+               if (!bus) {
+                       pr_warning("Unable to find PCI bus 1?\n");
+                       goto out_unlock;
+               }
+
+               if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
+                       pr_err("Unable to read PCI config space?\n");
+                       goto out_unlock;
+               }
+               absent = (l == 0xffffffff);
+
+               if (blocked != absent) {
+                       pr_warning("BIOS says wireless lan is %s, "
+                                  "but the pci device is %s\n",
+                                  blocked ? "blocked" : "unblocked",
+                                  absent ? "absent" : "present");
+                       pr_warning("skipped wireless hotplug as probably "
+                                  "inappropriate for this model\n");
+                       goto out_unlock;
+               }
+
+               if (!blocked) {
+                       dev = pci_get_slot(bus, 0);
+                       if (dev) {
+                               /* Device already present */
+                               pci_dev_put(dev);
+                               goto out_unlock;
+                       }
+                       dev = pci_scan_single_device(bus, 0);
+                       if (dev) {
+                               pci_bus_assign_resources(bus);
+                               if (pci_bus_add_device(dev))
+                                       pr_err("Unable to hotplug wifi\n");
+                       }
+               } else {
+                       dev = pci_get_slot(bus, 0);
+                       if (dev) {
+                               pci_remove_bus_device(dev);
+                               pci_dev_put(dev);
+                       }
+               }
+       }
+
+out_unlock:
+       mutex_unlock(&asus->hotplug_lock);
+}
+
+static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
+{
+       struct asus_wmi *asus = data;
+
+       if (event != ACPI_NOTIFY_BUS_CHECK)
+               return;
+
+       /*
+        * We can't call directly asus_rfkill_hotplug because most
+        * of the time WMBC is still being executed and not reetrant.
+        * There is currently no way to tell ACPICA that  we want this
+        * method to be serialized, we schedule a asus_rfkill_hotplug
+        * call later, in a safer context.
+        */
+       queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
+}
+
+static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
+{
+       acpi_status status;
+       acpi_handle handle;
+
+       status = acpi_get_handle(NULL, node, &handle);
+
+       if (ACPI_SUCCESS(status)) {
+               status = acpi_install_notify_handler(handle,
+                                                    ACPI_SYSTEM_NOTIFY,
+                                                    asus_rfkill_notify, asus);
+               if (ACPI_FAILURE(status))
+                       pr_warning("Failed to register notify on %s\n", node);
+       } else
+               return -ENODEV;
+
+       return 0;
+}
+
+static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
+{
+       acpi_status status = AE_OK;
+       acpi_handle handle;
+
+       status = acpi_get_handle(NULL, node, &handle);
+
+       if (ACPI_SUCCESS(status)) {
+               status = acpi_remove_notify_handler(handle,
+                                                   ACPI_SYSTEM_NOTIFY,
+                                                   asus_rfkill_notify);
+               if (ACPI_FAILURE(status))
+                       pr_err("Error removing rfkill notify handler %s\n",
+                              node);
+       }
+}
+
+static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
+                                  u8 *value)
+{
+       struct asus_wmi *asus = hotplug_slot->private;
+       int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+
+       if (result < 0)
+               return result;
+
+       *value = !!result;
+       return 0;
+}
+
+static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+       kfree(hotplug_slot->info);
+       kfree(hotplug_slot);
+}
+
+static struct hotplug_slot_ops asus_hotplug_slot_ops = {
+       .owner = THIS_MODULE,
+       .get_adapter_status = asus_get_adapter_status,
+       .get_power_status = asus_get_adapter_status,
+};
+
+static void asus_hotplug_work(struct work_struct *work)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(work, struct asus_wmi, hotplug_work);
+       asus_rfkill_hotplug(asus);
+}
+
+static int asus_setup_pci_hotplug(struct asus_wmi *asus)
+{
+       int ret = -ENOMEM;
+       struct pci_bus *bus = pci_find_bus(0, 1);
+
+       if (!bus) {
+               pr_err("Unable to find wifi PCI bus\n");
+               return -ENODEV;
+       }
+
+       asus->hotplug_workqueue =
+           create_singlethread_workqueue("hotplug_workqueue");
+       if (!asus->hotplug_workqueue)
+               goto error_workqueue;
+
+       INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
+
+       asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+       if (!asus->hotplug_slot)
+               goto error_slot;
+
+       asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+                                          GFP_KERNEL);
+       if (!asus->hotplug_slot->info)
+               goto error_info;
+
+       asus->hotplug_slot->private = asus;
+       asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
+       asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
+       asus_get_adapter_status(asus->hotplug_slot,
+                               &asus->hotplug_slot->info->adapter_status);
+
+       ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
+       if (ret) {
+               pr_err("Unable to register hotplug slot - %d\n", ret);
+               goto error_register;
+       }
+
+       return 0;
+
+error_register:
+       kfree(asus->hotplug_slot->info);
+error_info:
+       kfree(asus->hotplug_slot);
+       asus->hotplug_slot = NULL;
+error_slot:
+       destroy_workqueue(asus->hotplug_workqueue);
+error_workqueue:
+       return ret;
+}
+
+/*
+ * Rfkill devices
+ */
+static int asus_rfkill_set(void *data, bool blocked)
+{
+       struct asus_rfkill *priv = data;
+       u32 ctrl_param = !blocked;
+
+       return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
+}
+
+static void asus_rfkill_query(struct rfkill *rfkill, void *data)
+{
+       struct asus_rfkill *priv = data;
+       int result;
+
+       result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
+
+       if (result < 0)
+               return;
+
+       rfkill_set_sw_state(priv->rfkill, !result);
+}
+
+static int asus_rfkill_wlan_set(void *data, bool blocked)
+{
+       struct asus_rfkill *priv = data;
+       struct asus_wmi *asus = priv->asus;
+       int ret;
+
+       /*
+        * This handler is enabled only if hotplug is enabled.
+        * In this case, the asus_wmi_set_devstate() will
+        * trigger a wmi notification and we need to wait
+        * this call to finish before being able to call
+        * any wmi method
+        */
+       mutex_lock(&asus->wmi_lock);
+       ret = asus_rfkill_set(data, blocked);
+       mutex_unlock(&asus->wmi_lock);
+       return ret;
+}
+
+static const struct rfkill_ops asus_rfkill_wlan_ops = {
+       .set_block = asus_rfkill_wlan_set,
+       .query = asus_rfkill_query,
+};
+
+static const struct rfkill_ops asus_rfkill_ops = {
+       .set_block = asus_rfkill_set,
+       .query = asus_rfkill_query,
+};
+
+static int asus_new_rfkill(struct asus_wmi *asus,
+                          struct asus_rfkill *arfkill,
+                          const char *name, enum rfkill_type type, int dev_id)
+{
+       int result = asus_wmi_get_devstate_simple(asus, dev_id);
+       struct rfkill **rfkill = &arfkill->rfkill;
+
+       if (result < 0)
+               return result;
+
+       arfkill->dev_id = dev_id;
+       arfkill->asus = asus;
+
+       if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
+               *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
+                                      &asus_rfkill_wlan_ops, arfkill);
+       else
+               *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
+                                      &asus_rfkill_ops, arfkill);
+
+       if (!*rfkill)
+               return -EINVAL;
+
+       rfkill_init_sw_state(*rfkill, !result);
+       result = rfkill_register(*rfkill);
+       if (result) {
+               rfkill_destroy(*rfkill);
+               *rfkill = NULL;
+               return result;
+       }
+       return 0;
+}
+
+static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
+{
+       asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
+       asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
+       asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
+       if (asus->wlan.rfkill) {
+               rfkill_unregister(asus->wlan.rfkill);
+               rfkill_destroy(asus->wlan.rfkill);
+               asus->wlan.rfkill = NULL;
+       }
+       /*
+        * Refresh pci hotplug in case the rfkill state was changed after
+        * asus_unregister_rfkill_notifier()
+        */
+       asus_rfkill_hotplug(asus);
+       if (asus->hotplug_slot)
+               pci_hp_deregister(asus->hotplug_slot);
+       if (asus->hotplug_workqueue)
+               destroy_workqueue(asus->hotplug_workqueue);
+
+       if (asus->bluetooth.rfkill) {
+               rfkill_unregister(asus->bluetooth.rfkill);
+               rfkill_destroy(asus->bluetooth.rfkill);
+               asus->bluetooth.rfkill = NULL;
+       }
+       if (asus->wimax.rfkill) {
+               rfkill_unregister(asus->wimax.rfkill);
+               rfkill_destroy(asus->wimax.rfkill);
+               asus->wimax.rfkill = NULL;
+       }
+       if (asus->wwan3g.rfkill) {
+               rfkill_unregister(asus->wwan3g.rfkill);
+               rfkill_destroy(asus->wwan3g.rfkill);
+               asus->wwan3g.rfkill = NULL;
+       }
+}
+
+static int asus_wmi_rfkill_init(struct asus_wmi *asus)
+{
+       int result = 0;
+
+       mutex_init(&asus->hotplug_lock);
+       mutex_init(&asus->wmi_lock);
+
+       result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
+                                RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = asus_new_rfkill(asus, &asus->bluetooth,
+                                "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
+                                ASUS_WMI_DEVID_BLUETOOTH);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
+                                RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
+                                RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       if (!asus->driver->hotplug_wireless)
+               goto exit;
+
+       result = asus_setup_pci_hotplug(asus);
+       /*
+        * If we get -EBUSY then something else is handling the PCI hotplug -
+        * don't fail in this case
+        */
+       if (result == -EBUSY)
+               result = 0;
+
+       asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
+       asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
+       asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
+       /*
+        * Refresh pci hotplug in case the rfkill state was changed during
+        * setup.
+        */
+       asus_rfkill_hotplug(asus);
+
+exit:
+       if (result && result != -ENODEV)
+               asus_wmi_rfkill_exit(asus);
+
+       if (result == -ENODEV)
+               result = 0;
+
+       return result;
+}
+
+/*
+ * Hwmon device
+ */
+static ssize_t asus_hwmon_pwm1(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+       struct asus_wmi *asus = dev_get_drvdata(dev);
+       u32 value;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
+
+       if (err < 0)
+               return err;
+
+       value |= 0xFF;
+
+       if (value == 1) /* Low Speed */
+               value = 85;
+       else if (value == 2)
+               value = 170;
+       else if (value == 3)
+               value = 255;
+       else if (value != 0) {
+               pr_err("Unknown fan speed %#x", value);
+               value = -1;
+       }
+
+       return sprintf(buf, "%d\n", value);
+}
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "asus\n");
+}
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
+static struct attribute *hwmon_attributes[] = {
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_name.dev_attr.attr,
+       NULL
+};
+
+static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
+                                   struct attribute *attr, int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev->parent);
+       struct asus_wmi *asus = platform_get_drvdata(pdev);
+       bool ok = true;
+       int dev_id = -1;
+       u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
+
+       if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
+               dev_id = ASUS_WMI_DEVID_FAN_CTRL;
+
+       if (dev_id != -1) {
+               int err = asus_wmi_get_devstate(asus, dev_id, &value);
+
+               if (err < 0)
+                       return err;
+       }
+
+       if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
+               /*
+                * We need to find a better way, probably using sfun,
+                * bits or spec ...
+                * Currently we disable it if:
+                * - ASUS_WMI_UNSUPPORTED_METHOD is returned
+                * - reverved bits are non-zero
+                * - sfun and presence bit are not set
+                */
+               if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
+                   || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
+                       ok = false;
+       }
+
+       return ok ? attr->mode : 0;
+}
+
+static struct attribute_group hwmon_attribute_group = {
+       .is_visible = asus_hwmon_sysfs_is_visible,
+       .attrs = hwmon_attributes
+};
+
+static void asus_wmi_hwmon_exit(struct asus_wmi *asus)
+{
+       struct device *hwmon;
+
+       hwmon = asus->hwmon_device;
+       if (!hwmon)
+               return;
+       sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group);
+       hwmon_device_unregister(hwmon);
+       asus->hwmon_device = NULL;
+}
+
+static int asus_wmi_hwmon_init(struct asus_wmi *asus)
+{
+       struct device *hwmon;
+       int result;
+
+       hwmon = hwmon_device_register(&asus->platform_device->dev);
+       if (IS_ERR(hwmon)) {
+               pr_err("Could not register asus hwmon device\n");
+               return PTR_ERR(hwmon);
+       }
+       asus->hwmon_device = hwmon;
+       result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
+       if (result)
+               asus_wmi_hwmon_exit(asus);
+       return result;
+}
+
+/*
+ * Backlight
+ */
+static int read_backlight_power(struct asus_wmi *asus)
+{
+       int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
+
+       if (ret < 0)
+               return ret;
+
+       return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static int read_brightness_max(struct asus_wmi *asus)
+{
+       u32 retval;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
+
+       if (err < 0)
+               return err;
+
+       retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
+       retval >>= 8;
+
+       if (!retval)
+               return -ENODEV;
+
+       return retval;
+}
+
+static int read_brightness(struct backlight_device *bd)
+{
+       struct asus_wmi *asus = bl_get_data(bd);
+       u32 retval;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
+
+       if (err < 0)
+               return err;
+
+       return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+       struct asus_wmi *asus = bl_get_data(bd);
+       u32 ctrl_param;
+       int power, err;
+
+       ctrl_param = bd->props.brightness;
+
+       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
+                                   ctrl_param, NULL);
+
+       if (err < 0)
+               return err;
+
+       power = read_backlight_power(asus);
+       if (power != -ENODEV && bd->props.power != power) {
+               ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
+               err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
+                                           ctrl_param, NULL);
+       }
+       return err;
+}
+
+static const struct backlight_ops asus_wmi_bl_ops = {
+       .get_brightness = read_brightness,
+       .update_status = update_bl_status,
+};
+
+static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
+{
+       struct backlight_device *bd = asus->backlight_device;
+       int old = bd->props.brightness;
+       int new = old;
+
+       if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
+               new = code - NOTIFY_BRNUP_MIN + 1;
+       else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
+               new = code - NOTIFY_BRNDOWN_MIN;
+
+       bd->props.brightness = new;
+       backlight_update_status(bd);
+       backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
+
+       return old;
+}
+
+static int asus_wmi_backlight_init(struct asus_wmi *asus)
+{
+       struct backlight_device *bd;
+       struct backlight_properties props;
+       int max;
+       int power;
+
+       max = read_brightness_max(asus);
+
+       if (max == -ENODEV)
+               max = 0;
+       else if (max < 0)
+               return max;
+
+       power = read_backlight_power(asus);
+
+       if (power == -ENODEV)
+               power = FB_BLANK_UNBLANK;
+       else if (power < 0)
+               return power;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = max;
+       bd = backlight_device_register(asus->driver->name,
+                                      &asus->platform_device->dev, asus,
+                                      &asus_wmi_bl_ops, &props);
+       if (IS_ERR(bd)) {
+               pr_err("Could not register backlight device\n");
+               return PTR_ERR(bd);
+       }
+
+       asus->backlight_device = bd;
+
+       bd->props.brightness = read_brightness(bd);
+       bd->props.power = power;
+       backlight_update_status(bd);
+
+       return 0;
+}
+
+static void asus_wmi_backlight_exit(struct asus_wmi *asus)
+{
+       if (asus->backlight_device)
+               backlight_device_unregister(asus->backlight_device);
+
+       asus->backlight_device = NULL;
+}
+
+static void asus_wmi_notify(u32 value, void *context)
+{
+       struct asus_wmi *asus = context;
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       int code;
+       int orig_code;
+
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               pr_err("bad event status 0x%x\n", status);
+               return;
+       }
+
+       obj = (union acpi_object *)response.pointer;
+
+       if (!obj || obj->type != ACPI_TYPE_INTEGER)
+               goto exit;
+
+       code = obj->integer.value;
+       orig_code = code;
+
+       if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
+               code = NOTIFY_BRNUP_MIN;
+       else if (code >= NOTIFY_BRNDOWN_MIN &&
+                code <= NOTIFY_BRNDOWN_MAX)
+               code = NOTIFY_BRNDOWN_MIN;
+
+       if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
+               if (!acpi_video_backlight_support())
+                       asus_wmi_backlight_notify(asus, orig_code);
+       } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
+               pr_info("Unknown key %x pressed\n", code);
+
+exit:
+       kfree(obj);
+}
+
+/*
+ * Sys helpers
+ */
+static int parse_arg(const char *buf, unsigned long count, int *val)
+{
+       if (!count)
+               return 0;
+       if (sscanf(buf, "%i", val) != 1)
+               return -EINVAL;
+       return count;
+}
+
+static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
+                            const char *buf, size_t count)
+{
+       u32 retval;
+       int rv, err, value;
+
+       value = asus_wmi_get_devstate_simple(asus, devid);
+       if (value == -ENODEV)   /* Check device presence */
+               return value;
+
+       rv = parse_arg(buf, count, &value);
+       err = asus_wmi_set_devstate(devid, value, &retval);
+
+       if (err < 0)
+               return err;
+
+       return rv;
+}
+
+static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
+{
+       int value = asus_wmi_get_devstate_simple(asus, devid);
+
+       if (value < 0)
+               return value;
+
+       return sprintf(buf, "%d\n", value);
+}
+
+#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)                 \
+       static ssize_t show_##_name(struct device *dev,                 \
+                                   struct device_attribute *attr,      \
+                                   char *buf)                          \
+       {                                                               \
+               struct asus_wmi *asus = dev_get_drvdata(dev);           \
+                                                                       \
+               return show_sys_wmi(asus, _cm, buf);                    \
+       }                                                               \
+       static ssize_t store_##_name(struct device *dev,                \
+                                    struct device_attribute *attr,     \
+                                    const char *buf, size_t count)     \
+       {                                                               \
+               struct asus_wmi *asus = dev_get_drvdata(dev);           \
+                                                                       \
+               return store_sys_wmi(asus, _cm, buf, count);            \
+       }                                                               \
+       static struct device_attribute dev_attr_##_name = {             \
+               .attr = {                                               \
+                       .name = __stringify(_name),                     \
+                       .mode = _mode },                                \
+               .show   = show_##_name,                                 \
+               .store  = store_##_name,                                \
+       }
+
+ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
+ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
+ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
+
+static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       int value;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+       if (value < 0 || value > 2)
+               return -EINVAL;
+
+       return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+}
+
+static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
+
+static struct attribute *platform_attributes[] = {
+       &dev_attr_cpufv.attr,
+       &dev_attr_camera.attr,
+       &dev_attr_cardr.attr,
+       &dev_attr_touchpad.attr,
+       NULL
+};
+
+static mode_t asus_sysfs_is_visible(struct kobject *kobj,
+                                   struct attribute *attr, int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct asus_wmi *asus = platform_get_drvdata(pdev);
+       bool ok = true;
+       int devid = -1;
+
+       if (attr == &dev_attr_camera.attr)
+               devid = ASUS_WMI_DEVID_CAMERA;
+       else if (attr == &dev_attr_cardr.attr)
+               devid = ASUS_WMI_DEVID_CARDREADER;
+       else if (attr == &dev_attr_touchpad.attr)
+               devid = ASUS_WMI_DEVID_TOUCHPAD;
+
+       if (devid != -1)
+               ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
+
+       return ok ? attr->mode : 0;
+}
+
+static struct attribute_group platform_attribute_group = {
+       .is_visible = asus_sysfs_is_visible,
+       .attrs = platform_attributes
+};
+
+static void asus_wmi_sysfs_exit(struct platform_device *device)
+{
+       sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+static int asus_wmi_sysfs_init(struct platform_device *device)
+{
+       return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+/*
+ * Platform device
+ */
+static int __init asus_wmi_platform_init(struct asus_wmi *asus)
+{
+       int rv;
+
+       /* INIT enable hotkeys on some models */
+       if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
+               pr_info("Initialization: %#x", rv);
+
+       /* We don't know yet what to do with this version... */
+       if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
+               pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
+               asus->spec = rv;
+       }
+
+       /*
+        * The SFUN method probably allows the original driver to get the list
+        * of features supported by a given model. For now, 0x0100 or 0x0800
+        * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
+        * The significance of others is yet to be found.
+        */
+       if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
+               pr_info("SFUN value: %#x", rv);
+               asus->sfun = rv;
+       }
+
+       /*
+        * Eee PC and Notebooks seems to have different method_id for DSTS,
+        * but it may also be related to the BIOS's SPEC.
+        * Note, on most Eeepc, there is no way to check if a method exist
+        * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
+        * but once again, SPEC may probably be used for that kind of things.
+        */
+       if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
+               asus->dsts_id = ASUS_WMI_METHODID_DSTS;
+       else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
+               asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
+
+       if (!asus->dsts_id) {
+               pr_err("Can't find DSTS");
+               return -ENODEV;
+       }
+
+       return asus_wmi_sysfs_init(asus->platform_device);
+}
+
+static void asus_wmi_platform_exit(struct asus_wmi *asus)
+{
+       asus_wmi_sysfs_exit(asus->platform_device);
+}
+
+/*
+ * debugfs
+ */
+struct asus_wmi_debugfs_node {
+       struct asus_wmi *asus;
+       char *name;
+       int (*show) (struct seq_file *m, void *data);
+};
+
+static int show_dsts(struct seq_file *m, void *data)
+{
+       struct asus_wmi *asus = m->private;
+       int err;
+       u32 retval = -1;
+
+       err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
+
+       if (err < 0)
+               return err;
+
+       seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
+
+       return 0;
+}
+
+static int show_devs(struct seq_file *m, void *data)
+{
+       struct asus_wmi *asus = m->private;
+       int err;
+       u32 retval = -1;
+
+       err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
+                                   &retval);
+
+       if (err < 0)
+               return err;
+
+       seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
+                  asus->debug.ctrl_param, retval);
+
+       return 0;
+}
+
+static int show_call(struct seq_file *m, void *data)
+{
+       struct asus_wmi *asus = m->private;
+       struct bios_args args = {
+               .arg0 = asus->debug.dev_id,
+               .arg1 = asus->debug.ctrl_param,
+       };
+       struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+
+       status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
+                                    1, asus->debug.method_id,
+                                    &input, &output);
+
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       obj = (union acpi_object *)output.pointer;
+       if (obj && obj->type == ACPI_TYPE_INTEGER)
+               seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
+                          asus->debug.dev_id, asus->debug.ctrl_param,
+                          (u32) obj->integer.value);
+       else
+               seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
+                          asus->debug.dev_id, asus->debug.ctrl_param,
+                          obj ? obj->type : -1);
+
+       kfree(obj);
+
+       return 0;
+}
+
+static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
+       {NULL, "devs", show_devs},
+       {NULL, "dsts", show_dsts},
+       {NULL, "call", show_call},
+};
+
+static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
+{
+       struct asus_wmi_debugfs_node *node = inode->i_private;
+
+       return single_open(file, node->show, node->asus);
+}
+
+static const struct file_operations asus_wmi_debugfs_io_ops = {
+       .owner = THIS_MODULE,
+       .open = asus_wmi_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
+{
+       debugfs_remove_recursive(asus->debug.root);
+}
+
+static int asus_wmi_debugfs_init(struct asus_wmi *asus)
+{
+       struct dentry *dent;
+       int i;
+
+       asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
+       if (!asus->debug.root) {
+               pr_err("failed to create debugfs directory");
+               goto error_debugfs;
+       }
+
+       dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
+                                 asus->debug.root, &asus->debug.method_id);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
+                                 asus->debug.root, &asus->debug.dev_id);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
+                                 asus->debug.root, &asus->debug.ctrl_param);
+       if (!dent)
+               goto error_debugfs;
+
+       for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
+               struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
+
+               node->asus = asus;
+               dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
+                                          asus->debug.root, node,
+                                          &asus_wmi_debugfs_io_ops);
+               if (!dent) {
+                       pr_err("failed to create debug file: %s\n", node->name);
+                       goto error_debugfs;
+               }
+       }
+
+       return 0;
+
+error_debugfs:
+       asus_wmi_debugfs_exit(asus);
+       return -ENOMEM;
+}
+
+/*
+ * WMI Driver
+ */
+static int asus_wmi_add(struct platform_device *pdev)
+{
+       struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
+       struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
+       struct asus_wmi *asus;
+       acpi_status status;
+       int err;
+
+       asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
+       if (!asus)
+               return -ENOMEM;
+
+       asus->driver = wdrv;
+       asus->platform_device = pdev;
+       wdrv->platform_device = pdev;
+       platform_set_drvdata(asus->platform_device, asus);
+
+       if (wdrv->quirks)
+               wdrv->quirks(asus->driver);
+
+       err = asus_wmi_platform_init(asus);
+       if (err)
+               goto fail_platform;
+
+       err = asus_wmi_input_init(asus);
+       if (err)
+               goto fail_input;
+
+       err = asus_wmi_hwmon_init(asus);
+       if (err)
+               goto fail_hwmon;
+
+       err = asus_wmi_led_init(asus);
+       if (err)
+               goto fail_leds;
+
+       err = asus_wmi_rfkill_init(asus);
+       if (err)
+               goto fail_rfkill;
+
+       if (!acpi_video_backlight_support()) {
+               err = asus_wmi_backlight_init(asus);
+               if (err && err != -ENODEV)
+                       goto fail_backlight;
+       } else
+               pr_info("Backlight controlled by ACPI video driver\n");
+
+       status = wmi_install_notify_handler(asus->driver->event_guid,
+                                           asus_wmi_notify, asus);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Unable to register notify handler - %d\n", status);
+               err = -ENODEV;
+               goto fail_wmi_handler;
+       }
+
+       err = asus_wmi_debugfs_init(asus);
+       if (err)
+               goto fail_debugfs;
+
+       return 0;
+
+fail_debugfs:
+       wmi_remove_notify_handler(asus->driver->event_guid);
+fail_wmi_handler:
+       asus_wmi_backlight_exit(asus);
+fail_backlight:
+       asus_wmi_rfkill_exit(asus);
+fail_rfkill:
+       asus_wmi_led_exit(asus);
+fail_leds:
+       asus_wmi_hwmon_exit(asus);
+fail_hwmon:
+       asus_wmi_input_exit(asus);
+fail_input:
+       asus_wmi_platform_exit(asus);
+fail_platform:
+       kfree(asus);
+       return err;
+}
+
+static int asus_wmi_remove(struct platform_device *device)
+{
+       struct asus_wmi *asus;
+
+       asus = platform_get_drvdata(device);
+       wmi_remove_notify_handler(asus->driver->event_guid);
+       asus_wmi_backlight_exit(asus);
+       asus_wmi_input_exit(asus);
+       asus_wmi_hwmon_exit(asus);
+       asus_wmi_led_exit(asus);
+       asus_wmi_rfkill_exit(asus);
+       asus_wmi_debugfs_exit(asus);
+       asus_wmi_platform_exit(asus);
+
+       kfree(asus);
+       return 0;
+}
+
+/*
+ * Platform driver - hibernate/resume callbacks
+ */
+static int asus_hotk_thaw(struct device *device)
+{
+       struct asus_wmi *asus = dev_get_drvdata(device);
+
+       if (asus->wlan.rfkill) {
+               bool wlan;
+
+               /*
+                * Work around bios bug - acpi _PTS turns off the wireless led
+                * during suspend.  Normally it restores it on resume, but
+                * we should kick it ourselves in case hibernation is aborted.
+                */
+               wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+               asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
+       }
+
+       return 0;
+}
+
+static int asus_hotk_restore(struct device *device)
+{
+       struct asus_wmi *asus = dev_get_drvdata(device);
+       int bl;
+
+       /* Refresh both wlan rfkill state and pci hotplug */
+       if (asus->wlan.rfkill)
+               asus_rfkill_hotplug(asus);
+
+       if (asus->bluetooth.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus,
+                                                  ASUS_WMI_DEVID_BLUETOOTH);
+               rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
+       }
+       if (asus->wimax.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
+               rfkill_set_sw_state(asus->wimax.rfkill, bl);
+       }
+       if (asus->wwan3g.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
+               rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
+       }
+
+       return 0;
+}
+
+static const struct dev_pm_ops asus_pm_ops = {
+       .thaw = asus_hotk_thaw,
+       .restore = asus_hotk_restore,
+};
+
+static int asus_wmi_probe(struct platform_device *pdev)
+{
+       struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
+       struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
+       int ret;
+
+       if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
+               pr_warning("Management GUID not found\n");
+               return -ENODEV;
+       }
+
+       if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
+               pr_warning("Event GUID not found\n");
+               return -ENODEV;
+       }
+
+       if (wdrv->probe) {
+               ret = wdrv->probe(pdev);
+               if (ret)
+                       return ret;
+       }
+
+       return asus_wmi_add(pdev);
+}
+
+static bool used;
+
+int asus_wmi_register_driver(struct asus_wmi_driver *driver)
+{
+       struct platform_driver *platform_driver;
+       struct platform_device *platform_device;
+
+       if (used)
+               return -EBUSY;
+
+       platform_driver = &driver->platform_driver;
+       platform_driver->remove = asus_wmi_remove;
+       platform_driver->driver.owner = driver->owner;
+       platform_driver->driver.name = driver->name;
+       platform_driver->driver.pm = &asus_pm_ops;
+
+       platform_device = platform_create_bundle(platform_driver,
+                                                asus_wmi_probe,
+                                                NULL, 0, NULL, 0);
+       if (IS_ERR(platform_device))
+               return PTR_ERR(platform_device);
+
+       used = true;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
+
+void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
+{
+       platform_device_unregister(driver->platform_device);
+       platform_driver_unregister(&driver->platform_driver);
+       used = false;
+}
+EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
+
+static int __init asus_wmi_init(void)
+{
+       if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
+               pr_info("Asus Management GUID not found");
+               return -ENODEV;
+       }
+
+       pr_info("ASUS WMI generic driver loaded");
+       return 0;
+}
+
+static void __exit asus_wmi_exit(void)
+{
+       pr_info("ASUS WMI generic driver unloaded");
+}
+
+module_init(asus_wmi_init);
+module_exit(asus_wmi_exit);
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
new file mode 100644 (file)
index 0000000..c044522
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Asus PC WMI hotkey driver
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _ASUS_WMI_H_
+#define _ASUS_WMI_H_
+
+#include <linux/platform_device.h>
+
+struct module;
+struct key_entry;
+struct asus_wmi;
+
+struct asus_wmi_driver {
+       bool                    hotplug_wireless;
+
+       const char              *name;
+       struct module           *owner;
+
+       const char              *event_guid;
+
+       const struct key_entry  *keymap;
+       const char              *input_name;
+       const char              *input_phys;
+
+       int (*probe) (struct platform_device *device);
+       void (*quirks) (struct asus_wmi_driver *driver);
+
+       struct platform_driver  platform_driver;
+       struct platform_device *platform_device;
+};
+
+int asus_wmi_register_driver(struct asus_wmi_driver *driver);
+void asus_wmi_unregister_driver(struct asus_wmi_driver *driver);
+
+#endif /* !_ASUS_WMI_H_ */
index eb95878fa58335aa3a22bea204be4ecb28746046..c16a27641cedc57888fcc88b160aabec098520fd 100644 (file)
@@ -201,7 +201,7 @@ static bool extra_features;
  * into 0x4F and read a few bytes from the output, like so:
  *     u8 writeData = 0x33;
  *     ec_transaction(0x4F, &writeData, 1, buffer, 32, 0);
- * That address is labled "fan1 table information" in the service manual.
+ * That address is labelled "fan1 table information" in the service manual.
  * It should be clear which value in 'buffer' changes). This seems to be
  * related to fan speed. It isn't a proper 'realtime' fan speed value
  * though, because physically stopping or speeding up the fan doesn't
@@ -275,7 +275,7 @@ static int set_backlight_level(int level)
 
        ec_write(BACKLIGHT_LEVEL_ADDR, level);
 
-       return 1;
+       return 0;
 }
 
 static int get_backlight_level(void)
@@ -763,7 +763,7 @@ static int dmi_check_cb(const struct dmi_system_id *id)
        printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s'\n",
                id->ident);
        extra_features = false;
-       return 0;
+       return 1;
 }
 
 static int dmi_check_cb_extra(const struct dmi_system_id *id)
@@ -772,7 +772,7 @@ static int dmi_check_cb_extra(const struct dmi_system_id *id)
                "enabling extra features\n",
                id->ident);
        extra_features = true;
-       return 0;
+       return 1;
 }
 
 static struct dmi_system_id __initdata compal_dmi_table[] = {
diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c
new file mode 100644 (file)
index 0000000..0ed8457
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *  WMI hotkeys support for Dell All-In-One series
+ *
+ *  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
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
+#include <linux/string.h>
+
+MODULE_DESCRIPTION("WMI hotkeys driver for Dell All-In-One series");
+MODULE_LICENSE("GPL");
+
+#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
+#define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"
+
+static const char *dell_wmi_aio_guids[] = {
+       EVENT_GUID1,
+       EVENT_GUID2,
+       NULL
+};
+
+MODULE_ALIAS("wmi:"EVENT_GUID1);
+MODULE_ALIAS("wmi:"EVENT_GUID2);
+
+static const struct key_entry dell_wmi_aio_keymap[] = {
+       { KE_KEY, 0xc0, { KEY_VOLUMEUP } },
+       { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
+       { KE_END, 0 }
+};
+
+static struct input_dev *dell_wmi_aio_input_dev;
+
+static void dell_wmi_aio_notify(u32 value, void *context)
+{
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               pr_info("bad event status 0x%x\n", status);
+               return;
+       }
+
+       obj = (union acpi_object *)response.pointer;
+       if (obj) {
+               unsigned int scancode;
+
+               switch (obj->type) {
+               case ACPI_TYPE_INTEGER:
+                       /* Most All-In-One correctly return integer scancode */
+                       scancode = obj->integer.value;
+                       sparse_keymap_report_event(dell_wmi_aio_input_dev,
+                               scancode, 1, true);
+                       break;
+               case ACPI_TYPE_BUFFER:
+                       /* Broken machines return the scancode in a buffer */
+                       if (obj->buffer.pointer && obj->buffer.length > 0) {
+                               scancode = obj->buffer.pointer[0];
+                               sparse_keymap_report_event(
+                                       dell_wmi_aio_input_dev,
+                                       scancode, 1, true);
+                       }
+                       break;
+               }
+       }
+       kfree(obj);
+}
+
+static int __init dell_wmi_aio_input_setup(void)
+{
+       int err;
+
+       dell_wmi_aio_input_dev = input_allocate_device();
+
+       if (!dell_wmi_aio_input_dev)
+               return -ENOMEM;
+
+       dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys";
+       dell_wmi_aio_input_dev->phys = "wmi/input0";
+       dell_wmi_aio_input_dev->id.bustype = BUS_HOST;
+
+       err = sparse_keymap_setup(dell_wmi_aio_input_dev,
+                       dell_wmi_aio_keymap, NULL);
+       if (err) {
+               pr_err("Unable to setup input device keymap\n");
+               goto err_free_dev;
+       }
+       err = input_register_device(dell_wmi_aio_input_dev);
+       if (err) {
+               pr_info("Unable to register input device\n");
+               goto err_free_keymap;
+       }
+       return 0;
+
+err_free_keymap:
+       sparse_keymap_free(dell_wmi_aio_input_dev);
+err_free_dev:
+       input_free_device(dell_wmi_aio_input_dev);
+       return err;
+}
+
+static const char *dell_wmi_aio_find(void)
+{
+       int i;
+
+       for (i = 0; dell_wmi_aio_guids[i] != NULL; i++)
+               if (wmi_has_guid(dell_wmi_aio_guids[i]))
+                       return dell_wmi_aio_guids[i];
+
+       return NULL;
+}
+
+static int __init dell_wmi_aio_init(void)
+{
+       int err;
+       const char *guid;
+
+       guid = dell_wmi_aio_find();
+       if (!guid) {
+               pr_warning("No known WMI GUID found\n");
+               return -ENXIO;
+       }
+
+       err = dell_wmi_aio_input_setup();
+       if (err)
+               return err;
+
+       err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
+       if (err) {
+               pr_err("Unable to register notify handler - %d\n", err);
+               sparse_keymap_free(dell_wmi_aio_input_dev);
+               input_unregister_device(dell_wmi_aio_input_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+static void __exit dell_wmi_aio_exit(void)
+{
+       const char *guid;
+
+       guid = dell_wmi_aio_find();
+       wmi_remove_notify_handler(guid);
+       sparse_keymap_free(dell_wmi_aio_input_dev);
+       input_unregister_device(dell_wmi_aio_input_dev);
+}
+
+module_init(dell_wmi_aio_init);
+module_exit(dell_wmi_aio_exit);
index 6605beac0d0e5e570b0b0e7baf6edf6abbd03f73..5f2dd386152b52236991b73c60b61fa361555af9 100644 (file)
@@ -1322,7 +1322,7 @@ static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
 {
        int dummy;
 
-       /* Some BIOSes do not report cm although it is avaliable.
+       /* Some BIOSes do not report cm although it is available.
           Check if cm_getv[cm] works and, if yes, assume cm should be set. */
        if (!(eeepc->cm_supported & (1 << cm))
            && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
index 4d38f98aa97657b0b13262327eccc757d6f93066..0ddc434fb93ba2bdb8144f5937ba66707d3c72f5 100644 (file)
@@ -2,7 +2,7 @@
  * Eee PC WMI hotkey driver
  *
  * Copyright(C) 2010 Intel Corporation.
- * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
  *
  * Portions based on wistron_btns.c:
  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <linux/fb.h>
-#include <linux/backlight.h>
-#include <linux/leds.h>
-#include <linux/rfkill.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/platform_device.h>
+#include <linux/dmi.h>
 #include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+
+#include "asus-wmi.h"
 
 #define        EEEPC_WMI_FILE  "eeepc-wmi"
 
-MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
 MODULE_LICENSE("GPL");
 
 #define EEEPC_ACPI_HID         "ASUS010" /* old _HID used in eeepc-laptop */
 
 #define EEEPC_WMI_EVENT_GUID   "ABBC0F72-8EA1-11D1-00A0-C90629100000"
-#define EEEPC_WMI_MGMT_GUID    "97845ED0-4E6D-11DE-8A39-0800200C9A66"
 
 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
-MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
-
-#define NOTIFY_BRNUP_MIN       0x11
-#define NOTIFY_BRNUP_MAX       0x1f
-#define NOTIFY_BRNDOWN_MIN     0x20
-#define NOTIFY_BRNDOWN_MAX     0x2e
 
-#define EEEPC_WMI_METHODID_DEVS        0x53564544
-#define EEEPC_WMI_METHODID_DSTS        0x53544344
-#define EEEPC_WMI_METHODID_CFVS        0x53564643
+static bool hotplug_wireless;
 
-#define EEEPC_WMI_DEVID_BACKLIGHT      0x00050012
-#define EEEPC_WMI_DEVID_TPDLED         0x00100011
-#define EEEPC_WMI_DEVID_WLAN           0x00010011
-#define EEEPC_WMI_DEVID_BLUETOOTH      0x00010013
-#define EEEPC_WMI_DEVID_WWAN3G         0x00010019
+module_param(hotplug_wireless, bool, 0444);
+MODULE_PARM_DESC(hotplug_wireless,
+                "Enable hotplug for wireless device. "
+                "If your laptop needs that, please report to "
+                "acpi4asus-user@lists.sourceforge.net.");
 
 static const struct key_entry eeepc_wmi_keymap[] = {
        /* Sleep already handled via generic ACPI code */
-       { KE_KEY, 0x5d, { KEY_WLAN } },
-       { KE_KEY, 0x32, { KEY_MUTE } },
-       { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
        { KE_KEY, 0x30, { KEY_VOLUMEUP } },
-       { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
-       { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x32, { KEY_MUTE } },
+       { KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */
+       { KE_KEY, 0x5d, { KEY_WLAN } },
+       { KE_KEY, 0x6b, { KEY_TOUCHPAD_TOGGLE } }, /* Toggle Touchpad */
+       { KE_KEY, 0x82, { KEY_CAMERA } },
+       { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
+       { KE_KEY, 0x88, { KEY_WLAN } },
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
-       { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
-       { KE_KEY, 0xe1, { KEY_F14 } },
-       { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
-       { KE_KEY, 0xe0, { KEY_PROG1 } },
-       { KE_KEY, 0x5c, { KEY_F15 } },
+       { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
+       { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+       { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
+       { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
+       { KE_KEY, 0xec, { KEY_CAMERA_UP } },
+       { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
+       { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
+       { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
        { KE_END, 0},
 };
 
-struct bios_args {
-       u32     dev_id;
-       u32     ctrl_param;
-};
-
-/*
- * eeepc-wmi/    - debugfs root directory
- *   dev_id      - current dev_id
- *   ctrl_param  - current ctrl_param
- *   devs        - call DEVS(dev_id, ctrl_param) and print result
- *   dsts        - call DSTS(dev_id)  and print result
- */
-struct eeepc_wmi_debug {
-       struct dentry *root;
-       u32 dev_id;
-       u32 ctrl_param;
-};
-
-struct eeepc_wmi {
-       struct input_dev *inputdev;
-       struct backlight_device *backlight_device;
-       struct platform_device *platform_device;
-
-       struct led_classdev tpd_led;
-       int tpd_led_wk;
-       struct workqueue_struct *led_workqueue;
-       struct work_struct tpd_led_work;
-
-       struct rfkill *wlan_rfkill;
-       struct rfkill *bluetooth_rfkill;
-       struct rfkill *wwan3g_rfkill;
-
-       struct eeepc_wmi_debug debug;
-};
-
-/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
-static struct platform_device *platform_device;
-
-static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
-{
-       int err;
-
-       eeepc->inputdev = input_allocate_device();
-       if (!eeepc->inputdev)
-               return -ENOMEM;
-
-       eeepc->inputdev->name = "Eee PC WMI hotkeys";
-       eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
-       eeepc->inputdev->id.bustype = BUS_HOST;
-       eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
-
-       err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
-       if (err)
-               goto err_free_dev;
-
-       err = input_register_device(eeepc->inputdev);
-       if (err)
-               goto err_free_keymap;
-
-       return 0;
-
-err_free_keymap:
-       sparse_keymap_free(eeepc->inputdev);
-err_free_dev:
-       input_free_device(eeepc->inputdev);
-       return err;
-}
-
-static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
-{
-       if (eeepc->inputdev) {
-               sparse_keymap_free(eeepc->inputdev);
-               input_unregister_device(eeepc->inputdev);
-       }
-
-       eeepc->inputdev = NULL;
-}
-
-static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
-{
-       struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       acpi_status status;
-       u32 tmp;
-
-       status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
-                       1, EEEPC_WMI_METHODID_DSTS, &input, &output);
-
-       if (ACPI_FAILURE(status))
-               return status;
-
-       obj = (union acpi_object *)output.pointer;
-       if (obj && obj->type == ACPI_TYPE_INTEGER)
-               tmp = (u32)obj->integer.value;
-       else
-               tmp = 0;
-
-       if (retval)
-               *retval = tmp;
-
-       kfree(obj);
-
-       return status;
-
-}
-
-static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
-                                         u32 *retval)
-{
-       struct bios_args args = {
-               .dev_id = dev_id,
-               .ctrl_param = ctrl_param,
-       };
-       struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
-       acpi_status status;
-
-       if (!retval) {
-               status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
-                                            EEEPC_WMI_METHODID_DEVS,
-                                            &input, NULL);
-       } else {
-               struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-               union acpi_object *obj;
-               u32 tmp;
-
-               status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
-                                            EEEPC_WMI_METHODID_DEVS,
-                                            &input, &output);
-
-               if (ACPI_FAILURE(status))
-                       return status;
-
-               obj = (union acpi_object *)output.pointer;
-               if (obj && obj->type == ACPI_TYPE_INTEGER)
-                       tmp = (u32)obj->integer.value;
-               else
-                       tmp = 0;
-
-               *retval = tmp;
-
-               kfree(obj);
-       }
-
-       return status;
-}
-
-/*
- * LEDs
- */
-/*
- * These functions actually update the LED's, and are called from a
- * workqueue. By doing this as separate work rather than when the LED
- * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
- * potentially bad time, such as a timer interrupt.
- */
-static void tpd_led_update(struct work_struct *work)
-{
-       int ctrl_param;
-       struct eeepc_wmi *eeepc;
-
-       eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
-
-       ctrl_param = eeepc->tpd_led_wk;
-       eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
-}
-
-static void tpd_led_set(struct led_classdev *led_cdev,
-                       enum led_brightness value)
-{
-       struct eeepc_wmi *eeepc;
-
-       eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
-
-       eeepc->tpd_led_wk = !!value;
-       queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
-}
-
-static int read_tpd_state(struct eeepc_wmi *eeepc)
-{
-       u32 retval;
-       acpi_status status;
-
-       status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &retval);
-
-       if (ACPI_FAILURE(status))
-               return -1;
-       else if (!retval || retval == 0x00060000)
-               /*
-                * if touchpad led is present, DSTS will set some bits,
-                * usually 0x00020000.
-                * 0x00060000 means that the device is not supported
-                */
-               return -ENODEV;
-       else
-               /* Status is stored in the first bit */
-               return retval & 0x1;
-}
-
-static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
-{
-       struct eeepc_wmi *eeepc;
-
-       eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
-
-       return read_tpd_state(eeepc);
-}
-
-static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
-{
-       int rv;
-
-       if (read_tpd_state(eeepc) < 0)
-               return 0;
-
-       eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
-       if (!eeepc->led_workqueue)
-               return -ENOMEM;
-       INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
-
-       eeepc->tpd_led.name = "eeepc::touchpad";
-       eeepc->tpd_led.brightness_set = tpd_led_set;
-       eeepc->tpd_led.brightness_get = tpd_led_get;
-       eeepc->tpd_led.max_brightness = 1;
-
-       rv = led_classdev_register(&eeepc->platform_device->dev,
-                                  &eeepc->tpd_led);
-       if (rv) {
-               destroy_workqueue(eeepc->led_workqueue);
-               return rv;
-       }
-
-       return 0;
-}
-
-static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
-{
-       if (eeepc->tpd_led.dev)
-               led_classdev_unregister(&eeepc->tpd_led);
-       if (eeepc->led_workqueue)
-               destroy_workqueue(eeepc->led_workqueue);
-}
-
-/*
- * Rfkill devices
- */
-static int eeepc_rfkill_set(void *data, bool blocked)
-{
-       int dev_id = (unsigned long)data;
-       u32 ctrl_param = !blocked;
-
-       return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
-}
-
-static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
-{
-       int dev_id = (unsigned long)data;
-       u32 retval;
-       acpi_status status;
-
-       status = eeepc_wmi_get_devstate(dev_id, &retval);
-
-       if (ACPI_FAILURE(status))
-               return ;
-
-       rfkill_set_sw_state(rfkill, !(retval & 0x1));
-}
-
-static const struct rfkill_ops eeepc_rfkill_ops = {
-       .set_block = eeepc_rfkill_set,
-       .query = eeepc_rfkill_query,
-};
-
-static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
-                           struct rfkill **rfkill,
-                           const char *name,
-                           enum rfkill_type type, int dev_id)
-{
-       int result;
-       u32 retval;
-       acpi_status status;
-
-       status = eeepc_wmi_get_devstate(dev_id, &retval);
-
-       if (ACPI_FAILURE(status))
-               return -1;
-
-       /* If the device is present, DSTS will always set some bits
-        * 0x00070000 - 1110000000000000000 - device supported
-        * 0x00060000 - 1100000000000000000 - not supported
-        * 0x00020000 - 0100000000000000000 - device supported
-        * 0x00010000 - 0010000000000000000 - not supported / special mode ?
-        */
-       if (!retval || retval == 0x00060000)
-               return -ENODEV;
-
-       *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
-                              &eeepc_rfkill_ops, (void *)(long)dev_id);
-
-       if (!*rfkill)
-               return -EINVAL;
-
-       rfkill_init_sw_state(*rfkill, !(retval & 0x1));
-       result = rfkill_register(*rfkill);
-       if (result) {
-               rfkill_destroy(*rfkill);
-               *rfkill = NULL;
-               return result;
-       }
-       return 0;
-}
-
-static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
-{
-       if (eeepc->wlan_rfkill) {
-               rfkill_unregister(eeepc->wlan_rfkill);
-               rfkill_destroy(eeepc->wlan_rfkill);
-               eeepc->wlan_rfkill = NULL;
-       }
-       if (eeepc->bluetooth_rfkill) {
-               rfkill_unregister(eeepc->bluetooth_rfkill);
-               rfkill_destroy(eeepc->bluetooth_rfkill);
-               eeepc->bluetooth_rfkill = NULL;
-       }
-       if (eeepc->wwan3g_rfkill) {
-               rfkill_unregister(eeepc->wwan3g_rfkill);
-               rfkill_destroy(eeepc->wwan3g_rfkill);
-               eeepc->wwan3g_rfkill = NULL;
-       }
-}
-
-static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
-{
-       int result = 0;
-
-       result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
-                                 "eeepc-wlan", RFKILL_TYPE_WLAN,
-                                 EEEPC_WMI_DEVID_WLAN);
-
-       if (result && result != -ENODEV)
-               goto exit;
-
-       result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
-                                 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
-                                 EEEPC_WMI_DEVID_BLUETOOTH);
-
-       if (result && result != -ENODEV)
-               goto exit;
-
-       result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
-                                 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
-                                 EEEPC_WMI_DEVID_WWAN3G);
-
-       if (result && result != -ENODEV)
-               goto exit;
-
-exit:
-       if (result && result != -ENODEV)
-               eeepc_wmi_rfkill_exit(eeepc);
-
-       if (result == -ENODEV)
-               result = 0;
-
-       return result;
-}
-
-/*
- * Backlight
- */
-static int read_brightness(struct backlight_device *bd)
-{
-       u32 retval;
-       acpi_status status;
-
-       status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval);
-
-       if (ACPI_FAILURE(status))
-               return -1;
-       else
-               return retval & 0xFF;
-}
-
-static int update_bl_status(struct backlight_device *bd)
-{
-
-       u32 ctrl_param;
-       acpi_status status;
-
-       ctrl_param = bd->props.brightness;
-
-       status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
-                                       ctrl_param, NULL);
-
-       if (ACPI_FAILURE(status))
-               return -1;
-       else
-               return 0;
-}
-
-static const struct backlight_ops eeepc_wmi_bl_ops = {
-       .get_brightness = read_brightness,
-       .update_status = update_bl_status,
-};
-
-static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
-{
-       struct backlight_device *bd = eeepc->backlight_device;
-       int old = bd->props.brightness;
-       int new = old;
-
-       if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
-               new = code - NOTIFY_BRNUP_MIN + 1;
-       else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
-               new = code - NOTIFY_BRNDOWN_MIN;
-
-       bd->props.brightness = new;
-       backlight_update_status(bd);
-       backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
-
-       return old;
-}
-
-static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
-{
-       struct backlight_device *bd;
-       struct backlight_properties props;
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.max_brightness = 15;
-       bd = backlight_device_register(EEEPC_WMI_FILE,
-                                      &eeepc->platform_device->dev, eeepc,
-                                      &eeepc_wmi_bl_ops, &props);
-       if (IS_ERR(bd)) {
-               pr_err("Could not register backlight device\n");
-               return PTR_ERR(bd);
-       }
-
-       eeepc->backlight_device = bd;
-
-       bd->props.brightness = read_brightness(bd);
-       bd->props.power = FB_BLANK_UNBLANK;
-       backlight_update_status(bd);
-
-       return 0;
-}
-
-static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
-{
-       if (eeepc->backlight_device)
-               backlight_device_unregister(eeepc->backlight_device);
-
-       eeepc->backlight_device = NULL;
-}
-
-static void eeepc_wmi_notify(u32 value, void *context)
-{
-       struct eeepc_wmi *eeepc = context;
-       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       acpi_status status;
-       int code;
-       int orig_code;
-
-       status = wmi_get_event_data(value, &response);
-       if (status != AE_OK) {
-               pr_err("bad event status 0x%x\n", status);
-               return;
-       }
-
-       obj = (union acpi_object *)response.pointer;
-
-       if (obj && obj->type == ACPI_TYPE_INTEGER) {
-               code = obj->integer.value;
-               orig_code = code;
-
-               if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
-                       code = NOTIFY_BRNUP_MIN;
-               else if (code >= NOTIFY_BRNDOWN_MIN &&
-                        code <= NOTIFY_BRNDOWN_MAX)
-                       code = NOTIFY_BRNDOWN_MIN;
-
-               if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
-                       if (!acpi_video_backlight_support())
-                               eeepc_wmi_backlight_notify(eeepc, orig_code);
-               }
-
-               if (!sparse_keymap_report_event(eeepc->inputdev,
-                                               code, 1, true))
-                       pr_info("Unknown key %x pressed\n", code);
-       }
-
-       kfree(obj);
-}
-
-static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       int value;
-       struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
-       acpi_status status;
-
-       if (!count || sscanf(buf, "%i", &value) != 1)
-               return -EINVAL;
-       if (value < 0 || value > 2)
-               return -EINVAL;
-
-       status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
-                                    1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
-
-       if (ACPI_FAILURE(status))
-               return -EIO;
-       else
-               return count;
-}
-
-static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
-
-static struct attribute *platform_attributes[] = {
-       &dev_attr_cpufv.attr,
-       NULL
-};
-
-static struct attribute_group platform_attribute_group = {
-       .attrs = platform_attributes
-};
-
-static void eeepc_wmi_sysfs_exit(struct platform_device *device)
-{
-       sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
-}
-
-static int eeepc_wmi_sysfs_init(struct platform_device *device)
-{
-       return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
-}
-
-/*
- * Platform device
- */
-static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
-{
-       int err;
-
-       eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
-       if (!eeepc->platform_device)
-               return -ENOMEM;
-       platform_set_drvdata(eeepc->platform_device, eeepc);
-
-       err = platform_device_add(eeepc->platform_device);
-       if (err)
-               goto fail_platform_device;
-
-       err = eeepc_wmi_sysfs_init(eeepc->platform_device);
-       if (err)
-               goto fail_sysfs;
-       return 0;
-
-fail_sysfs:
-       platform_device_del(eeepc->platform_device);
-fail_platform_device:
-       platform_device_put(eeepc->platform_device);
-       return err;
-}
-
-static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
-{
-       eeepc_wmi_sysfs_exit(eeepc->platform_device);
-       platform_device_unregister(eeepc->platform_device);
-}
-
-/*
- * debugfs
- */
-struct eeepc_wmi_debugfs_node {
-       struct eeepc_wmi *eeepc;
-       char *name;
-       int (*show)(struct seq_file *m, void *data);
-};
-
-static int show_dsts(struct seq_file *m, void *data)
-{
-       struct eeepc_wmi *eeepc = m->private;
-       acpi_status status;
-       u32 retval = -1;
-
-       status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
-
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
-
-       return 0;
-}
-
-static int show_devs(struct seq_file *m, void *data)
-{
-       struct eeepc_wmi *eeepc = m->private;
-       acpi_status status;
-       u32 retval = -1;
-
-       status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
-                                       eeepc->debug.ctrl_param, &retval);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
-                  eeepc->debug.ctrl_param, retval);
-
-       return 0;
-}
-
-static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
-       { NULL, "devs", show_devs },
-       { NULL, "dsts", show_dsts },
-};
-
-static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
-{
-       struct eeepc_wmi_debugfs_node *node = inode->i_private;
-
-       return single_open(file, node->show, node->eeepc);
-}
-
-static const struct file_operations eeepc_wmi_debugfs_io_ops = {
-       .owner = THIS_MODULE,
-       .open  = eeepc_wmi_debugfs_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
-{
-       debugfs_remove_recursive(eeepc->debug.root);
-}
-
-static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
-{
-       struct dentry *dent;
-       int i;
-
-       eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
-       if (!eeepc->debug.root) {
-               pr_err("failed to create debugfs directory");
-               goto error_debugfs;
-       }
-
-       dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
-                                 eeepc->debug.root, &eeepc->debug.dev_id);
-       if (!dent)
-               goto error_debugfs;
-
-       dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
-                                 eeepc->debug.root, &eeepc->debug.ctrl_param);
-       if (!dent)
-               goto error_debugfs;
-
-       for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
-               struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
-
-               node->eeepc = eeepc;
-               dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
-                                          eeepc->debug.root, node,
-                                          &eeepc_wmi_debugfs_io_ops);
-               if (!dent) {
-                       pr_err("failed to create debug file: %s\n", node->name);
-                       goto error_debugfs;
-               }
-       }
-
-       return 0;
-
-error_debugfs:
-       eeepc_wmi_debugfs_exit(eeepc);
-       return -ENOMEM;
-}
-
-/*
- * WMI Driver
- */
-static struct platform_device * __init eeepc_wmi_add(void)
-{
-       struct eeepc_wmi *eeepc;
-       acpi_status status;
-       int err;
-
-       eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
-       if (!eeepc)
-               return ERR_PTR(-ENOMEM);
-
-       /*
-        * Register the platform device first.  It is used as a parent for the
-        * sub-devices below.
-        */
-       err = eeepc_wmi_platform_init(eeepc);
-       if (err)
-               goto fail_platform;
-
-       err = eeepc_wmi_input_init(eeepc);
-       if (err)
-               goto fail_input;
-
-       err = eeepc_wmi_led_init(eeepc);
-       if (err)
-               goto fail_leds;
-
-       err = eeepc_wmi_rfkill_init(eeepc);
-       if (err)
-               goto fail_rfkill;
-
-       if (!acpi_video_backlight_support()) {
-               err = eeepc_wmi_backlight_init(eeepc);
-               if (err)
-                       goto fail_backlight;
-       } else
-               pr_info("Backlight controlled by ACPI video driver\n");
-
-       status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
-                                           eeepc_wmi_notify, eeepc);
-       if (ACPI_FAILURE(status)) {
-               pr_err("Unable to register notify handler - %d\n",
-                       status);
-               err = -ENODEV;
-               goto fail_wmi_handler;
-       }
-
-       err = eeepc_wmi_debugfs_init(eeepc);
-       if (err)
-               goto fail_debugfs;
-
-       return eeepc->platform_device;
-
-fail_debugfs:
-       wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
-fail_wmi_handler:
-       eeepc_wmi_backlight_exit(eeepc);
-fail_backlight:
-       eeepc_wmi_rfkill_exit(eeepc);
-fail_rfkill:
-       eeepc_wmi_led_exit(eeepc);
-fail_leds:
-       eeepc_wmi_input_exit(eeepc);
-fail_input:
-       eeepc_wmi_platform_exit(eeepc);
-fail_platform:
-       kfree(eeepc);
-       return ERR_PTR(err);
-}
-
-static int eeepc_wmi_remove(struct platform_device *device)
-{
-       struct eeepc_wmi *eeepc;
-
-       eeepc = platform_get_drvdata(device);
-       wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
-       eeepc_wmi_backlight_exit(eeepc);
-       eeepc_wmi_input_exit(eeepc);
-       eeepc_wmi_led_exit(eeepc);
-       eeepc_wmi_rfkill_exit(eeepc);
-       eeepc_wmi_debugfs_exit(eeepc);
-       eeepc_wmi_platform_exit(eeepc);
-
-       kfree(eeepc);
-       return 0;
-}
-
-static struct platform_driver platform_driver = {
-       .driver = {
-               .name = EEEPC_WMI_FILE,
-               .owner = THIS_MODULE,
-       },
-};
-
-static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
+static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
                                                 void *context, void **retval)
 {
        pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
@@ -871,7 +87,7 @@ static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
        return AE_CTRL_TERMINATE;
 }
 
-static int __init eeepc_wmi_check_atkd(void)
+static int eeepc_wmi_check_atkd(void)
 {
        acpi_status status;
        bool found = false;
@@ -884,16 +100,8 @@ static int __init eeepc_wmi_check_atkd(void)
        return -1;
 }
 
-static int __init eeepc_wmi_init(void)
+static int eeepc_wmi_probe(struct platform_device *pdev)
 {
-       int err;
-
-       if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
-           !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
-               pr_warning("No known WMI GUID found\n");
-               return -ENODEV;
-       }
-
        if (eeepc_wmi_check_atkd()) {
                pr_warning("WMI device present, but legacy ATKD device is also "
                           "present and enabled.");
@@ -901,33 +109,59 @@ static int __init eeepc_wmi_init(void)
                           "acpi_osi=\"!Windows 2009\"");
                pr_warning("Can't load eeepc-wmi, use default acpi_osi "
                           "(preferred) or eeepc-laptop");
-               return -ENODEV;
+               return -EBUSY;
        }
+       return 0;
+}
 
-       platform_device = eeepc_wmi_add();
-       if (IS_ERR(platform_device)) {
-               err = PTR_ERR(platform_device);
-               goto fail_eeepc_wmi;
-       }
+static void eeepc_dmi_check(struct asus_wmi_driver *driver)
+{
+       const char *model;
+
+       model = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (!model)
+               return;
 
-       err = platform_driver_register(&platform_driver);
-       if (err) {
-               pr_warning("Unable to register platform driver\n");
-               goto fail_platform_driver;
+       /*
+        * Whitelist for wlan hotplug
+        *
+        * Asus 1000H needs the current hotplug code to handle
+        * Fn+F2 correctly. We may add other Asus here later, but
+        * it seems that most of the laptops supported by asus-wmi
+        * don't need to be on this list
+        */
+       if (strcmp(model, "1000H") == 0) {
+               driver->hotplug_wireless = true;
+               pr_info("wlan hotplug enabled\n");
        }
+}
+
+static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
+{
+       driver->hotplug_wireless = hotplug_wireless;
+       eeepc_dmi_check(driver);
+}
+
+static struct asus_wmi_driver asus_wmi_driver = {
+       .name = EEEPC_WMI_FILE,
+       .owner = THIS_MODULE,
+       .event_guid = EEEPC_WMI_EVENT_GUID,
+       .keymap = eeepc_wmi_keymap,
+       .input_name = "Eee PC WMI hotkeys",
+       .input_phys = EEEPC_WMI_FILE "/input0",
+       .probe = eeepc_wmi_probe,
+       .quirks = eeepc_wmi_quirks,
+};
 
-       return 0;
 
-fail_platform_driver:
-       eeepc_wmi_remove(platform_device);
-fail_eeepc_wmi:
-       return err;
+static int __init eeepc_wmi_init(void)
+{
+       return asus_wmi_register_driver(&asus_wmi_driver);
 }
 
 static void __exit eeepc_wmi_exit(void)
 {
-       eeepc_wmi_remove(platform_device);
-       platform_driver_unregister(&platform_driver);
+       asus_wmi_unregister_driver(&asus_wmi_driver);
 }
 
 module_init(eeepc_wmi_init);
index 9e05af9c41cbcd129bc3912c4bff2b6b8ad61b96..1bc4a7539ba93f9b9f9cbdd74244b90a67302435 100644 (file)
@@ -2,6 +2,7 @@
  * HP WMI hotkeys
  *
  * Copyright (C) 2008 Red Hat <mjg@redhat.com>
+ * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
  *
  * Portions based on wistron_btns.c:
  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
@@ -51,6 +52,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
 #define HPWMI_HOTKEY_QUERY 0xc
+#define HPWMI_WIRELESS2_QUERY 0x1b
 
 #define PREFIX "HP WMI: "
 #define UNIMP "Unimplemented "
@@ -86,7 +88,46 @@ struct bios_args {
 struct bios_return {
        u32 sigpass;
        u32 return_code;
-       u32 value;
+};
+
+enum hp_return_value {
+       HPWMI_RET_WRONG_SIGNATURE       = 0x02,
+       HPWMI_RET_UNKNOWN_COMMAND       = 0x03,
+       HPWMI_RET_UNKNOWN_CMDTYPE       = 0x04,
+       HPWMI_RET_INVALID_PARAMETERS    = 0x05,
+};
+
+enum hp_wireless2_bits {
+       HPWMI_POWER_STATE       = 0x01,
+       HPWMI_POWER_SOFT        = 0x02,
+       HPWMI_POWER_BIOS        = 0x04,
+       HPWMI_POWER_HARD        = 0x08,
+};
+
+#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \
+                        != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD))
+#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
+
+struct bios_rfkill2_device_state {
+       u8 radio_type;
+       u8 bus_type;
+       u16 vendor_id;
+       u16 product_id;
+       u16 subsys_vendor_id;
+       u16 subsys_product_id;
+       u8 rfkill_id;
+       u8 power;
+       u8 unknown[4];
+};
+
+/* 7 devices fit into the 128 byte buffer */
+#define HPWMI_MAX_RFKILL2_DEVICES      7
+
+struct bios_rfkill2_state {
+       u8 unknown[7];
+       u8 count;
+       u8 pad[8];
+       struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
 };
 
 static const struct key_entry hp_wmi_keymap[] = {
@@ -108,6 +149,15 @@ static struct rfkill *wifi_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *wwan_rfkill;
 
+struct rfkill2_device {
+       u8 id;
+       int num;
+       struct rfkill *rfkill;
+};
+
+static int rfkill2_count;
+static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
+
 static const struct dev_pm_ops hp_wmi_pm_ops = {
        .resume  = hp_wmi_resume_handler,
        .restore  = hp_wmi_resume_handler,
@@ -129,7 +179,8 @@ static struct platform_driver hp_wmi_driver = {
  * query:      The commandtype -> What should be queried
  * write:      The command -> 0 read, 1 write, 3 ODM specific
  * buffer:     Buffer used as input and/or output
- * buffersize: Size of buffer
+ * insize:     Size of input buffer
+ * outsize:    Size of output buffer
  *
  * returns zero on success
  *         an HP WMI query specific error code (which is positive)
@@ -140,25 +191,29 @@ static struct platform_driver hp_wmi_driver = {
  *       size. E.g. Battery info query (0x7) is defined to have 1 byte input
  *       and 128 byte output. The caller would do:
  *       buffer = kzalloc(128, GFP_KERNEL);
- *       ret = hp_wmi_perform_query(0x7, 0, buffer, 128)
+ *       ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128)
  */
-static int hp_wmi_perform_query(int query, int write, u32 *buffer,
-                               int buffersize)
+static int hp_wmi_perform_query(int query, int write, void *buffer,
+                               int insize, int outsize)
 {
-       struct bios_return bios_return;
-       acpi_status status;
+       struct bios_return *bios_return;
+       int actual_outsize;
        union acpi_object *obj;
        struct bios_args args = {
                .signature = 0x55434553,
                .command = write ? 0x2 : 0x1,
                .commandtype = query,
-               .datasize = buffersize,
-               .data = *buffer,
+               .datasize = insize,
+               .data = 0,
        };
        struct acpi_buffer input = { sizeof(struct bios_args), &args };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
+       if (WARN_ON(insize > sizeof(args.data)))
+               return -EINVAL;
+       memcpy(&args.data, buffer, insize);
+
+       wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
 
        obj = output.pointer;
 
@@ -169,10 +224,26 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer,
                return -EINVAL;
        }
 
-       bios_return = *((struct bios_return *)obj->buffer.pointer);
+       bios_return = (struct bios_return *)obj->buffer.pointer;
 
-       memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
+       if (bios_return->return_code) {
+               if (bios_return->return_code != HPWMI_RET_UNKNOWN_CMDTYPE)
+                       printk(KERN_WARNING PREFIX "query 0x%x returned "
+                                                  "error 0x%x\n",
+                              query, bios_return->return_code);
+               kfree(obj);
+               return bios_return->return_code;
+       }
+
+       if (!outsize) {
+               /* ignore output data */
+               kfree(obj);
+               return 0;
+       }
 
+       actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
+       memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
+       memset(buffer + actual_outsize, 0, outsize - actual_outsize);
        kfree(obj);
        return 0;
 }
@@ -181,7 +252,7 @@ static int hp_wmi_display_state(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
-                                      sizeof(state));
+                                      sizeof(state), sizeof(state));
        if (ret)
                return -EINVAL;
        return state;
@@ -191,7 +262,7 @@ static int hp_wmi_hddtemp_state(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
-                                      sizeof(state));
+                                      sizeof(state), sizeof(state));
        if (ret)
                return -EINVAL;
        return state;
@@ -201,7 +272,7 @@ static int hp_wmi_als_state(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
-                                      sizeof(state));
+                                      sizeof(state), sizeof(state));
        if (ret)
                return -EINVAL;
        return state;
@@ -211,7 +282,7 @@ static int hp_wmi_dock_state(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
-                                      sizeof(state));
+                                      sizeof(state), sizeof(state));
 
        if (ret)
                return -EINVAL;
@@ -223,7 +294,7 @@ static int hp_wmi_tablet_state(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
-                                      sizeof(state));
+                                      sizeof(state), sizeof(state));
        if (ret)
                return ret;
 
@@ -237,7 +308,7 @@ static int hp_wmi_set_block(void *data, bool blocked)
        int ret;
 
        ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
-                                  &query, sizeof(query));
+                                  &query, sizeof(query), 0);
        if (ret)
                return -EINVAL;
        return 0;
@@ -252,7 +323,8 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
        int wireless = 0;
        int mask;
        hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-                            &wireless, sizeof(wireless));
+                            &wireless, sizeof(wireless),
+                            sizeof(wireless));
        /* TBD: Pass error */
 
        mask = 0x200 << (r * 8);
@@ -268,7 +340,8 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
        int wireless = 0;
        int mask;
        hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-                            &wireless, sizeof(wireless));
+                            &wireless, sizeof(wireless),
+                            sizeof(wireless));
        /* TBD: Pass error */
 
        mask = 0x800 << (r * 8);
@@ -279,6 +352,51 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
                return true;
 }
 
+static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
+{
+       int rfkill_id = (int)(long)data;
+       char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
+
+       if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1,
+                                  buffer, sizeof(buffer), 0))
+               return -EINVAL;
+       return 0;
+}
+
+static const struct rfkill_ops hp_wmi_rfkill2_ops = {
+       .set_block = hp_wmi_rfkill2_set_block,
+};
+
+static int hp_wmi_rfkill2_refresh(void)
+{
+       int err, i;
+       struct bios_rfkill2_state state;
+
+       err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
+                                  0, sizeof(state));
+       if (err)
+               return err;
+
+       for (i = 0; i < rfkill2_count; i++) {
+               int num = rfkill2[i].num;
+               struct bios_rfkill2_device_state *devstate;
+               devstate = &state.device[num];
+
+               if (num >= state.count ||
+                   devstate->rfkill_id != rfkill2[i].id) {
+                       printk(KERN_WARNING PREFIX "power configuration of "
+                              "the wireless devices unexpectedly changed\n");
+                       continue;
+               }
+
+               rfkill_set_states(rfkill2[i].rfkill,
+                                 IS_SWBLOCKED(devstate->power),
+                                 IS_HWBLOCKED(devstate->power));
+       }
+
+       return 0;
+}
+
 static ssize_t show_display(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
@@ -329,7 +447,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr,
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
        int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp,
-                                      sizeof(tmp));
+                                      sizeof(tmp), sizeof(tmp));
        if (ret)
                return -EINVAL;
 
@@ -402,6 +520,7 @@ static void hp_wmi_notify(u32 value, void *context)
        case HPWMI_BEZEL_BUTTON:
                ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
                                           &key_code,
+                                          sizeof(key_code),
                                           sizeof(key_code));
                if (ret)
                        break;
@@ -412,6 +531,11 @@ static void hp_wmi_notify(u32 value, void *context)
                               key_code);
                break;
        case HPWMI_WIRELESS:
+               if (rfkill2_count) {
+                       hp_wmi_rfkill2_refresh();
+                       break;
+               }
+
                if (wifi_rfkill)
                        rfkill_set_states(wifi_rfkill,
                                          hp_wmi_get_sw_state(HPWMI_WIFI),
@@ -502,32 +626,16 @@ static void cleanup_sysfs(struct platform_device *device)
        device_remove_file(&device->dev, &dev_attr_tablet);
 }
 
-static int __devinit hp_wmi_bios_setup(struct platform_device *device)
+static int __devinit hp_wmi_rfkill_setup(struct platform_device *device)
 {
        int err;
        int wireless = 0;
 
        err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless,
-                                  sizeof(wireless));
+                                  sizeof(wireless), sizeof(wireless));
        if (err)
                return err;
 
-       err = device_create_file(&device->dev, &dev_attr_display);
-       if (err)
-               goto add_sysfs_error;
-       err = device_create_file(&device->dev, &dev_attr_hddtemp);
-       if (err)
-               goto add_sysfs_error;
-       err = device_create_file(&device->dev, &dev_attr_als);
-       if (err)
-               goto add_sysfs_error;
-       err = device_create_file(&device->dev, &dev_attr_dock);
-       if (err)
-               goto add_sysfs_error;
-       err = device_create_file(&device->dev, &dev_attr_tablet);
-       if (err)
-               goto add_sysfs_error;
-
        if (wireless & 0x1) {
                wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
                                           RFKILL_TYPE_WLAN,
@@ -573,14 +681,131 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device)
        return 0;
 register_wwan_err:
        rfkill_destroy(wwan_rfkill);
+       wwan_rfkill = NULL;
        if (bluetooth_rfkill)
                rfkill_unregister(bluetooth_rfkill);
 register_bluetooth_error:
        rfkill_destroy(bluetooth_rfkill);
+       bluetooth_rfkill = NULL;
        if (wifi_rfkill)
                rfkill_unregister(wifi_rfkill);
 register_wifi_error:
        rfkill_destroy(wifi_rfkill);
+       wifi_rfkill = NULL;
+       return err;
+}
+
+static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device)
+{
+       int err, i;
+       struct bios_rfkill2_state state;
+       err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
+                                  0, sizeof(state));
+       if (err)
+               return err;
+
+       if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
+               printk(KERN_WARNING PREFIX "unable to parse 0x1b query output\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < state.count; i++) {
+               struct rfkill *rfkill;
+               enum rfkill_type type;
+               char *name;
+               switch (state.device[i].radio_type) {
+               case HPWMI_WIFI:
+                       type = RFKILL_TYPE_WLAN;
+                       name = "hp-wifi";
+                       break;
+               case HPWMI_BLUETOOTH:
+                       type = RFKILL_TYPE_BLUETOOTH;
+                       name = "hp-bluetooth";
+                       break;
+               case HPWMI_WWAN:
+                       type = RFKILL_TYPE_WWAN;
+                       name = "hp-wwan";
+                       break;
+               default:
+                       printk(KERN_WARNING PREFIX "unknown device type 0x%x\n",
+                                state.device[i].radio_type);
+                       continue;
+               }
+
+               if (!state.device[i].vendor_id) {
+                       printk(KERN_WARNING PREFIX "zero device %d while %d "
+                              "reported\n", i, state.count);
+                       continue;
+               }
+
+               rfkill = rfkill_alloc(name, &device->dev, type,
+                                     &hp_wmi_rfkill2_ops, (void *)(long)i);
+               if (!rfkill) {
+                       err = -ENOMEM;
+                       goto fail;
+               }
+
+               rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
+               rfkill2[rfkill2_count].num = i;
+               rfkill2[rfkill2_count].rfkill = rfkill;
+
+               rfkill_init_sw_state(rfkill,
+                                    IS_SWBLOCKED(state.device[i].power));
+               rfkill_set_hw_state(rfkill,
+                                   IS_HWBLOCKED(state.device[i].power));
+
+               if (!(state.device[i].power & HPWMI_POWER_BIOS))
+                       printk(KERN_INFO PREFIX "device %s blocked by BIOS\n",
+                              name);
+
+               err = rfkill_register(rfkill);
+               if (err) {
+                       rfkill_destroy(rfkill);
+                       goto fail;
+               }
+
+               rfkill2_count++;
+       }
+
+       return 0;
+fail:
+       for (; rfkill2_count > 0; rfkill2_count--) {
+               rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
+               rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
+       }
+       return err;
+}
+
+static int __devinit hp_wmi_bios_setup(struct platform_device *device)
+{
+       int err;
+
+       /* clear detected rfkill devices */
+       wifi_rfkill = NULL;
+       bluetooth_rfkill = NULL;
+       wwan_rfkill = NULL;
+       rfkill2_count = 0;
+
+       if (hp_wmi_rfkill_setup(device))
+               hp_wmi_rfkill2_setup(device);
+
+       err = device_create_file(&device->dev, &dev_attr_display);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_hddtemp);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_als);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_dock);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_tablet);
+       if (err)
+               goto add_sysfs_error;
+       return 0;
+
 add_sysfs_error:
        cleanup_sysfs(device);
        return err;
@@ -588,8 +813,14 @@ add_sysfs_error:
 
 static int __exit hp_wmi_bios_remove(struct platform_device *device)
 {
+       int i;
        cleanup_sysfs(device);
 
+       for (i = 0; i < rfkill2_count; i++) {
+               rfkill_unregister(rfkill2[i].rfkill);
+               rfkill_destroy(rfkill2[i].rfkill);
+       }
+
        if (wifi_rfkill) {
                rfkill_unregister(wifi_rfkill);
                rfkill_destroy(wifi_rfkill);
@@ -622,6 +853,9 @@ static int hp_wmi_resume_handler(struct device *device)
                input_sync(hp_wmi_input_dev);
        }
 
+       if (rfkill2_count)
+               hp_wmi_rfkill2_refresh();
+
        if (wifi_rfkill)
                rfkill_set_states(wifi_rfkill,
                                  hp_wmi_get_sw_state(HPWMI_WIFI),
index 114d95247cdf8f6ad3c07d14a6a88496d6f63f43..21b101899baeeb76e718c80c089caa2c8553c848 100644 (file)
@@ -459,6 +459,8 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
                if (test_bit(vpc_bit, &vpc1)) {
                        if (vpc_bit == 9)
                                ideapad_sync_rfk_state(adevice);
+                       else if (vpc_bit == 4)
+                               read_ec_data(handle, 0x12, &vpc2);
                        else
                                ideapad_input_report(priv, vpc_bit);
                }
index 1294a39373bab688fbc8ce14a777a8811c66c7b2..85c8ad43c0c5821f1e38ca2572ff02799324f014 100644 (file)
@@ -1111,7 +1111,7 @@ static int ips_monitor(void *data)
                last_msecs = jiffies_to_msecs(jiffies);
                expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD);
 
-               __set_current_state(TASK_UNINTERRUPTIBLE);
+               __set_current_state(TASK_INTERRUPTIBLE);
                mod_timer(&timer, expire);
                schedule();
 
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
new file mode 100644 (file)
index 0000000..213e79b
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Power button driver for Medfield.
+ *
+ * Copyright (C) 2010 Intel Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <asm/intel_scu_ipc.h>
+
+#define DRIVER_NAME "msic_power_btn"
+
+#define MSIC_IRQ_STAT  0x02
+  #define MSIC_IRQ_PB  (1 << 0)
+#define MSIC_PB_CONFIG 0x3e
+#define MSIC_PB_STATUS 0x3f
+  #define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
+
+struct mfld_pb_priv {
+       struct input_dev *input;
+       unsigned int irq;
+};
+
+static irqreturn_t mfld_pb_isr(int irq, void *dev_id)
+{
+       struct mfld_pb_priv *priv = dev_id;
+       int ret;
+       u8 pbstat;
+
+       ret = intel_scu_ipc_ioread8(MSIC_PB_STATUS, &pbstat);
+       if (ret < 0)
+               return IRQ_HANDLED;
+
+       input_event(priv->input, EV_KEY, KEY_POWER, !(pbstat & MSIC_PB_LEVEL));
+       input_sync(priv->input);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit mfld_pb_probe(struct platform_device *pdev)
+{
+       struct mfld_pb_priv *priv;
+       struct input_dev *input;
+       int irq;
+       int error;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return -EINVAL;
+
+       priv = kzalloc(sizeof(struct mfld_pb_priv), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!priv || !input) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       priv->input = input;
+       priv->irq = irq;
+
+       input->name = pdev->name;
+       input->phys = "power-button/input0";
+       input->id.bustype = BUS_HOST;
+       input->dev.parent = &pdev->dev;
+
+       input_set_capability(input, EV_KEY, KEY_POWER);
+
+       error = request_threaded_irq(priv->irq, NULL, mfld_pb_isr,
+                                    0, DRIVER_NAME, priv);
+       if (error) {
+               dev_err(&pdev->dev,
+                       "unable to request irq %d for mfld power button\n",
+                       irq);
+               goto err_free_mem;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev,
+                       "unable to register input dev, error %d\n", error);
+               goto err_free_irq;
+       }
+
+       platform_set_drvdata(pdev, priv);
+       return 0;
+
+err_free_irq:
+       free_irq(priv->irq, priv);
+err_free_mem:
+       input_free_device(input);
+       kfree(priv);
+       return error;
+}
+
+static int __devexit mfld_pb_remove(struct platform_device *pdev)
+{
+       struct mfld_pb_priv *priv = platform_get_drvdata(pdev);
+
+       free_irq(priv->irq, priv);
+       input_unregister_device(priv->input);
+       kfree(priv);
+
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver mfld_pb_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe  = mfld_pb_probe,
+       .remove = __devexit_p(mfld_pb_remove),
+};
+
+static int __init mfld_pb_init(void)
+{
+       return platform_driver_register(&mfld_pb_driver);
+}
+module_init(mfld_pb_init);
+
+static void __exit mfld_pb_exit(void)
+{
+       platform_driver_unregister(&mfld_pb_driver);
+}
+module_exit(mfld_pb_exit);
+
+MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
+MODULE_DESCRIPTION("Intel Medfield Power Button Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
new file mode 100644 (file)
index 0000000..6c12db5
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * intel_mid_thermal.c - Intel MID platform thermal driver
+ *
+ * Copyright (C) 2011 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 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Author: Durgadoss R <durgadoss.r@intel.com>
+ */
+
+#define pr_fmt(fmt) "intel_mid_thermal: " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/thermal.h>
+
+#include <asm/intel_scu_ipc.h>
+
+/* Number of thermal sensors */
+#define MSIC_THERMAL_SENSORS   4
+
+/* ADC1 - thermal registers */
+#define MSIC_THERM_ADC1CNTL1   0x1C0
+#define MSIC_ADC_ENBL          0x10
+#define MSIC_ADC_START         0x08
+
+#define MSIC_THERM_ADC1CNTL3   0x1C2
+#define MSIC_ADCTHERM_ENBL     0x04
+#define MSIC_ADCRRDATA_ENBL    0x05
+#define MSIC_CHANL_MASK_VAL    0x0F
+
+#define MSIC_STOPBIT_MASK      16
+#define MSIC_ADCTHERM_MASK     4
+#define ADC_CHANLS_MAX         15 /* Number of ADC channels */
+#define ADC_LOOP_MAX           (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
+
+/* ADC channel code values */
+#define SKIN_SENSOR0_CODE      0x08
+#define SKIN_SENSOR1_CODE      0x09
+#define SYS_SENSOR_CODE                0x0A
+#define MSIC_DIE_SENSOR_CODE   0x03
+
+#define SKIN_THERM_SENSOR0     0
+#define SKIN_THERM_SENSOR1     1
+#define SYS_THERM_SENSOR2      2
+#define MSIC_DIE_THERM_SENSOR3 3
+
+/* ADC code range */
+#define ADC_MAX                        977
+#define ADC_MIN                        162
+#define ADC_VAL0C              887
+#define ADC_VAL20C             720
+#define ADC_VAL40C             508
+#define ADC_VAL60C             315
+
+/* ADC base addresses */
+#define ADC_CHNL_START_ADDR    0x1C5   /* increments by 1 */
+#define ADC_DATA_START_ADDR     0x1D4   /* increments by 2 */
+
+/* MSIC die attributes */
+#define MSIC_DIE_ADC_MIN       488
+#define MSIC_DIE_ADC_MAX       1004
+
+/* This holds the address of the first free ADC channel,
+ * among the 15 channels
+ */
+static int channel_index;
+
+struct platform_info {
+       struct platform_device *pdev;
+       struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
+};
+
+struct thermal_device_info {
+       unsigned int chnl_addr;
+       int direct;
+       /* This holds the current temperature in millidegree celsius */
+       long curr_temp;
+};
+
+/**
+ * to_msic_die_temp - converts adc_val to msic_die temperature
+ * @adc_val: ADC value to be converted
+ *
+ * Can sleep
+ */
+static int to_msic_die_temp(uint16_t adc_val)
+{
+       return (368 * (adc_val) / 1000) - 220;
+}
+
+/**
+ * is_valid_adc - checks whether the adc code is within the defined range
+ * @min: minimum value for the sensor
+ * @max: maximum value for the sensor
+ *
+ * Can sleep
+ */
+static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
+{
+       return (adc_val >= min) && (adc_val <= max);
+}
+
+/**
+ * adc_to_temp - converts the ADC code to temperature in C
+ * @direct: true if ths channel is direct index
+ * @adc_val: the adc_val that needs to be converted
+ * @tp: temperature return value
+ *
+ * Linear approximation is used to covert the skin adc value into temperature.
+ * This technique is used to avoid very long look-up table to get
+ * the appropriate temp value from ADC value.
+ * The adc code vs sensor temp curve is split into five parts
+ * to achieve very close approximate temp value with less than
+ * 0.5C error
+ */
+static int adc_to_temp(int direct, uint16_t adc_val, unsigned long *tp)
+{
+       int temp;
+
+       /* Direct conversion for die temperature */
+       if (direct) {
+               if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
+                       *tp = to_msic_die_temp(adc_val) * 1000;
+                       return 0;
+               }
+               return -ERANGE;
+       }
+
+       if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
+               return -ERANGE;
+
+       /* Linear approximation for skin temperature */
+       if (adc_val > ADC_VAL0C)
+               temp = 177 - (adc_val/5);
+       else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
+               temp = 111 - (adc_val/8);
+       else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
+               temp = 92 - (adc_val/10);
+       else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
+               temp = 91 - (adc_val/10);
+       else
+               temp = 112 - (adc_val/6);
+
+       /* Convert temperature in celsius to milli degree celsius */
+       *tp = temp * 1000;
+       return 0;
+}
+
+/**
+ * mid_read_temp - read sensors for temperature
+ * @temp: holds the current temperature for the sensor after reading
+ *
+ * reads the adc_code from the channel and converts it to real
+ * temperature. The converted value is stored in temp.
+ *
+ * Can sleep
+ */
+static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+{
+       struct thermal_device_info *td_info = tzd->devdata;
+       uint16_t adc_val, addr;
+       uint8_t data = 0;
+       int ret;
+       unsigned long curr_temp;
+
+
+       addr = td_info->chnl_addr;
+
+       /* Enable the msic for conversion before reading */
+       ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
+       if (ret)
+               return ret;
+
+       /* Re-toggle the RRDATARD bit (temporary workaround) */
+       ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
+       if (ret)
+               return ret;
+
+       /* Read the higher bits of data */
+       ret = intel_scu_ipc_ioread8(addr, &data);
+       if (ret)
+               return ret;
+
+       /* Shift bits to accomodate the lower two data bits */
+       adc_val = (data << 2);
+       addr++;
+
+       ret = intel_scu_ipc_ioread8(addr, &data);/* Read lower bits */
+       if (ret)
+               return ret;
+
+       /* Adding lower two bits to the higher bits */
+       data &= 03;
+       adc_val += data;
+
+       /* Convert ADC value to temperature */
+       ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
+       if (ret == 0)
+               *temp = td_info->curr_temp = curr_temp;
+       return ret;
+}
+
+/**
+ * configure_adc - enables/disables the ADC for conversion
+ * @val: zero: disables the ADC non-zero:enables the ADC
+ *
+ * Enable/Disable the ADC depending on the argument
+ *
+ * Can sleep
+ */
+static int configure_adc(int val)
+{
+       int ret;
+       uint8_t data;
+
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
+       if (ret)
+               return ret;
+
+       if (val) {
+               /* Enable and start the ADC */
+               data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
+       } else {
+               /* Just stop the ADC */
+               data &= (~MSIC_ADC_START);
+       }
+
+       return intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1, data);
+}
+
+/**
+ * set_up_therm_channel - enable thermal channel for conversion
+ * @base_addr: index of free msic ADC channel
+ *
+ * Enable all the three channels for conversion
+ *
+ * Can sleep
+ */
+static int set_up_therm_channel(u16 base_addr)
+{
+       int ret;
+
+       /* Enable all the sensor channels */
+       ret = intel_scu_ipc_iowrite8(base_addr, SKIN_SENSOR0_CODE);
+       if (ret)
+               return ret;
+
+       ret = intel_scu_ipc_iowrite8(base_addr + 1, SKIN_SENSOR1_CODE);
+       if (ret)
+               return ret;
+
+       ret = intel_scu_ipc_iowrite8(base_addr + 2, SYS_SENSOR_CODE);
+       if (ret)
+               return ret;
+
+       /* Since this is the last channel, set the stop bit
+          to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
+       ret = intel_scu_ipc_iowrite8(base_addr + 3,
+                                       (MSIC_DIE_SENSOR_CODE | 0x10));
+       if (ret)
+               return ret;
+
+       /* Enable ADC and start it */
+       return configure_adc(1);
+}
+
+/**
+ * reset_stopbit - sets the stop bit to 0 on the given channel
+ * @addr: address of the channel
+ *
+ * Can sleep
+ */
+static int reset_stopbit(uint16_t addr)
+{
+       int ret;
+       uint8_t data;
+       ret = intel_scu_ipc_ioread8(addr, &data);
+       if (ret)
+               return ret;
+       /* Set the stop bit to zero */
+       return intel_scu_ipc_iowrite8(addr, (data & 0xEF));
+}
+
+/**
+ * find_free_channel - finds an empty channel for conversion
+ *
+ * If the ADC is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds or an error code.
+ *
+ * Context: can sleep
+ *
+ * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
+ * code.
+ */
+static int find_free_channel(void)
+{
+       int ret;
+       int i;
+       uint8_t data;
+
+       /* check whether ADC is enabled */
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
+       if (ret)
+               return ret;
+
+       if ((data & MSIC_ADC_ENBL) == 0)
+               return 0;
+
+       /* ADC is already enabled; Looking for an empty channel */
+       for (i = 0; i < ADC_CHANLS_MAX; i++) {
+               ret = intel_scu_ipc_ioread8(ADC_CHNL_START_ADDR + i, &data);
+               if (ret)
+                       return ret;
+
+               if (data & MSIC_STOPBIT_MASK) {
+                       ret = i;
+                       break;
+               }
+       }
+       return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
+}
+
+/**
+ * mid_initialize_adc - initializing the ADC
+ * @dev: our device structure
+ *
+ * Initialize the ADC for reading thermistor values. Can sleep.
+ */
+static int mid_initialize_adc(struct device *dev)
+{
+       u8  data;
+       u16 base_addr;
+       int ret;
+
+       /*
+        * Ensure that adctherm is disabled before we
+        * initialize the ADC
+        */
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL3, &data);
+       if (ret)
+               return ret;
+
+       if (data & MSIC_ADCTHERM_MASK)
+               dev_warn(dev, "ADCTHERM already set");
+
+       /* Index of the first channel in which the stop bit is set */
+       channel_index = find_free_channel();
+       if (channel_index < 0) {
+               dev_err(dev, "No free ADC channels");
+               return channel_index;
+       }
+
+       base_addr = ADC_CHNL_START_ADDR + channel_index;
+
+       if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
+               /* Reset stop bit for channels other than 0 and 12 */
+               ret = reset_stopbit(base_addr);
+               if (ret)
+                       return ret;
+
+               /* Index of the first free channel */
+               base_addr++;
+               channel_index++;
+       }
+
+       ret = set_up_therm_channel(base_addr);
+       if (ret) {
+               dev_err(dev, "unable to enable ADC");
+               return ret;
+       }
+       dev_dbg(dev, "ADC initialization successful");
+       return ret;
+}
+
+/**
+ * initialize_sensor - sets default temp and timer ranges
+ * @index: index of the sensor
+ *
+ * Context: can sleep
+ */
+static struct thermal_device_info *initialize_sensor(int index)
+{
+       struct thermal_device_info *td_info =
+               kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
+
+       if (!td_info)
+               return NULL;
+
+       /* Set the base addr of the channel for this sensor */
+       td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
+       /* Sensor 3 is direct conversion */
+       if (index == 3)
+               td_info->direct = 1;
+       return td_info;
+}
+
+/**
+ * mid_thermal_resume - resume routine
+ * @pdev: platform device structure
+ *
+ * mid thermal resume: re-initializes the adc. Can sleep.
+ */
+static int mid_thermal_resume(struct platform_device *pdev)
+{
+       return mid_initialize_adc(&pdev->dev);
+}
+
+/**
+ * mid_thermal_suspend - suspend routine
+ * @pdev: platform device structure
+ *
+ * mid thermal suspend implements the suspend functionality
+ * by stopping the ADC. Can sleep.
+ */
+static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       /*
+        * This just stops the ADC and does not disable it.
+        * temporary workaround until we have a generic ADC driver.
+        * If 0 is passed, it disables the ADC.
+        */
+       return configure_adc(0);
+}
+
+/**
+ * read_curr_temp - reads the current temperature and stores in temp
+ * @temp: holds the current temperature value after reading
+ *
+ * Can sleep
+ */
+static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+{
+       WARN_ON(tzd == NULL);
+       return mid_read_temp(tzd, temp);
+}
+
+/* Can't be const */
+static struct thermal_zone_device_ops tzd_ops = {
+       .get_temp = read_curr_temp,
+};
+
+
+/**
+ * mid_thermal_probe - mfld thermal initialize
+ * @pdev: platform device structure
+ *
+ * mid thermal probe initializes the hardware and registers
+ * all the sensors with the generic thermal framework. Can sleep.
+ */
+static int mid_thermal_probe(struct platform_device *pdev)
+{
+       static char *name[MSIC_THERMAL_SENSORS] = {
+               "skin0", "skin1", "sys", "msicdie"
+       };
+
+       int ret;
+       int i;
+       struct platform_info *pinfo;
+
+       pinfo = kzalloc(sizeof(struct platform_info), GFP_KERNEL);
+       if (!pinfo)
+               return -ENOMEM;
+
+       /* Initializing the hardware */
+       ret = mid_initialize_adc(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "ADC init failed");
+               kfree(pinfo);
+               return ret;
+       }
+
+       /* Register each sensor with the generic thermal framework*/
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               pinfo->tzd[i] = thermal_zone_device_register(name[i],
+                                       0, initialize_sensor(i),
+                                       &tzd_ops, 0, 0, 0, 0);
+               if (IS_ERR(pinfo->tzd[i]))
+                       goto reg_fail;
+       }
+
+       pinfo->pdev = pdev;
+       platform_set_drvdata(pdev, pinfo);
+       return 0;
+
+reg_fail:
+       ret = PTR_ERR(pinfo->tzd[i]);
+       while (--i >= 0)
+               thermal_zone_device_unregister(pinfo->tzd[i]);
+       configure_adc(0);
+       kfree(pinfo);
+       return ret;
+}
+
+/**
+ * mid_thermal_remove - mfld thermal finalize
+ * @dev: platform device structure
+ *
+ * MLFD thermal remove unregisters all the sensors from the generic
+ * thermal framework. Can sleep.
+ */
+static int mid_thermal_remove(struct platform_device *pdev)
+{
+       int i;
+       struct platform_info *pinfo = platform_get_drvdata(pdev);
+
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+               thermal_zone_device_unregister(pinfo->tzd[i]);
+
+       platform_set_drvdata(pdev, NULL);
+
+       /* Stop the ADC */
+       return configure_adc(0);
+}
+
+/*********************************************************************
+ *             Driver initialisation and finalization
+ *********************************************************************/
+
+#define DRIVER_NAME "msic_sensor"
+
+static const struct platform_device_id therm_id_table[] = {
+       { DRIVER_NAME, 1 },
+       { }
+};
+
+static struct platform_driver mid_thermal_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = mid_thermal_probe,
+       .suspend = mid_thermal_suspend,
+       .resume = mid_thermal_resume,
+       .remove = __devexit_p(mid_thermal_remove),
+       .id_table = therm_id_table,
+};
+
+static int __init mid_thermal_module_init(void)
+{
+       return platform_driver_register(&mid_thermal_driver);
+}
+
+static void __exit mid_thermal_module_exit(void)
+{
+       platform_driver_unregister(&mid_thermal_driver);
+}
+
+module_init(mid_thermal_module_init);
+module_exit(mid_thermal_module_exit);
+
+MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
+MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
+MODULE_LICENSE("GPL");
index 61433d4928620292f4ab691f4ea455c136768752..d653104b59cb25540d17a85d78f298eea75fd48a 100644 (file)
@@ -257,9 +257,11 @@ static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
        }
 
        for (i = 0; i < 8; i++) {
-               set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip,
-                                       handle_simple_irq, "demux");
-               set_irq_chip_data(i + pg->irq_base, pg);
+               irq_set_chip_and_handler_name(i + pg->irq_base,
+                                             &pmic_irqchip,
+                                             handle_simple_irq,
+                                             "demux");
+               irq_set_chip_data(i + pg->irq_base, pg);
        }
        return 0;
 err:
index 2b11a33325e6a93bf872e67e7d1ab549b98ccc9c..bde47e9080cd9a131dc76563e42d01e273bab990 100644 (file)
@@ -485,7 +485,7 @@ EXPORT_SYMBOL(rar_lock);
  *
  *     The register_rar function is to used by other device drivers
  *     to ensure that this driver is ready. As we cannot be sure of
- *     the compile/execute order of drivers in ther kernel, it is
+ *     the compile/execute order of drivers in the kernel, it is
  *     best to give this driver a callback function to call when
  *     it is ready to give out addresses. The callback function
  *     would have those steps that continue the initialization of
index a91d510a798b2a9e5f2e35c67c369979b273900f..940accbe28d3a2db53c745217bf85f2dd36a1bc0 100644 (file)
@@ -9,7 +9,7 @@
  * as published by the Free Software Foundation; version 2
  * of the License.
  *
- * SCU runing in ARC processor communicates with other entity running in IA
+ * SCU running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad SCU.
  * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
  * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with
index 142d38579314837085930228752ed92adfaf4b0e..23fb2afda00b0c600dd5ca515a85023d7f0b4792 100644 (file)
@@ -51,6 +51,8 @@
  * laptop as MSI S270. YMMV.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -60,6 +62,8 @@
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
 #include <linux/i8042.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define MSI_DRIVER_VERSION "0.5"
 
@@ -78,6 +82,9 @@
 #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS       0x2d
 #define MSI_STANDARD_EC_SCM_LOAD_MASK          (1 << 0)
 
+#define MSI_STANDARD_EC_TOUCHPAD_ADDRESS       0xe4
+#define MSI_STANDARD_EC_TOUCHPAD_MASK          (1 << 4)
+
 static int msi_laptop_resume(struct platform_device *device);
 
 #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
@@ -90,6 +97,14 @@ static int auto_brightness;
 module_param(auto_brightness, int, 0);
 MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
 
+static const struct key_entry msi_laptop_keymap[] = {
+       {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },  /* Touch Pad On */
+       {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },/* Touch Pad On */
+       {KE_END, 0}
+};
+
+static struct input_dev *msi_laptop_input_dev;
+
 static bool old_ec_model;
 static int wlan_s, bluetooth_s, threeg_s;
 static int threeg_exists;
@@ -432,8 +447,7 @@ static struct platform_device *msipf_device;
 
 static int dmi_check_cb(const struct dmi_system_id *id)
 {
-       printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n",
-              id->ident);
+       pr_info("Identified laptop model '%s'.\n", id->ident);
        return 1;
 }
 
@@ -605,6 +619,21 @@ static void msi_update_rfkill(struct work_struct *ignored)
 }
 static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill);
 
+static void msi_send_touchpad_key(struct work_struct *ignored)
+{
+       u8 rdata;
+       int result;
+
+       result = ec_read(MSI_STANDARD_EC_TOUCHPAD_ADDRESS, &rdata);
+       if (result < 0)
+               return;
+
+       sparse_keymap_report_event(msi_laptop_input_dev,
+               (rdata & MSI_STANDARD_EC_TOUCHPAD_MASK) ?
+               KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF, 1, true);
+}
+static DECLARE_DELAYED_WORK(msi_touchpad_work, msi_send_touchpad_key);
+
 static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
                                struct serio *port)
 {
@@ -613,12 +642,17 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
        if (str & 0x20)
                return false;
 
-       /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/
+       /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan, 0xE4 touchpad toggle*/
        if (unlikely(data == 0xe0)) {
                extended = true;
                return false;
        } else if (unlikely(extended)) {
+               extended = false;
                switch (data) {
+               case 0xE4:
+                       schedule_delayed_work(&msi_touchpad_work,
+                               round_jiffies_relative(0.5 * HZ));
+                       break;
                case 0x54:
                case 0x62:
                case 0x76:
@@ -626,7 +660,6 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
                                round_jiffies_relative(0.5 * HZ));
                        break;
                }
-               extended = false;
        }
 
        return false;
@@ -731,6 +764,42 @@ static int msi_laptop_resume(struct platform_device *device)
        return 0;
 }
 
+static int __init msi_laptop_input_setup(void)
+{
+       int err;
+
+       msi_laptop_input_dev = input_allocate_device();
+       if (!msi_laptop_input_dev)
+               return -ENOMEM;
+
+       msi_laptop_input_dev->name = "MSI Laptop hotkeys";
+       msi_laptop_input_dev->phys = "msi-laptop/input0";
+       msi_laptop_input_dev->id.bustype = BUS_HOST;
+
+       err = sparse_keymap_setup(msi_laptop_input_dev,
+               msi_laptop_keymap, NULL);
+       if (err)
+               goto err_free_dev;
+
+       err = input_register_device(msi_laptop_input_dev);
+       if (err)
+               goto err_free_keymap;
+
+       return 0;
+
+err_free_keymap:
+       sparse_keymap_free(msi_laptop_input_dev);
+err_free_dev:
+       input_free_device(msi_laptop_input_dev);
+       return err;
+}
+
+static void msi_laptop_input_destroy(void)
+{
+       sparse_keymap_free(msi_laptop_input_dev);
+       input_unregister_device(msi_laptop_input_dev);
+}
+
 static int load_scm_model_init(struct platform_device *sdev)
 {
        u8 data;
@@ -759,16 +828,23 @@ static int load_scm_model_init(struct platform_device *sdev)
        if (result < 0)
                goto fail_rfkill;
 
+       /* setup input device */
+       result = msi_laptop_input_setup();
+       if (result)
+               goto fail_input;
+
        result = i8042_install_filter(msi_laptop_i8042_filter);
        if (result) {
-               printk(KERN_ERR
-                       "msi-laptop: Unable to install key filter\n");
+               pr_err("Unable to install key filter\n");
                goto fail_filter;
        }
 
        return 0;
 
 fail_filter:
+       msi_laptop_input_destroy();
+
+fail_input:
        rfkill_cleanup();
 
 fail_rfkill:
@@ -799,7 +875,7 @@ static int __init msi_init(void)
        /* Register backlight stuff */
 
        if (acpi_video_backlight_support()) {
-               printk(KERN_INFO "MSI: Brightness ignored, must be controlled "
+               pr_info("Brightness ignored, must be controlled "
                       "by ACPI video driver\n");
        } else {
                struct backlight_properties props;
@@ -854,7 +930,7 @@ static int __init msi_init(void)
        if (auto_brightness != 2)
                set_auto_brightness(auto_brightness);
 
-       printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n");
+       pr_info("driver "MSI_DRIVER_VERSION" successfully loaded.\n");
 
        return 0;
 
@@ -886,6 +962,7 @@ static void __exit msi_cleanup(void)
 {
        if (load_scm_model) {
                i8042_remove_filter(msi_laptop_i8042_filter);
+               msi_laptop_input_destroy();
                cancel_delayed_work_sync(&msi_rfkill_work);
                rfkill_cleanup();
        }
@@ -901,7 +978,7 @@ static void __exit msi_cleanup(void)
        if (auto_brightness != 2)
                set_auto_brightness(1);
 
-       printk(KERN_INFO "msi-laptop: driver unloaded.\n");
+       pr_info("driver unloaded.\n");
 }
 
 module_init(msi_init);
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
new file mode 100644 (file)
index 0000000..de434c6
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * Samsung Laptop driver
+ *
+ * Copyright (C) 2009,2011 Greg Kroah-Hartman (gregkh@suse.de)
+ * Copyright (C) 2009,2011 Novell 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/dmi.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+
+/*
+ * This driver is needed because a number of Samsung laptops do not hook
+ * their control settings through ACPI.  So we have to poke around in the
+ * BIOS to do things like brightness values, and "special" key controls.
+ */
+
+/*
+ * We have 0 - 8 as valid brightness levels.  The specs say that level 0 should
+ * be reserved by the BIOS (which really doesn't make much sense), we tell
+ * userspace that the value is 0 - 7 and then just tell the hardware 1 - 8
+ */
+#define MAX_BRIGHT     0x07
+
+
+#define SABI_IFACE_MAIN                        0x00
+#define SABI_IFACE_SUB                 0x02
+#define SABI_IFACE_COMPLETE            0x04
+#define SABI_IFACE_DATA                        0x05
+
+/* Structure to get data back to the calling function */
+struct sabi_retval {
+       u8 retval[20];
+};
+
+struct sabi_header_offsets {
+       u8 port;
+       u8 re_mem;
+       u8 iface_func;
+       u8 en_mem;
+       u8 data_offset;
+       u8 data_segment;
+};
+
+struct sabi_commands {
+       /*
+        * Brightness is 0 - 8, as described above.
+        * Value 0 is for the BIOS to use
+        */
+       u8 get_brightness;
+       u8 set_brightness;
+
+       /*
+        * first byte:
+        * 0x00 - wireless is off
+        * 0x01 - wireless is on
+        * second byte:
+        * 0x02 - 3G is off
+        * 0x03 - 3G is on
+        * TODO, verify 3G is correct, that doesn't seem right...
+        */
+       u8 get_wireless_button;
+       u8 set_wireless_button;
+
+       /* 0 is off, 1 is on */
+       u8 get_backlight;
+       u8 set_backlight;
+
+       /*
+        * 0x80 or 0x00 - no action
+        * 0x81 - recovery key pressed
+        */
+       u8 get_recovery_mode;
+       u8 set_recovery_mode;
+
+       /*
+        * on seclinux: 0 is low, 1 is high,
+        * on swsmi: 0 is normal, 1 is silent, 2 is turbo
+        */
+       u8 get_performance_level;
+       u8 set_performance_level;
+
+       /*
+        * Tell the BIOS that Linux is running on this machine.
+        * 81 is on, 80 is off
+        */
+       u8 set_linux;
+};
+
+struct sabi_performance_level {
+       const char *name;
+       u8 value;
+};
+
+struct sabi_config {
+       const char *test_string;
+       u16 main_function;
+       const struct sabi_header_offsets header_offsets;
+       const struct sabi_commands commands;
+       const struct sabi_performance_level performance_levels[4];
+       u8 min_brightness;
+       u8 max_brightness;
+};
+
+static const struct sabi_config sabi_configs[] = {
+       {
+               .test_string = "SECLINUX",
+
+               .main_function = 0x4c49,
+
+               .header_offsets = {
+                       .port = 0x00,
+                       .re_mem = 0x02,
+                       .iface_func = 0x03,
+                       .en_mem = 0x04,
+                       .data_offset = 0x05,
+                       .data_segment = 0x07,
+               },
+
+               .commands = {
+                       .get_brightness = 0x00,
+                       .set_brightness = 0x01,
+
+                       .get_wireless_button = 0x02,
+                       .set_wireless_button = 0x03,
+
+                       .get_backlight = 0x04,
+                       .set_backlight = 0x05,
+
+                       .get_recovery_mode = 0x06,
+                       .set_recovery_mode = 0x07,
+
+                       .get_performance_level = 0x08,
+                       .set_performance_level = 0x09,
+
+                       .set_linux = 0x0a,
+               },
+
+               .performance_levels = {
+                       {
+                               .name = "silent",
+                               .value = 0,
+                       },
+                       {
+                               .name = "normal",
+                               .value = 1,
+                       },
+                       { },
+               },
+               .min_brightness = 1,
+               .max_brightness = 8,
+       },
+       {
+               .test_string = "SwSmi@",
+
+               .main_function = 0x5843,
+
+               .header_offsets = {
+                       .port = 0x00,
+                       .re_mem = 0x04,
+                       .iface_func = 0x02,
+                       .en_mem = 0x03,
+                       .data_offset = 0x05,
+                       .data_segment = 0x07,
+               },
+
+               .commands = {
+                       .get_brightness = 0x10,
+                       .set_brightness = 0x11,
+
+                       .get_wireless_button = 0x12,
+                       .set_wireless_button = 0x13,
+
+                       .get_backlight = 0x2d,
+                       .set_backlight = 0x2e,
+
+                       .get_recovery_mode = 0xff,
+                       .set_recovery_mode = 0xff,
+
+                       .get_performance_level = 0x31,
+                       .set_performance_level = 0x32,
+
+                       .set_linux = 0xff,
+               },
+
+               .performance_levels = {
+                       {
+                               .name = "normal",
+                               .value = 0,
+                       },
+                       {
+                               .name = "silent",
+                               .value = 1,
+                       },
+                       {
+                               .name = "overclock",
+                               .value = 2,
+                       },
+                       { },
+               },
+               .min_brightness = 0,
+               .max_brightness = 8,
+       },
+       { },
+};
+
+static const struct sabi_config *sabi_config;
+
+static void __iomem *sabi;
+static void __iomem *sabi_iface;
+static void __iomem *f0000_segment;
+static struct backlight_device *backlight_device;
+static struct mutex sabi_mutex;
+static struct platform_device *sdev;
+static struct rfkill *rfk;
+
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force,
+               "Disable the DMI check and forces the driver to be loaded");
+
+static int debug;
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int sabi_get_command(u8 command, struct sabi_retval *sretval)
+{
+       int retval = 0;
+       u16 port = readw(sabi + sabi_config->header_offsets.port);
+       u8 complete, iface_data;
+
+       mutex_lock(&sabi_mutex);
+
+       /* enable memory to be able to write to it */
+       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+
+       /* write out the command */
+       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
+       writew(command, sabi_iface + SABI_IFACE_SUB);
+       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
+       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+
+       /* write protect memory to make it safe */
+       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+
+       /* see if the command actually succeeded */
+       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+       if (complete != 0xaa || iface_data == 0xff) {
+               pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+                       command, complete, iface_data);
+               retval = -EINVAL;
+               goto exit;
+       }
+       /*
+        * Save off the data into a structure so the caller use it.
+        * Right now we only want the first 4 bytes,
+        * There are commands that need more, but not for the ones we
+        * currently care about.
+        */
+       sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
+       sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
+       sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
+       sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
+
+exit:
+       mutex_unlock(&sabi_mutex);
+       return retval;
+
+}
+
+static int sabi_set_command(u8 command, u8 data)
+{
+       int retval = 0;
+       u16 port = readw(sabi + sabi_config->header_offsets.port);
+       u8 complete, iface_data;
+
+       mutex_lock(&sabi_mutex);
+
+       /* enable memory to be able to write to it */
+       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+
+       /* write out the command */
+       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
+       writew(command, sabi_iface + SABI_IFACE_SUB);
+       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
+       writeb(data, sabi_iface + SABI_IFACE_DATA);
+       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+
+       /* write protect memory to make it safe */
+       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+
+       /* see if the command actually succeeded */
+       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+       if (complete != 0xaa || iface_data == 0xff) {
+               pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+                      command, complete, iface_data);
+               retval = -EINVAL;
+       }
+
+       mutex_unlock(&sabi_mutex);
+       return retval;
+}
+
+static void test_backlight(void)
+{
+       struct sabi_retval sretval;
+
+       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+
+       sabi_set_command(sabi_config->commands.set_backlight, 0);
+       printk(KERN_DEBUG "backlight should be off\n");
+
+       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+
+       msleep(1000);
+
+       sabi_set_command(sabi_config->commands.set_backlight, 1);
+       printk(KERN_DEBUG "backlight should be on\n");
+
+       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+}
+
+static void test_wireless(void)
+{
+       struct sabi_retval sretval;
+
+       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+
+       sabi_set_command(sabi_config->commands.set_wireless_button, 0);
+       printk(KERN_DEBUG "wireless led should be off\n");
+
+       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+
+       msleep(1000);
+
+       sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+       printk(KERN_DEBUG "wireless led should be on\n");
+
+       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+}
+
+static u8 read_brightness(void)
+{
+       struct sabi_retval sretval;
+       int user_brightness = 0;
+       int retval;
+
+       retval = sabi_get_command(sabi_config->commands.get_brightness,
+                                 &sretval);
+       if (!retval) {
+               user_brightness = sretval.retval[0];
+               if (user_brightness != 0)
+                       user_brightness -= sabi_config->min_brightness;
+       }
+       return user_brightness;
+}
+
+static void set_brightness(u8 user_brightness)
+{
+       u8 user_level = user_brightness - sabi_config->min_brightness;
+
+       sabi_set_command(sabi_config->commands.set_brightness, user_level);
+}
+
+static int get_brightness(struct backlight_device *bd)
+{
+       return (int)read_brightness();
+}
+
+static int update_status(struct backlight_device *bd)
+{
+       set_brightness(bd->props.brightness);
+
+       if (bd->props.power == FB_BLANK_UNBLANK)
+               sabi_set_command(sabi_config->commands.set_backlight, 1);
+       else
+               sabi_set_command(sabi_config->commands.set_backlight, 0);
+       return 0;
+}
+
+static const struct backlight_ops backlight_ops = {
+       .get_brightness = get_brightness,
+       .update_status  = update_status,
+};
+
+static int rfkill_set(void *data, bool blocked)
+{
+       /* Do something with blocked...*/
+       /*
+        * blocked == false is on
+        * blocked == true is off
+        */
+       if (blocked)
+               sabi_set_command(sabi_config->commands.set_wireless_button, 0);
+       else
+               sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+
+       return 0;
+}
+
+static struct rfkill_ops rfkill_ops = {
+       .set_block = rfkill_set,
+};
+
+static int init_wireless(struct platform_device *sdev)
+{
+       int retval;
+
+       rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
+                          &rfkill_ops, NULL);
+       if (!rfk)
+               return -ENOMEM;
+
+       retval = rfkill_register(rfk);
+       if (retval) {
+               rfkill_destroy(rfk);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void destroy_wireless(void)
+{
+       rfkill_unregister(rfk);
+       rfkill_destroy(rfk);
+}
+
+static ssize_t get_performance_level(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct sabi_retval sretval;
+       int retval;
+       int i;
+
+       /* Read the state */
+       retval = sabi_get_command(sabi_config->commands.get_performance_level,
+                                 &sretval);
+       if (retval)
+               return retval;
+
+       /* The logic is backwards, yeah, lots of fun... */
+       for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+               if (sretval.retval[0] == sabi_config->performance_levels[i].value)
+                       return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+       }
+       return sprintf(buf, "%s\n", "unknown");
+}
+
+static ssize_t set_performance_level(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       if (count >= 1) {
+               int i;
+               for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+                       const struct sabi_performance_level *level =
+                               &sabi_config->performance_levels[i];
+                       if (!strncasecmp(level->name, buf, strlen(level->name))) {
+                               sabi_set_command(sabi_config->commands.set_performance_level,
+                                                level->value);
+                               break;
+                       }
+               }
+               if (!sabi_config->performance_levels[i].name)
+                       return -EINVAL;
+       }
+       return count;
+}
+static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
+                  get_performance_level, set_performance_level);
+
+
+static int __init dmi_check_cb(const struct dmi_system_id *id)
+{
+       pr_info("found laptop model '%s'\n",
+               id->ident);
+       return 1;
+}
+
+static struct dmi_system_id __initdata samsung_dmi_table[] = {
+       {
+               .ident = "N128",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N128"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "N130",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N130"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "X125",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
+                       DMI_MATCH(DMI_BOARD_NAME, "X125"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "X120/X170",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
+                       DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "NC10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
+                       DMI_MATCH(DMI_BOARD_NAME, "NC10"),
+               },
+               .callback = dmi_check_cb,
+       },
+               {
+               .ident = "NP-Q45",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
+                       DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
+               },
+               .callback = dmi_check_cb,
+               },
+       {
+               .ident = "X360",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
+                       DMI_MATCH(DMI_BOARD_NAME, "X360"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "R518",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
+                       DMI_MATCH(DMI_BOARD_NAME, "R518"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "R519/R719",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
+                       DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "N150/N210/N220",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "N150P/N210P/N220P",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "R530/R730",
+               .matches = {
+                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+                     DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
+                     DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "NF110/NF210/NF310",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+                       DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "N145P/N250P/N260P",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "R70/R71",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
+                       DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
+               },
+               .callback = dmi_check_cb,
+       },
+       {
+               .ident = "P460",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
+                       DMI_MATCH(DMI_BOARD_NAME, "P460"),
+               },
+               .callback = dmi_check_cb,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+       int i = 0;
+       int loca;
+
+       for (loca = 0; loca < 0xffff; loca++) {
+               char temp = readb(memcheck + loca);
+
+               if (temp == testStr[i]) {
+                       if (i == strlen(testStr)-1)
+                               break;
+                       ++i;
+               } else {
+                       i = 0;
+               }
+       }
+       return loca;
+}
+
+static int __init samsung_init(void)
+{
+       struct backlight_properties props;
+       struct sabi_retval sretval;
+       unsigned int ifaceP;
+       int i;
+       int loca;
+       int retval;
+
+       mutex_init(&sabi_mutex);
+
+       if (!force && !dmi_check_system(samsung_dmi_table))
+               return -ENODEV;
+
+       f0000_segment = ioremap_nocache(0xf0000, 0xffff);
+       if (!f0000_segment) {
+               pr_err("Can't map the segment at 0xf0000\n");
+               return -EINVAL;
+       }
+
+       /* Try to find one of the signatures in memory to find the header */
+       for (i = 0; sabi_configs[i].test_string != 0; ++i) {
+               sabi_config = &sabi_configs[i];
+               loca = find_signature(f0000_segment, sabi_config->test_string);
+               if (loca != 0xffff)
+                       break;
+       }
+
+       if (loca == 0xffff) {
+               pr_err("This computer does not support SABI\n");
+               goto error_no_signature;
+       }
+
+       /* point to the SMI port Number */
+       loca += 1;
+       sabi = (f0000_segment + loca);
+
+       if (debug) {
+               printk(KERN_DEBUG "This computer supports SABI==%x\n",
+                       loca + 0xf0000 - 6);
+               printk(KERN_DEBUG "SABI header:\n");
+               printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
+                       readw(sabi + sabi_config->header_offsets.port));
+               printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
+                       readb(sabi + sabi_config->header_offsets.iface_func));
+               printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
+                       readb(sabi + sabi_config->header_offsets.en_mem));
+               printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
+                       readb(sabi + sabi_config->header_offsets.re_mem));
+               printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
+                       readw(sabi + sabi_config->header_offsets.data_offset));
+               printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
+                       readw(sabi + sabi_config->header_offsets.data_segment));
+       }
+
+       /* Get a pointer to the SABI Interface */
+       ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
+       ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
+       sabi_iface = ioremap_nocache(ifaceP, 16);
+       if (!sabi_iface) {
+               pr_err("Can't remap %x\n", ifaceP);
+               goto exit;
+       }
+       if (debug) {
+               printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
+               printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
+
+               test_backlight();
+               test_wireless();
+
+               retval = sabi_get_command(sabi_config->commands.get_brightness,
+                                         &sretval);
+               printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
+       }
+
+       /* Turn on "Linux" mode in the BIOS */
+       if (sabi_config->commands.set_linux != 0xff) {
+               retval = sabi_set_command(sabi_config->commands.set_linux,
+                                         0x81);
+               if (retval) {
+                       pr_warn("Linux mode was not set!\n");
+                       goto error_no_platform;
+               }
+       }
+
+       /* knock up a platform device to hang stuff off of */
+       sdev = platform_device_register_simple("samsung", -1, NULL, 0);
+       if (IS_ERR(sdev))
+               goto error_no_platform;
+
+       /* create a backlight device to talk to this one */
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = sabi_config->max_brightness;
+       backlight_device = backlight_device_register("samsung", &sdev->dev,
+                                                    NULL, &backlight_ops,
+                                                    &props);
+       if (IS_ERR(backlight_device))
+               goto error_no_backlight;
+
+       backlight_device->props.brightness = read_brightness();
+       backlight_device->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(backlight_device);
+
+       retval = init_wireless(sdev);
+       if (retval)
+               goto error_no_rfk;
+
+       retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
+       if (retval)
+               goto error_file_create;
+
+exit:
+       return 0;
+
+error_file_create:
+       destroy_wireless();
+
+error_no_rfk:
+       backlight_device_unregister(backlight_device);
+
+error_no_backlight:
+       platform_device_unregister(sdev);
+
+error_no_platform:
+       iounmap(sabi_iface);
+
+error_no_signature:
+       iounmap(f0000_segment);
+       return -EINVAL;
+}
+
+static void __exit samsung_exit(void)
+{
+       /* Turn off "Linux" mode in the BIOS */
+       if (sabi_config->commands.set_linux != 0xff)
+               sabi_set_command(sabi_config->commands.set_linux, 0x80);
+
+       device_remove_file(&sdev->dev, &dev_attr_performance_level);
+       backlight_device_unregister(backlight_device);
+       destroy_wireless();
+       iounmap(sabi_iface);
+       iounmap(f0000_segment);
+       platform_device_unregister(sdev);
+}
+
+module_init(samsung_init);
+module_exit(samsung_exit);
+
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+MODULE_DESCRIPTION("Samsung Backlight driver");
+MODULE_LICENSE("GPL");
index 13d8d63bcca9ef7cf307860a72f9b94c06466ed8..e642f5f295046edf07f9d16aed5bc26f5dde8731 100644 (file)
@@ -71,8 +71,9 @@
 #endif
 
 #define DRV_PFX                        "sony-laptop: "
-#define dprintk(msg...)                do {                    \
-       if (debug) printk(KERN_WARNING DRV_PFX  msg);   \
+#define dprintk(msg...)                do {    \
+       if (debug)                      \
+               pr_warn(DRV_PFX msg);   \
 } while (0)
 
 #define SONY_LAPTOP_DRIVER_VERSION     "0.6"
@@ -124,6 +125,19 @@ MODULE_PARM_DESC(minor,
                 "default is -1 (automatic)");
 #endif
 
+static int kbd_backlight;      /* = 1 */
+module_param(kbd_backlight, int, 0444);
+MODULE_PARM_DESC(kbd_backlight,
+                "set this to 0 to disable keyboard backlight, "
+                "1 to enable it (default: 0)");
+
+static int kbd_backlight_timeout;      /* = 0 */
+module_param(kbd_backlight_timeout, int, 0444);
+MODULE_PARM_DESC(kbd_backlight_timeout,
+                "set this to 0 to set the default 10 seconds timeout, "
+                "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
+                "(default: 0)");
+
 enum sony_nc_rfkill {
        SONY_WIFI,
        SONY_BLUETOOTH,
@@ -402,7 +416,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
        error = kfifo_alloc(&sony_laptop_input.fifo,
                            SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
        if (error) {
-               printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+               pr_err(DRV_PFX "kfifo_alloc failed\n");
                goto err_dec_users;
        }
 
@@ -591,7 +605,7 @@ struct sony_nc_value {
        int value;              /* current setting */
        int valid;              /* Has ever been set */
        int debug;              /* active only in debug mode ? */
-       struct device_attribute devattr;        /* sysfs atribute */
+       struct device_attribute devattr;        /* sysfs attribute */
 };
 
 #define SNC_HANDLE_NAMES(_name, _values...) \
@@ -686,7 +700,7 @@ static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
                return 0;
        }
 
-       printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n");
+       pr_warn(DRV_PFX "acpi_callreadfunc failed\n");
 
        return -1;
 }
@@ -712,7 +726,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
        if (status == AE_OK) {
                if (result != NULL) {
                        if (out_obj.type != ACPI_TYPE_INTEGER) {
-                               printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad "
+                               pr_warn(DRV_PFX "acpi_evaluate_object bad "
                                       "return type\n");
                                return -1;
                        }
@@ -721,34 +735,103 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
                return 0;
        }
 
-       printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n");
+       pr_warn(DRV_PFX "acpi_evaluate_object failed\n");
 
        return -1;
 }
 
-static int sony_find_snc_handle(int handle)
+struct sony_nc_handles {
+       u16 cap[0x10];
+       struct device_attribute devattr;
+};
+
+static struct sony_nc_handles *handles;
+
+static ssize_t sony_nc_handles_show(struct device *dev,
+               struct device_attribute *attr, char *buffer)
+{
+       ssize_t len = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+               len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
+                               handles->cap[i]);
+       }
+       len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
+
+       return len;
+}
+
+static int sony_nc_handles_setup(struct platform_device *pd)
 {
        int i;
        int result;
 
-       for (i = 0x20; i < 0x30; i++) {
-               acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
-               if (result == handle)
-                       return i-0x20;
+       handles = kzalloc(sizeof(*handles), GFP_KERNEL);
+       if (!handles)
+               return -ENOMEM;
+
+       sysfs_attr_init(&handles->devattr.attr);
+       handles->devattr.attr.name = "handles";
+       handles->devattr.attr.mode = S_IRUGO;
+       handles->devattr.show = sony_nc_handles_show;
+
+       for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+               if (!acpi_callsetfunc(sony_nc_acpi_handle,
+                                       "SN00", i + 0x20, &result)) {
+                       dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
+                                       result, i);
+                       handles->cap[i] = result;
+               }
+       }
+
+       /* allow reading capabilities via sysfs */
+       if (device_create_file(&pd->dev, &handles->devattr)) {
+               kfree(handles);
+               handles = NULL;
+               return -1;
+       }
+
+       return 0;
+}
+
+static int sony_nc_handles_cleanup(struct platform_device *pd)
+{
+       if (handles) {
+               device_remove_file(&pd->dev, &handles->devattr);
+               kfree(handles);
+               handles = NULL;
        }
+       return 0;
+}
 
+static int sony_find_snc_handle(int handle)
+{
+       int i;
+       for (i = 0; i < 0x10; i++) {
+               if (handles->cap[i] == handle) {
+                       dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
+                                       handle, i);
+                       return i;
+               }
+       }
+       dprintk("handle 0x%.4x not found\n", handle);
        return -1;
 }
 
 static int sony_call_snc_handle(int handle, int argument, int *result)
 {
+       int ret = 0;
        int offset = sony_find_snc_handle(handle);
 
        if (offset < 0)
                return -1;
 
-       return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
-                               result);
+       ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
+                       result);
+       dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
+                       *result);
+       return ret;
 }
 
 /*
@@ -857,11 +940,39 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)
        return value - 1;
 }
 
-static struct backlight_device *sony_backlight_device;
+static int sony_nc_get_brightness_ng(struct backlight_device *bd)
+{
+       int result;
+       int *handle = (int *)bl_get_data(bd);
+
+       sony_call_snc_handle(*handle, 0x0200, &result);
+
+       return result & 0xff;
+}
+
+static int sony_nc_update_status_ng(struct backlight_device *bd)
+{
+       int value, result;
+       int *handle = (int *)bl_get_data(bd);
+
+       value = bd->props.brightness;
+       sony_call_snc_handle(*handle, 0x0100 | (value << 16), &result);
+
+       return sony_nc_get_brightness_ng(bd);
+}
+
 static const struct backlight_ops sony_backlight_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
        .update_status = sony_backlight_update_status,
        .get_brightness = sony_backlight_get_brightness,
 };
+static const struct backlight_ops sony_backlight_ng_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = sony_nc_update_status_ng,
+       .get_brightness = sony_nc_get_brightness_ng,
+};
+static int backlight_ng_handle;
+static struct backlight_device *sony_backlight_device;
 
 /*
  * New SNC-only Vaios event mapping to driver known keys
@@ -972,7 +1083,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
                                }
 
                                if (!key_event->data)
-                                       printk(KERN_INFO DRV_PFX
+                                       pr_info(DRV_PFX
                                                        "Unknown event: 0x%x 0x%x\n",
                                                        key_handle,
                                                        ev);
@@ -996,7 +1107,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
        struct acpi_device_info *info;
 
        if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-               printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n",
+               pr_warn(DRV_PFX "method: name: %4.4s, args %X\n",
                        (char *)&info->name, info->param_count);
 
                kfree(info);
@@ -1037,7 +1148,7 @@ static int sony_nc_resume(struct acpi_device *device)
                ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
                                       item->value, NULL);
                if (ret < 0) {
-                       printk("%s: %d\n", __func__, ret);
+                       pr_err(DRV_PFX "%s: %d\n", __func__, ret);
                        break;
                }
        }
@@ -1054,11 +1165,6 @@ static int sony_nc_resume(struct acpi_device *device)
                sony_nc_function_setup(device);
        }
 
-       /* set the last requested brightness level */
-       if (sony_backlight_device &&
-                       sony_backlight_update_status(sony_backlight_device) < 0)
-               printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
-
        /* re-read rfkill state */
        sony_nc_rfkill_update();
 
@@ -1206,12 +1312,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)
 
        device_enum = (union acpi_object *) buffer.pointer;
        if (!device_enum) {
-               pr_err("Invalid SN06 return object\n");
+               pr_err(DRV_PFX "No SN06 return object.");
                goto out_no_enum;
        }
        if (device_enum->type != ACPI_TYPE_BUFFER) {
-               pr_err("Invalid SN06 return object type 0x%.2x\n",
-                      device_enum->type);
+               pr_err(DRV_PFX "Invalid SN06 return object 0x%.2x\n",
+                               device_enum->type);
                goto out_no_enum;
        }
 
@@ -1245,6 +1351,209 @@ out_no_enum:
        return;
 }
 
+/* Keyboard backlight feature */
+#define KBDBL_HANDLER  0x137
+#define KBDBL_PRESENT  0xB00
+#define        SET_MODE        0xC00
+#define SET_TIMEOUT    0xE00
+
+struct kbd_backlight {
+       int mode;
+       int timeout;
+       struct device_attribute mode_attr;
+       struct device_attribute timeout_attr;
+};
+
+static struct kbd_backlight *kbdbl_handle;
+
+static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
+{
+       int result;
+
+       if (value > 1)
+               return -EINVAL;
+
+       if (sony_call_snc_handle(KBDBL_HANDLER,
+                               (value << 0x10) | SET_MODE, &result))
+               return -EIO;
+
+       kbdbl_handle->mode = value;
+
+       return 0;
+}
+
+static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buffer, size_t count)
+{
+       int ret = 0;
+       unsigned long value;
+
+       if (count > 31)
+               return -EINVAL;
+
+       if (strict_strtoul(buffer, 10, &value))
+               return -EINVAL;
+
+       ret = __sony_nc_kbd_backlight_mode_set(value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
+               struct device_attribute *attr, char *buffer)
+{
+       ssize_t count = 0;
+       count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
+       return count;
+}
+
+static int __sony_nc_kbd_backlight_timeout_set(u8 value)
+{
+       int result;
+
+       if (value > 3)
+               return -EINVAL;
+
+       if (sony_call_snc_handle(KBDBL_HANDLER,
+                               (value << 0x10) | SET_TIMEOUT, &result))
+               return -EIO;
+
+       kbdbl_handle->timeout = value;
+
+       return 0;
+}
+
+static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buffer, size_t count)
+{
+       int ret = 0;
+       unsigned long value;
+
+       if (count > 31)
+               return -EINVAL;
+
+       if (strict_strtoul(buffer, 10, &value))
+               return -EINVAL;
+
+       ret = __sony_nc_kbd_backlight_timeout_set(value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
+               struct device_attribute *attr, char *buffer)
+{
+       ssize_t count = 0;
+       count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
+       return count;
+}
+
+static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
+{
+       int result;
+
+       if (sony_call_snc_handle(0x137, KBDBL_PRESENT, &result))
+               return 0;
+       if (!(result & 0x02))
+               return 0;
+
+       kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
+       if (!kbdbl_handle)
+               return -ENOMEM;
+
+       sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
+       kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
+       kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
+       kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
+       kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
+
+       sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
+       kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
+       kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
+       kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
+       kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
+
+       if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
+               goto outkzalloc;
+
+       if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
+               goto outmode;
+
+       __sony_nc_kbd_backlight_mode_set(kbd_backlight);
+       __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
+
+       return 0;
+
+outmode:
+       device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+outkzalloc:
+       kfree(kbdbl_handle);
+       kbdbl_handle = NULL;
+       return -1;
+}
+
+static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
+{
+       if (kbdbl_handle) {
+               device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+               device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
+               kfree(kbdbl_handle);
+       }
+       return 0;
+}
+
+static void sony_nc_backlight_setup(void)
+{
+       acpi_handle unused;
+       int max_brightness = 0;
+       const struct backlight_ops *ops = NULL;
+       struct backlight_properties props;
+
+       if (sony_find_snc_handle(0x12f) != -1) {
+               backlight_ng_handle = 0x12f;
+               ops = &sony_backlight_ng_ops;
+               max_brightness = 0xff;
+
+       } else if (sony_find_snc_handle(0x137) != -1) {
+               backlight_ng_handle = 0x137;
+               ops = &sony_backlight_ng_ops;
+               max_brightness = 0xff;
+
+       } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
+                                               &unused))) {
+               ops = &sony_backlight_ops;
+               max_brightness = SONY_MAX_BRIGHTNESS - 1;
+
+       } else
+               return;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = max_brightness;
+       sony_backlight_device = backlight_device_register("sony", NULL,
+                                                         &backlight_ng_handle,
+                                                         ops, &props);
+
+       if (IS_ERR(sony_backlight_device)) {
+               pr_warning(DRV_PFX "unable to register backlight device\n");
+               sony_backlight_device = NULL;
+       } else
+               sony_backlight_device->props.brightness =
+                   ops->get_brightness(sony_backlight_device);
+}
+
+static void sony_nc_backlight_cleanup(void)
+{
+       if (sony_backlight_device)
+               backlight_device_unregister(sony_backlight_device);
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
        acpi_status status;
@@ -1252,8 +1561,8 @@ static int sony_nc_add(struct acpi_device *device)
        acpi_handle handle;
        struct sony_nc_value *item;
 
-       printk(KERN_INFO DRV_PFX "%s v%s.\n",
-               SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
+       pr_info(DRV_PFX "%s v%s.\n", SONY_NC_DRIVER_NAME,
+                       SONY_LAPTOP_DRIVER_VERSION);
 
        sony_nc_acpi_device = device;
        strcpy(acpi_device_class(device), "sony/hotkey");
@@ -1269,13 +1578,18 @@ static int sony_nc_add(struct acpi_device *device)
                goto outwalk;
        }
 
+       result = sony_pf_add();
+       if (result)
+               goto outpresent;
+
        if (debug) {
-               status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
-                                            1, sony_walk_callback, NULL, NULL, NULL);
+               status = acpi_walk_namespace(ACPI_TYPE_METHOD,
+                               sony_nc_acpi_handle, 1, sony_walk_callback,
+                               NULL, NULL, NULL);
                if (ACPI_FAILURE(status)) {
-                       printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
+                       pr_warn(DRV_PFX "unable to walk acpi resources\n");
                        result = -ENODEV;
-                       goto outwalk;
+                       goto outpresent;
                }
        }
 
@@ -1288,6 +1602,12 @@ static int sony_nc_add(struct acpi_device *device)
        if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
                                         &handle))) {
                dprintk("Doing SNC setup\n");
+               result = sony_nc_handles_setup(sony_pf_device);
+               if (result)
+                       goto outpresent;
+               result = sony_nc_kbd_backlight_setup(sony_pf_device);
+               if (result)
+                       goto outsnc;
                sony_nc_function_setup(device);
                sony_nc_rfkill_setup(device);
        }
@@ -1295,40 +1615,17 @@ static int sony_nc_add(struct acpi_device *device)
        /* setup input devices and helper fifo */
        result = sony_laptop_setup_input(device);
        if (result) {
-               printk(KERN_ERR DRV_PFX
-                               "Unable to create input devices.\n");
-               goto outwalk;
+               pr_err(DRV_PFX "Unable to create input devices.\n");
+               goto outkbdbacklight;
        }
 
        if (acpi_video_backlight_support()) {
-               printk(KERN_INFO DRV_PFX "brightness ignored, must be "
+               pr_info(DRV_PFX "brightness ignored, must be "
                       "controlled by ACPI video driver\n");
-       } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
-                                               &handle))) {
-               struct backlight_properties props;
-               memset(&props, 0, sizeof(struct backlight_properties));
-               props.type = BACKLIGHT_PLATFORM;
-               props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
-               sony_backlight_device = backlight_device_register("sony", NULL,
-                                                                 NULL,
-                                                                 &sony_backlight_ops,
-                                                                 &props);
-
-               if (IS_ERR(sony_backlight_device)) {
-                       printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
-                       sony_backlight_device = NULL;
-               } else {
-                       sony_backlight_device->props.brightness =
-                           sony_backlight_get_brightness
-                           (sony_backlight_device);
-               }
-
+       } else {
+               sony_nc_backlight_setup();
        }
 
-       result = sony_pf_add();
-       if (result)
-               goto outbacklight;
-
        /* create sony_pf sysfs attributes related to the SNC device */
        for (item = sony_nc_values; item->name; ++item) {
 
@@ -1374,14 +1671,19 @@ static int sony_nc_add(struct acpi_device *device)
        for (item = sony_nc_values; item->name; ++item) {
                device_remove_file(&sony_pf_device->dev, &item->devattr);
        }
-       sony_pf_remove();
-
-      outbacklight:
-       if (sony_backlight_device)
-               backlight_device_unregister(sony_backlight_device);
+       sony_nc_backlight_cleanup();
 
        sony_laptop_remove_input();
 
+      outkbdbacklight:
+       sony_nc_kbd_backlight_cleanup(sony_pf_device);
+
+      outsnc:
+       sony_nc_handles_cleanup(sony_pf_device);
+
+      outpresent:
+       sony_pf_remove();
+
       outwalk:
        sony_nc_rfkill_cleanup();
        return result;
@@ -1391,8 +1693,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
 {
        struct sony_nc_value *item;
 
-       if (sony_backlight_device)
-               backlight_device_unregister(sony_backlight_device);
+       sony_nc_backlight_cleanup();
 
        sony_nc_acpi_device = NULL;
 
@@ -1400,6 +1701,8 @@ static int sony_nc_remove(struct acpi_device *device, int type)
                device_remove_file(&sony_pf_device->dev, &item->devattr);
        }
 
+       sony_nc_kbd_backlight_cleanup(sony_pf_device);
+       sony_nc_handles_cleanup(sony_pf_device);
        sony_pf_remove();
        sony_laptop_remove_input();
        sony_nc_rfkill_cleanup();
@@ -1438,7 +1741,6 @@ static struct acpi_driver sony_nc_driver = {
 #define SONYPI_DEVICE_TYPE1    0x00000001
 #define SONYPI_DEVICE_TYPE2    0x00000002
 #define SONYPI_DEVICE_TYPE3    0x00000004
-#define SONYPI_DEVICE_TYPE4    0x00000008
 
 #define SONYPI_TYPE1_OFFSET    0x04
 #define SONYPI_TYPE2_OFFSET    0x12
@@ -1584,8 +1886,8 @@ static struct sonypi_event sonypi_blueev[] = {
 
 /* The set of possible wireless events */
 static struct sonypi_event sonypi_wlessev[] = {
-       { 0x59, SONYPI_EVENT_WIRELESS_ON },
-       { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+       { 0x59, SONYPI_EVENT_IGNORE },
+       { 0x5a, SONYPI_EVENT_IGNORE },
        { 0, 0 }
 };
 
@@ -1842,7 +2144,7 @@ out:
        if (pcidev)
                pci_dev_put(pcidev);
 
-       printk(KERN_INFO DRV_PFX "detected Type%d model\n",
+       pr_info(DRV_PFX "detected Type%d model\n",
                        dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
                        dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
 }
@@ -1890,7 +2192,7 @@ static int __sony_pic_camera_ready(void)
 static int __sony_pic_camera_off(void)
 {
        if (!camera) {
-               printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
+               pr_warn(DRV_PFX "camera control not enabled\n");
                return -ENODEV;
        }
 
@@ -1910,7 +2212,7 @@ static int __sony_pic_camera_on(void)
        int i, j, x;
 
        if (!camera) {
-               printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
+               pr_warn(DRV_PFX "camera control not enabled\n");
                return -ENODEV;
        }
 
@@ -1933,7 +2235,7 @@ static int __sony_pic_camera_on(void)
        }
 
        if (j == 0) {
-               printk(KERN_WARNING DRV_PFX "failed to power on camera\n");
+               pr_warn(DRV_PFX "failed to power on camera\n");
                return -ENODEV;
        }
 
@@ -1989,7 +2291,7 @@ int sony_pic_camera_command(int command, u8 value)
                                ITERATIONS_SHORT);
                break;
        default:
-               printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n",
+               pr_err(DRV_PFX "sony_pic_camera_command invalid: %d\n",
                       command);
                break;
        }
@@ -2396,7 +2698,7 @@ static int sonypi_compat_init(void)
        error =
         kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
        if (error) {
-               printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+               pr_err(DRV_PFX "kfifo_alloc failed\n");
                return error;
        }
 
@@ -2406,11 +2708,11 @@ static int sonypi_compat_init(void)
                sonypi_misc_device.minor = minor;
        error = misc_register(&sonypi_misc_device);
        if (error) {
-               printk(KERN_ERR DRV_PFX "misc_register failed\n");
+               pr_err(DRV_PFX "misc_register failed\n");
                goto err_free_kfifo;
        }
        if (minor == -1)
-               printk(KERN_INFO DRV_PFX "device allocated minor is %d\n",
+               pr_info(DRV_PFX "device allocated minor is %d\n",
                       sonypi_misc_device.minor);
 
        return 0;
@@ -2470,8 +2772,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
                        }
                        for (i = 0; i < p->interrupt_count; i++) {
                                if (!p->interrupts[i]) {
-                                       printk(KERN_WARNING DRV_PFX
-                                                       "Invalid IRQ %d\n",
+                                       pr_warn(DRV_PFX "Invalid IRQ %d\n",
                                                        p->interrupts[i]);
                                        continue;
                                }
@@ -2510,7 +2811,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
                                                ioport->io2.address_length);
                        }
                        else {
-                               printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
+                               pr_err(DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
                                return AE_ERROR;
                        }
                        return AE_OK;
@@ -2538,7 +2839,7 @@ static int sony_pic_possible_resources(struct acpi_device *device)
        dprintk("Evaluating _STA\n");
        result = acpi_bus_get_status(device);
        if (result) {
-               printk(KERN_WARNING DRV_PFX "Unable to read status\n");
+               pr_warn(DRV_PFX "Unable to read status\n");
                goto end;
        }
 
@@ -2554,8 +2855,7 @@ static int sony_pic_possible_resources(struct acpi_device *device)
        status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
                        sony_pic_read_possible_resource, &spic_dev);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING DRV_PFX
-                               "Failure evaluating %s\n",
+               pr_warn(DRV_PFX "Failure evaluating %s\n",
                                METHOD_NAME__PRS);
                result = -ENODEV;
        }
@@ -2669,7 +2969,7 @@ static int sony_pic_enable(struct acpi_device *device,
 
        /* check for total failure */
        if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
+               pr_err(DRV_PFX "Error evaluating _SRS\n");
                result = -ENODEV;
                goto end;
        }
@@ -2725,6 +3025,9 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
                        if (ev == dev->event_types[i].events[j].data) {
                                device_event =
                                        dev->event_types[i].events[j].event;
+                               /* some events may require ignoring */
+                               if (!device_event)
+                                       return IRQ_HANDLED;
                                goto found;
                        }
                }
@@ -2744,7 +3047,6 @@ found:
        sony_laptop_report_input_event(device_event);
        acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
        sonypi_compat_report_event(device_event);
-
        return IRQ_HANDLED;
 }
 
@@ -2759,7 +3061,7 @@ static int sony_pic_remove(struct acpi_device *device, int type)
        struct sony_pic_irq *irq, *tmp_irq;
 
        if (sony_pic_disable(device)) {
-               printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
+               pr_err(DRV_PFX "Couldn't disable device.\n");
                return -ENXIO;
        }
 
@@ -2799,8 +3101,8 @@ static int sony_pic_add(struct acpi_device *device)
        struct sony_pic_ioport *io, *tmp_io;
        struct sony_pic_irq *irq, *tmp_irq;
 
-       printk(KERN_INFO DRV_PFX "%s v%s.\n",
-               SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
+       pr_info(DRV_PFX "%s v%s.\n", SONY_PIC_DRIVER_NAME,
+                       SONY_LAPTOP_DRIVER_VERSION);
 
        spic_dev.acpi_dev = device;
        strcpy(acpi_device_class(device), "sony/hotkey");
@@ -2810,16 +3112,14 @@ static int sony_pic_add(struct acpi_device *device)
        /* read _PRS resources */
        result = sony_pic_possible_resources(device);
        if (result) {
-               printk(KERN_ERR DRV_PFX
-                               "Unable to read possible resources.\n");
+               pr_err(DRV_PFX "Unable to read possible resources.\n");
                goto err_free_resources;
        }
 
        /* setup input devices and helper fifo */
        result = sony_laptop_setup_input(device);
        if (result) {
-               printk(KERN_ERR DRV_PFX
-                               "Unable to create input devices.\n");
+               pr_err(DRV_PFX "Unable to create input devices.\n");
                goto err_free_resources;
        }
 
@@ -2829,7 +3129,7 @@ static int sony_pic_add(struct acpi_device *device)
        /* request io port */
        list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
                if (request_region(io->io1.minimum, io->io1.address_length,
-                                       "Sony Programable I/O Device")) {
+                                       "Sony Programmable I/O Device")) {
                        dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
                                        io->io1.minimum, io->io1.maximum,
                                        io->io1.address_length);
@@ -2837,7 +3137,7 @@ static int sony_pic_add(struct acpi_device *device)
                        if (io->io2.minimum) {
                                if (request_region(io->io2.minimum,
                                                io->io2.address_length,
-                                               "Sony Programable I/O Device")) {
+                                               "Sony Programmable I/O Device")) {
                                        dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
                                                        io->io2.minimum, io->io2.maximum,
                                                        io->io2.address_length);
@@ -2860,7 +3160,7 @@ static int sony_pic_add(struct acpi_device *device)
                }
        }
        if (!spic_dev.cur_ioport) {
-               printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
+               pr_err(DRV_PFX "Failed to request_region.\n");
                result = -ENODEV;
                goto err_remove_compat;
        }
@@ -2880,7 +3180,7 @@ static int sony_pic_add(struct acpi_device *device)
                }
        }
        if (!spic_dev.cur_irq) {
-               printk(KERN_ERR DRV_PFX "Failed to request_irq.\n");
+               pr_err(DRV_PFX "Failed to request_irq.\n");
                result = -ENODEV;
                goto err_release_region;
        }
@@ -2888,7 +3188,7 @@ static int sony_pic_add(struct acpi_device *device)
        /* set resource status _SRS */
        result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
        if (result) {
-               printk(KERN_ERR DRV_PFX "Couldn't enable device.\n");
+               pr_err(DRV_PFX "Couldn't enable device.\n");
                goto err_free_irq;
        }
 
@@ -2997,8 +3297,7 @@ static int __init sony_laptop_init(void)
        if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
                result = acpi_bus_register_driver(&sony_pic_driver);
                if (result) {
-                       printk(KERN_ERR DRV_PFX
-                                       "Unable to register SPIC driver.");
+                       pr_err(DRV_PFX "Unable to register SPIC driver.");
                        goto out;
                }
                spic_drv_registered = 1;
@@ -3006,7 +3305,7 @@ static int __init sony_laptop_init(void)
 
        result = acpi_bus_register_driver(&sony_nc_driver);
        if (result) {
-               printk(KERN_ERR DRV_PFX "Unable to register SNC driver.");
+               pr_err(DRV_PFX "Unable to register SNC driver.");
                goto out_unregister_pic;
        }
 
index 947bdcaa0ce9b624b858ca786c7dffaff410056f..a08561f5349ef038decaf8edcd73528f30f056a9 100644 (file)
@@ -2407,7 +2407,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
         * This code is supposed to duplicate the IBM firmware behaviour:
         * - Pressing MUTE issues mute hotkey message, even when already mute
         * - Pressing Volume up/down issues volume up/down hotkey messages,
-        *   even when already at maximum or minumum volume
+        *   even when already at maximum or minimum volume
         * - The act of unmuting issues volume up/down notification,
         *   depending which key was used to unmute
         *
@@ -2990,7 +2990,7 @@ static void tpacpi_send_radiosw_update(void)
         * rfkill input events, or we will race the rfkill core input
         * handler.
         *
-        * tpacpi_inputdev_send_mutex works as a syncronization point
+        * tpacpi_inputdev_send_mutex works as a synchronization point
         * for the above.
         *
         * We optimize to avoid numerous calls to hotkey_get_wlsw.
diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c
new file mode 100644 (file)
index 0000000..c1372ed
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  OLPC XO-1.5 ebook switch driver
+ *  (based on generic ACPI button driver)
+ *
+ *  Copyright (C) 2009 Paul Fox <pgf@laptop.org>
+ *  Copyright (C) 2010 One Laptop per Child
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define MODULE_NAME "xo15-ebook"
+#define PREFIX MODULE_NAME ": "
+
+#define XO15_EBOOK_CLASS               MODULE_NAME
+#define XO15_EBOOK_TYPE_UNKNOWN        0x00
+#define XO15_EBOOK_NOTIFY_STATUS       0x80
+
+#define XO15_EBOOK_SUBCLASS            "ebook"
+#define XO15_EBOOK_HID                 "XO15EBK"
+#define XO15_EBOOK_DEVICE_NAME         "EBook Switch"
+
+ACPI_MODULE_NAME(MODULE_NAME);
+
+MODULE_DESCRIPTION("OLPC XO-1.5 ebook switch driver");
+MODULE_LICENSE("GPL");
+
+static const struct acpi_device_id ebook_device_ids[] = {
+       { XO15_EBOOK_HID, 0 },
+       { "", 0 },
+};
+MODULE_DEVICE_TABLE(acpi, ebook_device_ids);
+
+struct ebook_switch {
+       struct input_dev *input;
+       char phys[32];                  /* for input device */
+};
+
+static int ebook_send_state(struct acpi_device *device)
+{
+       struct ebook_switch *button = acpi_driver_data(device);
+       unsigned long long state;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "EBK", NULL, &state);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       /* input layer checks if event is redundant */
+       input_report_switch(button->input, SW_TABLET_MODE, !state);
+       input_sync(button->input);
+       return 0;
+}
+
+static void ebook_switch_notify(struct acpi_device *device, u32 event)
+{
+       switch (event) {
+       case ACPI_FIXED_HARDWARE_EVENT:
+       case XO15_EBOOK_NOTIFY_STATUS:
+               ebook_send_state(device);
+               break;
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Unsupported event [0x%x]\n", event));
+               break;
+       }
+}
+
+static int ebook_switch_resume(struct acpi_device *device)
+{
+       return ebook_send_state(device);
+}
+
+static int ebook_switch_add(struct acpi_device *device)
+{
+       struct ebook_switch *button;
+       struct input_dev *input;
+       const char *hid = acpi_device_hid(device);
+       char *name, *class;
+       int error;
+
+       button = kzalloc(sizeof(struct ebook_switch), GFP_KERNEL);
+       if (!button)
+               return -ENOMEM;
+
+       device->driver_data = button;
+
+       button->input = input = input_allocate_device();
+       if (!input) {
+               error = -ENOMEM;
+               goto err_free_button;
+       }
+
+       name = acpi_device_name(device);
+       class = acpi_device_class(device);
+
+       if (strcmp(hid, XO15_EBOOK_HID)) {
+               printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
+               error = -ENODEV;
+               goto err_free_input;
+       }
+
+       strcpy(name, XO15_EBOOK_DEVICE_NAME);
+       sprintf(class, "%s/%s", XO15_EBOOK_CLASS, XO15_EBOOK_SUBCLASS);
+
+       snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
+
+       input->name = name;
+       input->phys = button->phys;
+       input->id.bustype = BUS_HOST;
+       input->dev.parent = &device->dev;
+
+       input->evbit[0] = BIT_MASK(EV_SW);
+       set_bit(SW_TABLET_MODE, input->swbit);
+
+       error = input_register_device(input);
+       if (error)
+               goto err_free_input;
+
+       ebook_send_state(device);
+
+       if (device->wakeup.flags.valid) {
+               /* Button's GPE is run-wake GPE */
+               acpi_enable_gpe(device->wakeup.gpe_device,
+                               device->wakeup.gpe_number);
+               device_set_wakeup_enable(&device->dev, true);
+       }
+
+       return 0;
+
+ err_free_input:
+       input_free_device(input);
+ err_free_button:
+       kfree(button);
+       return error;
+}
+
+static int ebook_switch_remove(struct acpi_device *device, int type)
+{
+       struct ebook_switch *button = acpi_driver_data(device);
+
+       input_unregister_device(button->input);
+       kfree(button);
+       return 0;
+}
+
+static struct acpi_driver xo15_ebook_driver = {
+       .name = MODULE_NAME,
+       .class = XO15_EBOOK_CLASS,
+       .ids = ebook_device_ids,
+       .ops = {
+               .add = ebook_switch_add,
+               .resume = ebook_switch_resume,
+               .remove = ebook_switch_remove,
+               .notify = ebook_switch_notify,
+       },
+};
+
+static int __init xo15_ebook_init(void)
+{
+       return acpi_bus_register_driver(&xo15_ebook_driver);
+}
+
+static void __exit xo15_ebook_exit(void)
+{
+       acpi_bus_unregister_driver(&xo15_ebook_driver);
+}
+
+module_init(xo15_ebook_init);
+module_exit(xo15_ebook_exit);
index 2a9ab89f83b8af99264495663516694fc2afee25..e5ced3a4c1ed9a8ad4b38467cfe199a15e472bc3 100644 (file)
@@ -215,8 +215,8 @@ static int __devinit z2_batt_probe(struct i2c_client *client,
                if (ret)
                        goto err2;
 
-               set_irq_type(gpio_to_irq(info->charge_gpio),
-                               IRQ_TYPE_EDGE_BOTH);
+               irq_set_irq_type(gpio_to_irq(info->charge_gpio),
+                                IRQ_TYPE_EDGE_BOTH);
                ret = request_irq(gpio_to_irq(info->charge_gpio),
                                z2_charge_switch_irq, IRQF_DISABLED,
                                "AC Detect", charger);
index de75f67f4cc3768012007331ac76aa2e28b9e475..b9f29e0d4295b0f1031b151a8e03efde7e974a40 100644 (file)
@@ -126,7 +126,7 @@ config REGULATOR_MAX8998
          and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
 config REGULATOR_TWL4030
-       bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
+       bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
        depends on TWL4030_CORE
        help
          This driver supports the voltage regulators provided by
index 2dec589a89087e8340b1f074c42c7baa866e4c3b..b1d77946e9c64dd69aed6f840fcaf2c685846e92 100644 (file)
@@ -206,29 +206,6 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
                return err;
        }
 
-       /* Per-regulator power on delay from spec */
-       switch (abreg->regreg) {
-       case AB3100_LDO_A: /* Fallthrough */
-       case AB3100_LDO_C: /* Fallthrough */
-       case AB3100_LDO_D: /* Fallthrough */
-       case AB3100_LDO_E: /* Fallthrough */
-       case AB3100_LDO_H: /* Fallthrough */
-       case AB3100_LDO_K:
-               udelay(200);
-               break;
-       case AB3100_LDO_F:
-               udelay(600);
-               break;
-       case AB3100_LDO_G:
-               udelay(400);
-               break;
-       case AB3100_BUCK:
-               mdelay(1);
-               break;
-       default:
-               break;
-       }
-
        return 0;
 }
 
@@ -450,11 +427,37 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
        return abreg->plfdata->external_voltage;
 }
 
+static int ab3100_enable_time_regulator(struct regulator_dev *reg)
+{
+       struct ab3100_regulator *abreg = reg->reg_data;
+
+       /* Per-regulator power on delay from spec */
+       switch (abreg->regreg) {
+       case AB3100_LDO_A: /* Fallthrough */
+       case AB3100_LDO_C: /* Fallthrough */
+       case AB3100_LDO_D: /* Fallthrough */
+       case AB3100_LDO_E: /* Fallthrough */
+       case AB3100_LDO_H: /* Fallthrough */
+       case AB3100_LDO_K:
+               return 200;
+       case AB3100_LDO_F:
+               return 600;
+       case AB3100_LDO_G:
+               return 400;
+       case AB3100_BUCK:
+               return 1000;
+       default:
+               break;
+       }
+       return 0;
+}
+
 static struct regulator_ops regulator_ops_fixed = {
        .enable      = ab3100_enable_regulator,
        .disable     = ab3100_disable_regulator,
        .is_enabled  = ab3100_is_enabled_regulator,
        .get_voltage = ab3100_get_voltage_regulator,
+       .enable_time = ab3100_enable_time_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable = {
@@ -464,6 +467,7 @@ static struct regulator_ops regulator_ops_variable = {
        .get_voltage = ab3100_get_voltage_regulator,
        .set_voltage = ab3100_set_voltage_regulator,
        .list_voltage = ab3100_list_voltage_regulator,
+       .enable_time = ab3100_enable_time_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable_sleepable = {
@@ -474,6 +478,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
        .set_voltage = ab3100_set_voltage_regulator,
        .set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
        .list_voltage = ab3100_list_voltage_regulator,
+       .enable_time = ab3100_enable_time_regulator,
 };
 
 /*
index d9a052c53aec2d8d9ed958026748c886dc3c0aad..02f3c2333c8374d81f3bec3a1e2fb714f4c71095 100644 (file)
@@ -9,7 +9,7 @@
  * AB8500 peripheral regulators
  *
  * AB8500 supports the following regulators:
- *   VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA
+ *   VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -38,6 +38,7 @@
  * @voltage_mask: mask to control regulator voltage
  * @voltages: supported voltage table
  * @voltages_len: number of supported voltages for the regulator
+ * @delay: startup/set voltage delay in us
  */
 struct ab8500_regulator_info {
        struct device           *dev;
@@ -55,6 +56,7 @@ struct ab8500_regulator_info {
        u8 voltage_mask;
        int const *voltages;
        int voltages_len;
+       unsigned int delay;
 };
 
 /* voltage tables for the vauxn/vintcore supplies */
@@ -290,6 +292,29 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
        return ret;
 }
 
+static int ab8500_regulator_enable_time(struct regulator_dev *rdev)
+{
+       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+       return info->delay;
+}
+
+static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                            unsigned int old_sel,
+                                            unsigned int new_sel)
+{
+       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+       int ret;
+
+       /* If the regulator isn't on, it won't take time here */
+       ret = ab8500_regulator_is_enabled(rdev);
+       if (ret < 0)
+               return ret;
+       if (!ret)
+               return 0;
+       return info->delay;
+}
+
 static struct regulator_ops ab8500_regulator_ops = {
        .enable         = ab8500_regulator_enable,
        .disable        = ab8500_regulator_disable,
@@ -297,6 +322,8 @@ static struct regulator_ops ab8500_regulator_ops = {
        .get_voltage    = ab8500_regulator_get_voltage,
        .set_voltage    = ab8500_regulator_set_voltage,
        .list_voltage   = ab8500_list_voltage,
+       .enable_time    = ab8500_regulator_enable_time,
+       .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
@@ -317,6 +344,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = {
        .is_enabled     = ab8500_regulator_is_enabled,
        .get_voltage    = ab8500_fixed_get_voltage,
        .list_voltage   = ab8500_list_voltage,
+       .enable_time    = ab8500_regulator_enable_time,
+       .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static struct ab8500_regulator_info
@@ -426,12 +455,28 @@ static struct ab8500_regulator_info
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
                },
+               .delay                  = 10000,
                .fixed_uV               = 2000000,
                .update_bank            = 0x03,
                .update_reg             = 0x80,
                .update_mask            = 0x82,
                .update_val_enable      = 0x02,
        },
+       [AB8500_LDO_USB] = {
+               .desc = {
+                       .name           = "LDO-USB",
+                       .ops            = &ab8500_regulator_fixed_ops,
+                       .type           = REGULATOR_VOLTAGE,
+                       .id             = AB8500_LDO_USB,
+                       .owner          = THIS_MODULE,
+                       .n_voltages     = 1,
+               },
+               .fixed_uV               = 3300000,
+               .update_bank            = 0x03,
+               .update_reg             = 0x82,
+               .update_mask            = 0x03,
+               .update_val_enable      = 0x01,
+       },
        [AB8500_LDO_AUDIO] = {
                .desc = {
                        .name           = "LDO-AUDIO",
@@ -511,6 +556,186 @@ static struct ab8500_regulator_info
 
 };
 
+struct ab8500_reg_init {
+       u8 bank;
+       u8 addr;
+       u8 mask;
+};
+
+#define REG_INIT(_id, _bank, _addr, _mask)     \
+       [_id] = {                               \
+               .bank = _bank,                  \
+               .addr = _addr,                  \
+               .mask = _mask,                  \
+       }
+
+static struct ab8500_reg_init ab8500_reg_init[] = {
+       /*
+        * 0x30, VanaRequestCtrl
+        * 0x0C, VpllRequestCtrl
+        * 0xc0, VextSupply1RequestCtrl
+        */
+       REG_INIT(AB8500_REGUREQUESTCTRL2,       0x03, 0x04, 0xfc),
+       /*
+        * 0x03, VextSupply2RequestCtrl
+        * 0x0c, VextSupply3RequestCtrl
+        * 0x30, Vaux1RequestCtrl
+        * 0xc0, Vaux2RequestCtrl
+        */
+       REG_INIT(AB8500_REGUREQUESTCTRL3,       0x03, 0x05, 0xff),
+       /*
+        * 0x03, Vaux3RequestCtrl
+        * 0x04, SwHPReq
+        */
+       REG_INIT(AB8500_REGUREQUESTCTRL4,       0x03, 0x06, 0x07),
+       /*
+        * 0x08, VanaSysClkReq1HPValid
+        * 0x20, Vaux1SysClkReq1HPValid
+        * 0x40, Vaux2SysClkReq1HPValid
+        * 0x80, Vaux3SysClkReq1HPValid
+        */
+       REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xe8),
+       /*
+        * 0x10, VextSupply1SysClkReq1HPValid
+        * 0x20, VextSupply2SysClkReq1HPValid
+        * 0x40, VextSupply3SysClkReq1HPValid
+        */
+       REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x70),
+       /*
+        * 0x08, VanaHwHPReq1Valid
+        * 0x20, Vaux1HwHPReq1Valid
+        * 0x40, Vaux2HwHPReq1Valid
+        * 0x80, Vaux3HwHPReq1Valid
+        */
+       REG_INIT(AB8500_REGUHWHPREQ1VALID1,     0x03, 0x09, 0xe8),
+       /*
+        * 0x01, VextSupply1HwHPReq1Valid
+        * 0x02, VextSupply2HwHPReq1Valid
+        * 0x04, VextSupply3HwHPReq1Valid
+        */
+       REG_INIT(AB8500_REGUHWHPREQ1VALID2,     0x03, 0x0a, 0x07),
+       /*
+        * 0x08, VanaHwHPReq2Valid
+        * 0x20, Vaux1HwHPReq2Valid
+        * 0x40, Vaux2HwHPReq2Valid
+        * 0x80, Vaux3HwHPReq2Valid
+        */
+       REG_INIT(AB8500_REGUHWHPREQ2VALID1,     0x03, 0x0b, 0xe8),
+       /*
+        * 0x01, VextSupply1HwHPReq2Valid
+        * 0x02, VextSupply2HwHPReq2Valid
+        * 0x04, VextSupply3HwHPReq2Valid
+        */
+       REG_INIT(AB8500_REGUHWHPREQ2VALID2,     0x03, 0x0c, 0x07),
+       /*
+        * 0x20, VanaSwHPReqValid
+        * 0x80, Vaux1SwHPReqValid
+        */
+       REG_INIT(AB8500_REGUSWHPREQVALID1,      0x03, 0x0d, 0xa0),
+       /*
+        * 0x01, Vaux2SwHPReqValid
+        * 0x02, Vaux3SwHPReqValid
+        * 0x04, VextSupply1SwHPReqValid
+        * 0x08, VextSupply2SwHPReqValid
+        * 0x10, VextSupply3SwHPReqValid
+        */
+       REG_INIT(AB8500_REGUSWHPREQVALID2,      0x03, 0x0e, 0x1f),
+       /*
+        * 0x02, SysClkReq2Valid1
+        * ...
+        * 0x80, SysClkReq8Valid1
+        */
+       REG_INIT(AB8500_REGUSYSCLKREQVALID1,    0x03, 0x0f, 0xfe),
+       /*
+        * 0x02, SysClkReq2Valid2
+        * ...
+        * 0x80, SysClkReq8Valid2
+        */
+       REG_INIT(AB8500_REGUSYSCLKREQVALID2,    0x03, 0x10, 0xfe),
+       /*
+        * 0x02, VTVoutEna
+        * 0x04, Vintcore12Ena
+        * 0x38, Vintcore12Sel
+        * 0x40, Vintcore12LP
+        * 0x80, VTVoutLP
+        */
+       REG_INIT(AB8500_REGUMISC1,              0x03, 0x80, 0xfe),
+       /*
+        * 0x02, VaudioEna
+        * 0x04, VdmicEna
+        * 0x08, Vamic1Ena
+        * 0x10, Vamic2Ena
+        */
+       REG_INIT(AB8500_VAUDIOSUPPLY,           0x03, 0x83, 0x1e),
+       /*
+        * 0x01, Vamic1_dzout
+        * 0x02, Vamic2_dzout
+        */
+       REG_INIT(AB8500_REGUCTRL1VAMIC,         0x03, 0x84, 0x03),
+       /*
+        * 0x0c, VanaRegu
+        * 0x03, VpllRegu
+        */
+       REG_INIT(AB8500_VPLLVANAREGU,           0x04, 0x06, 0x0f),
+       /*
+        * 0x01, VrefDDREna
+        * 0x02, VrefDDRSleepMode
+        */
+       REG_INIT(AB8500_VREFDDR,                0x04, 0x07, 0x03),
+       /*
+        * 0x03, VextSupply1Regu
+        * 0x0c, VextSupply2Regu
+        * 0x30, VextSupply3Regu
+        * 0x40, ExtSupply2Bypass
+        * 0x80, ExtSupply3Bypass
+        */
+       REG_INIT(AB8500_EXTSUPPLYREGU,          0x04, 0x08, 0xff),
+       /*
+        * 0x03, Vaux1Regu
+        * 0x0c, Vaux2Regu
+        */
+       REG_INIT(AB8500_VAUX12REGU,             0x04, 0x09, 0x0f),
+       /*
+        * 0x03, Vaux3Regu
+        */
+       REG_INIT(AB8500_VRF1VAUX3REGU,          0x04, 0x0a, 0x03),
+       /*
+        * 0x3f, Vsmps1Sel1
+        */
+       REG_INIT(AB8500_VSMPS1SEL1,             0x04, 0x13, 0x3f),
+       /*
+        * 0x0f, Vaux1Sel
+        */
+       REG_INIT(AB8500_VAUX1SEL,               0x04, 0x1f, 0x0f),
+       /*
+        * 0x0f, Vaux2Sel
+        */
+       REG_INIT(AB8500_VAUX2SEL,               0x04, 0x20, 0x0f),
+       /*
+        * 0x07, Vaux3Sel
+        */
+       REG_INIT(AB8500_VRF1VAUX3SEL,           0x04, 0x21, 0x07),
+       /*
+        * 0x01, VextSupply12LP
+        */
+       REG_INIT(AB8500_REGUCTRL2SPARE,         0x04, 0x22, 0x01),
+       /*
+        * 0x04, Vaux1Disch
+        * 0x08, Vaux2Disch
+        * 0x10, Vaux3Disch
+        * 0x20, Vintcore12Disch
+        * 0x40, VTVoutDisch
+        * 0x80, VaudioDisch
+        */
+       REG_INIT(AB8500_REGUCTRLDISCH,          0x04, 0x43, 0xfc),
+       /*
+        * 0x02, VanaDisch
+        * 0x04, VdmicPullDownEna
+        * 0x10, VdmicDisch
+        */
+       REG_INIT(AB8500_REGUCTRLDISCH2,         0x04, 0x44, 0x16),
+};
+
 static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
@@ -529,10 +754,51 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
 
        /* make sure the platform data has the correct size */
        if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
-               dev_err(&pdev->dev, "platform configuration error\n");
+               dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
                return -EINVAL;
        }
 
+       /* initialize registers */
+       for (i = 0; i < pdata->num_regulator_reg_init; i++) {
+               int id;
+               u8 value;
+
+               id = pdata->regulator_reg_init[i].id;
+               value = pdata->regulator_reg_init[i].value;
+
+               /* check for configuration errors */
+               if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
+                       dev_err(&pdev->dev,
+                               "Configuration error: id outside range.\n");
+                       return -EINVAL;
+               }
+               if (value & ~ab8500_reg_init[id].mask) {
+                       dev_err(&pdev->dev,
+                               "Configuration error: value outside mask.\n");
+                       return -EINVAL;
+               }
+
+               /* initialize register */
+               err = abx500_mask_and_set_register_interruptible(&pdev->dev,
+                       ab8500_reg_init[id].bank,
+                       ab8500_reg_init[id].addr,
+                       ab8500_reg_init[id].mask,
+                       value);
+               if (err < 0) {
+                       dev_err(&pdev->dev,
+                               "Failed to initialize 0x%02x, 0x%02x.\n",
+                               ab8500_reg_init[id].bank,
+                               ab8500_reg_init[id].addr);
+                       return err;
+               }
+               dev_vdbg(&pdev->dev,
+                       "  init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+                       ab8500_reg_init[id].bank,
+                       ab8500_reg_init[id].addr,
+                       ab8500_reg_init[id].mask,
+                       value);
+       }
+
        /* register all regulators */
        for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
                struct ab8500_regulator_info *info = NULL;
index 9fa20957847dbe3e0f44cac292a49e0a35133de3..3ffc6979d164e820e4218420449e8a22f51700db 100644 (file)
@@ -1629,6 +1629,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV)
 {
        int ret;
+       int delay = 0;
        unsigned int selector;
 
        trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
@@ -1662,6 +1663,22 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                        }
                }
 
+               /*
+                * If we can't obtain the old selector there is not enough
+                * info to call set_voltage_time_sel().
+                */
+               if (rdev->desc->ops->set_voltage_time_sel &&
+                   rdev->desc->ops->get_voltage_sel) {
+                       unsigned int old_selector = 0;
+
+                       ret = rdev->desc->ops->get_voltage_sel(rdev);
+                       if (ret < 0)
+                               return ret;
+                       old_selector = ret;
+                       delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+                                               old_selector, selector);
+               }
+
                if (best_val != INT_MAX) {
                        ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
                        selector = best_val;
@@ -1672,6 +1689,14 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                ret = -EINVAL;
        }
 
+       /* Insert any necessary delays */
+       if (delay >= 1000) {
+               mdelay(delay / 1000);
+               udelay(delay % 1000);
+       } else if (delay) {
+               udelay(delay);
+       }
+
        if (ret == 0)
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
                                     NULL);
@@ -1739,6 +1764,51 @@ out:
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
+/**
+ * regulator_set_voltage_time - get raise/fall time
+ * @regulator: regulator source
+ * @old_uV: starting voltage in microvolts
+ * @new_uV: target voltage in microvolts
+ *
+ * Provided with the starting and ending voltage, this function attempts to
+ * calculate the time in microseconds required to rise or fall to this new
+ * voltage.
+ */
+int regulator_set_voltage_time(struct regulator *regulator,
+                              int old_uV, int new_uV)
+{
+       struct regulator_dev    *rdev = regulator->rdev;
+       struct regulator_ops    *ops = rdev->desc->ops;
+       int old_sel = -1;
+       int new_sel = -1;
+       int voltage;
+       int i;
+
+       /* Currently requires operations to do this */
+       if (!ops->list_voltage || !ops->set_voltage_time_sel
+           || !rdev->desc->n_voltages)
+               return -EINVAL;
+
+       for (i = 0; i < rdev->desc->n_voltages; i++) {
+               /* We only look for exact voltage matches here */
+               voltage = regulator_list_voltage(regulator, i);
+               if (voltage < 0)
+                       return -EINVAL;
+               if (voltage == 0)
+                       continue;
+               if (voltage == old_uV)
+                       old_sel = i;
+               if (voltage == new_uV)
+                       new_sel = i;
+       }
+
+       if (old_sel < 0 || new_sel < 0)
+               return -EINVAL;
+
+       return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
+
 /**
  * regulator_sync_voltage - re-apply last regulator output voltage
  * @regulator: regulator source
@@ -2565,8 +2635,11 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                        init_data->consumer_supplies[i].dev,
                        init_data->consumer_supplies[i].dev_name,
                        init_data->consumer_supplies[i].supply);
-               if (ret < 0)
+               if (ret < 0) {
+                       dev_err(dev, "Failed to set supply %s\n",
+                               init_data->consumer_supplies[i].supply);
                        goto unset_supplies;
+               }
        }
 
        list_add(&rdev->list, &regulator_list);
@@ -2652,6 +2725,47 @@ out:
 }
 EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
 
+/**
+ * regulator_suspend_finish - resume regulators from system wide suspend
+ *
+ * Turn on regulators that might be turned off by regulator_suspend_prepare
+ * and that should be turned on according to the regulators properties.
+ */
+int regulator_suspend_finish(void)
+{
+       struct regulator_dev *rdev;
+       int ret = 0, error;
+
+       mutex_lock(&regulator_list_mutex);
+       list_for_each_entry(rdev, &regulator_list, list) {
+               struct regulator_ops *ops = rdev->desc->ops;
+
+               mutex_lock(&rdev->mutex);
+               if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
+                               ops->enable) {
+                       error = ops->enable(rdev);
+                       if (error)
+                               ret = error;
+               } else {
+                       if (!has_full_constraints)
+                               goto unlock;
+                       if (!ops->disable)
+                               goto unlock;
+                       if (ops->is_enabled && !ops->is_enabled(rdev))
+                               goto unlock;
+
+                       error = ops->disable(rdev);
+                       if (error)
+                               ret = error;
+               }
+unlock:
+               mutex_unlock(&rdev->mutex);
+       }
+       mutex_unlock(&regulator_list_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_suspend_finish);
+
 /**
  * regulator_has_full_constraints - the system has fully specified constraints
  *
index 01ef7e9903bb8b9bd7080bef89f5e266c36f1671..77e0cfb30b23fcc5ff274cf66ac96b94a532a62d 100644 (file)
@@ -1185,6 +1185,7 @@ static const struct platform_device_id max8997_pmic_id[] = {
        { "max8997-pmic", 0},
        { },
 };
+MODULE_DEVICE_TABLE(platform, max8997_pmic_id);
 
 static struct platform_driver max8997_pmic_driver = {
        .driver = {
index 0ec49ca527a84de2f16b3eb8ab14bfe70df05e11..43410266f9938e4b3f8cc08a51250d860cf0ccba 100644 (file)
@@ -887,6 +887,7 @@ static const struct platform_device_id max8998_pmic_id[] = {
        { "lp3974-pmic", TYPE_LP3974 },
        { }
 };
+MODULE_DEVICE_TABLE(platform, max8998_pmic_id);
 
 static struct platform_driver max8998_pmic_driver = {
        .driver = {
index 176a6be5a8ce20c733d241805c6b7698c5c7c494..9166aa0a9df71c582425d89a7d6517bd22f01072 100644 (file)
@@ -596,7 +596,7 @@ static struct regulator_ops regulator_ops = {
        .get_current_limit      = get_current_limit,
 };
 
-static int __devexit pmic_remove(struct spi_device *spi)
+static int pmic_remove(struct spi_device *spi)
 {
        struct tps6524x *hw = spi_get_drvdata(spi);
        int i;
index 06df898842c0026ae63a86641d8aa067271ff649..e93453b1b9788020646ca8e1a81964567d99710d 100644 (file)
@@ -565,9 +565,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "UV");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-                                IRQF_TRIGGER_RISING, dcdc->name,
-                                dcdc);
+       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
@@ -575,9 +574,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "HC");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_oc_irq,
-                                IRQF_TRIGGER_RISING, dcdc->name,
-                                dcdc);
+       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
+                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
                        irq, ret);
@@ -589,7 +587,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        return 0;
 
 err_uv:
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+       free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
 err_regulator:
        regulator_unregister(dcdc->regulator);
 err:
@@ -606,8 +604,8 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+       free_irq(platform_get_irq_byname(pdev, "HC"), dcdc);
+       free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
        regulator_unregister(dcdc->regulator);
        if (dcdc->dvs_gpio)
                gpio_free(dcdc->dvs_gpio);
@@ -756,9 +754,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "UV");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-                                IRQF_TRIGGER_RISING, dcdc->name,
-                                dcdc);
+       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
@@ -783,7 +780,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+       free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
        regulator_unregister(dcdc->regulator);
        kfree(dcdc);
 
@@ -885,9 +882,9 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "UV");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-                                IRQF_TRIGGER_RISING, dcdc->name,
-                                dcdc);
+       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+                                  IRQF_TRIGGER_RISING, dcdc->name,
+                                  dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
@@ -908,11 +905,10 @@ err:
 static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = dcdc->wm831x;
 
        platform_set_drvdata(pdev, NULL);
 
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+       free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
        regulator_unregister(dcdc->regulator);
        kfree(dcdc);
 
index 6c446cd6ad546839aa455d2302fff558921ea3c3..01f27c7f4236bca00615e2f4521126f3ce87b702 100644 (file)
@@ -198,9 +198,8 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
-       ret = wm831x_request_irq(wm831x, irq, wm831x_isink_irq,
-                                IRQF_TRIGGER_RISING, isink->name,
-                                isink);
+       ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
+                                  IRQF_TRIGGER_RISING, isink->name, isink);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
                        irq, ret);
@@ -221,11 +220,10 @@ err:
 static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 {
        struct wm831x_isink *isink = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = isink->wm831x;
 
        platform_set_drvdata(pdev, NULL);
 
-       wm831x_free_irq(wm831x, platform_get_irq(pdev, 0), isink);
+       free_irq(platform_get_irq(pdev, 0), isink);
 
        regulator_unregister(isink->regulator);
        kfree(isink);
index c94fc5b7cd5b8ab22ef64129a7118e53f2380091..2220cf8defb1625a1c161f026cf5722fd7356ea2 100644 (file)
@@ -354,9 +354,9 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "UV");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_ldo_uv_irq,
-                                IRQF_TRIGGER_RISING, ldo->name,
-                                ldo);
+       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
+                                  IRQF_TRIGGER_RISING, ldo->name,
+                                  ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
@@ -377,11 +377,10 @@ err:
 static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = ldo->wm831x;
 
        platform_set_drvdata(pdev, NULL);
 
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
+       free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
        regulator_unregister(ldo->regulator);
        kfree(ldo);
 
@@ -619,9 +618,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq_byname(pdev, "UV");
-       ret = wm831x_request_irq(wm831x, irq, wm831x_ldo_uv_irq,
-                                IRQF_TRIGGER_RISING, ldo->name,
-                                ldo);
+       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
+                                  IRQF_TRIGGER_RISING, ldo->name, ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
@@ -642,9 +640,8 @@ err:
 static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = ldo->wm831x;
 
-       wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
+       free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
        regulator_unregister(ldo->regulator);
        kfree(ldo);
 
index e55dc1ac83ab5bd229093a786ba08544bef73d5d..6ac55fd48413f8c91ec20653738f5b454cf38281 100644 (file)
@@ -782,11 +782,11 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
        struct platform_device *pdev = to_platform_device(dev);
        struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
-       set_irq_wake(rtc->periodic_irq, enabled);
+       irq_set_irq_wake(rtc->periodic_irq, enabled);
 
        if (rtc->carry_irq > 0) {
-               set_irq_wake(rtc->carry_irq, enabled);
-               set_irq_wake(rtc->alarm_irq, enabled);
+               irq_set_irq_wake(rtc->carry_irq, enabled);
+               irq_set_irq_wake(rtc->alarm_irq, enabled);
        }
 }
 
index 5833afbf08d705899258463f3b772134557dc7a0..c6ca115c71dfc57babfe3804494729d14f078b79 100644 (file)
@@ -63,7 +63,7 @@ void intc_set_prio_level(unsigned int irq, unsigned int level)
 
 static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
 {
-       generic_handle_irq((unsigned int)get_irq_data(irq));
+       generic_handle_irq((unsigned int)irq_get_handler_data(irq));
 }
 
 static void __init intc_register_irq(struct intc_desc *desc,
@@ -116,9 +116,9 @@ static void __init intc_register_irq(struct intc_desc *desc,
        irq_data = irq_get_irq_data(irq);
 
        disable_irq_nosync(irq);
-       set_irq_chip_and_handler_name(irq, &d->chip,
-                                     handle_level_irq, "level");
-       set_irq_chip_data(irq, (void *)data[primary]);
+       irq_set_chip_and_handler_name(irq, &d->chip, handle_level_irq,
+                                     "level");
+       irq_set_chip_data(irq, (void *)data[primary]);
 
        /*
         * set priority level
@@ -340,9 +340,9 @@ int __init register_intc_controller(struct intc_desc *desc)
                        vect2->enum_id = 0;
 
                        /* redirect this interrupts to the first one */
-                       set_irq_chip(irq2, &dummy_irq_chip);
-                       set_irq_chained_handler(irq2, intc_redirect_irq);
-                       set_irq_data(irq2, (void *)irq);
+                       irq_set_chip(irq2, &dummy_irq_chip);
+                       irq_set_chained_handler(irq2, intc_redirect_irq);
+                       irq_set_handler_data(irq2, (void *)irq);
                }
        }
 
@@ -387,19 +387,16 @@ static int intc_suspend(void)
                /* enable wakeup irqs belonging to this intc controller */
                for_each_active_irq(irq) {
                        struct irq_data *data;
-                       struct irq_desc *desc;
                        struct irq_chip *chip;
 
                        data = irq_get_irq_data(irq);
                        chip = irq_data_get_irq_chip(data);
                        if (chip != &d->chip)
                                continue;
-                       desc = irq_to_desc(irq);
-                       if ((desc->status & IRQ_WAKEUP))
+                       if (irqd_is_wakeup_set(data))
                                chip->irq_enable(data);
                }
        }
-
        return 0;
 }
 
@@ -412,7 +409,6 @@ static void intc_resume(void)
 
                for_each_active_irq(irq) {
                        struct irq_data *data;
-                       struct irq_desc *desc;
                        struct irq_chip *chip;
 
                        data = irq_get_irq_data(irq);
@@ -423,8 +419,7 @@ static void intc_resume(void)
                         */
                        if (chip != &d->chip)
                                continue;
-                       desc = irq_to_desc(irq);
-                       if (desc->status & IRQ_DISABLED)
+                       if (irqd_irq_disabled(data))
                                chip->irq_disable(data);
                        else
                                chip->irq_enable(data);
index 4e0ff7181164c34eb603cd1b03e7633e34f681b3..ce5f81d7cc6b859a7301c1929a127498e516ce58 100644 (file)
@@ -110,7 +110,7 @@ static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_data *data = irq_get_irq_data(irq);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
-       struct intc_virq_list *entry, *vlist = irq_data_get_irq_data(data);
+       struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data);
        struct intc_desc_int *d = get_intc_desc(irq);
 
        chip->irq_mask_ack(data);
@@ -118,7 +118,7 @@ static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
        for_each_virq(entry, vlist) {
                unsigned long addr, handle;
 
-               handle = (unsigned long)get_irq_data(entry->irq);
+               handle = (unsigned long)irq_get_handler_data(entry->irq);
                addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
 
                if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
@@ -229,13 +229,13 @@ restart:
 
                intc_irq_xlate_set(irq, entry->enum_id, d);
 
-               set_irq_chip_and_handler_name(irq, get_irq_chip(entry->pirq),
+               irq_set_chip_and_handler_name(irq, irq_get_chip(entry->pirq),
                                              handle_simple_irq, "virq");
-               set_irq_chip_data(irq, get_irq_chip_data(entry->pirq));
+               irq_set_chip_data(irq, irq_get_chip_data(entry->pirq));
 
-               set_irq_data(irq, (void *)entry->handle);
+               irq_set_handler_data(irq, (void *)entry->handle);
 
-               set_irq_chained_handler(entry->pirq, intc_virq_handler);
+               irq_set_chained_handler(entry->pirq, intc_virq_handler);
                add_virq_to_pirq(entry->pirq, irq);
 
                radix_tree_tag_clear(&d->tree, entry->enum_id,
index e3556ff43bb9a0cb1412f356a3ce923e1dad234e..ac5bbc8722e5ac586d5a7d6af361bc0c343e5b56 100644 (file)
@@ -341,7 +341,7 @@ int bcmsdh_register_oob_intr(void *dhdp)
                if (error)
                        return -ENODEV;
 
-               set_irq_wake(sdhcinfo->oob_irq, 1);
+               irq_set_irq_wake(sdhcinfo->oob_irq, 1);
                sdhcinfo->oob_irq_registered = true;
        }
 
@@ -352,7 +352,7 @@ void bcmsdh_unregister_oob_intr(void)
 {
        SDLX_MSG(("%s: Enter\n", __func__));
 
-       set_irq_wake(sdhcinfo->oob_irq, 0);
+       irq_set_irq_wake(sdhcinfo->oob_irq, 0);
        disable_irq(sdhcinfo->oob_irq); /* just in case.. */
        free_irq(sdhcinfo->oob_irq, NULL);
        sdhcinfo->oob_irq_registered = false;
index ea9b733c3926d440231d34d9c552eb95636c39a4..21cdb0637beb391c2f2ee95402508159f2937a43 100644 (file)
@@ -597,7 +597,7 @@ static int cy_as_hal_configure_interrupts(void *dev_p)
        int result;
        int irq_pin  = AST_INT;
 
-       set_irq_type(OMAP_GPIO_IRQ(irq_pin), IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(OMAP_GPIO_IRQ(irq_pin), IRQ_TYPE_LEVEL_LOW);
 
        /*
         * for shared IRQS must provide non NULL device ptr
index 842cd9214a5ec120989e8a339ab158433dff5b91..289729daba80a5dffec1e473e189bc9b787a88ae 100644 (file)
@@ -1191,7 +1191,7 @@ static int cyasblkdev_add_disks(int bus_num,
                bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT;
                bd->user_disk_1->minors = 8;
                bd->user_disk_1->fops = &cyasblkdev_bdops;
-               bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE;
+               bd->user_disk_1->events = DISK_EVENT_MEDIA_CHANGE;
                bd->user_disk_1->private_data = bd;
                bd->user_disk_1->queue = bd->queue.queue;
                bd->dbgprn_flags = DBGPRN_RD_RQ;
index c35f1a73bc8bca281ccea8ee7e87eb6b534b0b11..52fdf60bdbe2db44a7457a1392de002d3f79d79d 100644 (file)
@@ -178,7 +178,7 @@ static int __init xen_hvc_init(void)
        if (xencons_irq < 0)
                xencons_irq = 0; /* NO_IRQ */
        else
-               set_irq_noprobe(xencons_irq);
+               irq_set_noprobe(xencons_irq);
 
        hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
        if (IS_ERR(hp))
index 2e7fc9cee9cc688cede3ae1a595b2a10245205a7..b906f11f7c1ad96908f2787d090acfd50e5f4d33 100644 (file)
@@ -1644,7 +1644,7 @@ static int __devinit msm_hs_probe(struct platform_device *pdev)
        if (unlikely(uport->irq < 0))
                return -ENXIO;
 
-       if (unlikely(set_irq_wake(uport->irq, 1)))
+       if (unlikely(irq_set_irq_wake(uport->irq, 1)))
                return -ENXIO;
 
        if (pdata == NULL || pdata->rx_wakeup_irq < 0)
@@ -1658,7 +1658,7 @@ static int __devinit msm_hs_probe(struct platform_device *pdev)
                if (unlikely(msm_uport->rx_wakeup.irq < 0))
                        return -ENXIO;
 
-               if (unlikely(set_irq_wake(msm_uport->rx_wakeup.irq, 1)))
+               if (unlikely(irq_set_irq_wake(msm_uport->rx_wakeup.irq, 1)))
                        return -ENXIO;
        }
 
index 38193f4e980e04eda0bb8ac5169095c27b544b3e..44e4deb362e132431632ca7bf4ae5a2ea7ac8ea1 100644 (file)
@@ -3832,7 +3832,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
-       ret = set_irq_type(irq, IRQF_TRIGGER_FALLING);
+       ret = irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);
        if (ret) {
                dev_err(&pdev->dev, "error setting irq type\n");
                ret = -EFAULT;
index 2ba3b070ed0bea492ae06d0f838e66efaf0c4caf..c47aac4a1f98415d19a91c56c8d6deb4ebf9aeff 100644 (file)
@@ -943,7 +943,7 @@ static void tusb_musb_enable(struct musb *musb)
        musb_writel(tbase, TUSB_INT_CTRL_CONF,
                        TUSB_INT_CTRL_CONF_INT_RELCYC(0));
 
-       set_irq_type(musb->nIrq, IRQ_TYPE_LEVEL_LOW);
+       irq_set_irq_type(musb->nIrq, IRQ_TYPE_LEVEL_LOW);
 
        /* maybe force into the Default-A OTG state machine */
        if (!(musb_readl(tbase, TUSB_DEV_OTG_STAT)
index f885c868a04de186fe917bc01db66d55b2c846fd..aa250cebecd2963207b3eda1b767af65b4437f02 100644 (file)
@@ -135,40 +135,40 @@ static void vlynq_reset(struct vlynq_device *dev)
        msleep(5);
 }
 
-static void vlynq_irq_unmask(unsigned int irq)
+static void vlynq_irq_unmask(struct irq_data *d)
 {
-       u32 val;
-       struct vlynq_device *dev = get_irq_chip_data(irq);
+       struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
        int virq;
+       u32 val;
 
        BUG_ON(!dev);
-       virq = irq - dev->irq_start;
+       virq = d->irq - dev->irq_start;
        val = readl(&dev->remote->int_device[virq >> 2]);
        val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq);
        writel(val, &dev->remote->int_device[virq >> 2]);
 }
 
-static void vlynq_irq_mask(unsigned int irq)
+static void vlynq_irq_mask(struct irq_data *d)
 {
-       u32 val;
-       struct vlynq_device *dev = get_irq_chip_data(irq);
+       struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
        int virq;
+       u32 val;
 
        BUG_ON(!dev);
-       virq = irq - dev->irq_start;
+       virq = d->irq - dev->irq_start;
        val = readl(&dev->remote->int_device[virq >> 2]);
        val &= ~(VINT_ENABLE << VINT_OFFSET(virq));
        writel(val, &dev->remote->int_device[virq >> 2]);
 }
 
-static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
+static int vlynq_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       u32 val;
-       struct vlynq_device *dev = get_irq_chip_data(irq);
+       struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
        int virq;
+       u32 val;
 
        BUG_ON(!dev);
-       virq = irq - dev->irq_start;
+       virq = d->irq - dev->irq_start;
        val = readl(&dev->remote->int_device[virq >> 2]);
        switch (flow_type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_RISING:
@@ -192,10 +192,9 @@ static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
        return 0;
 }
 
-static void vlynq_local_ack(unsigned int irq)
+static void vlynq_local_ack(struct irq_data *d)
 {
-       struct vlynq_device *dev = get_irq_chip_data(irq);
-
+       struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
        u32 status = readl(&dev->local->status);
 
        pr_debug("%s: local status: 0x%08x\n",
@@ -203,10 +202,9 @@ static void vlynq_local_ack(unsigned int irq)
        writel(status, &dev->local->status);
 }
 
-static void vlynq_remote_ack(unsigned int irq)
+static void vlynq_remote_ack(struct irq_data *d)
 {
-       struct vlynq_device *dev = get_irq_chip_data(irq);
-
+       struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
        u32 status = readl(&dev->remote->status);
 
        pr_debug("%s: remote status: 0x%08x\n",
@@ -238,23 +236,23 @@ static irqreturn_t vlynq_irq(int irq, void *dev_id)
 
 static struct irq_chip vlynq_irq_chip = {
        .name = "vlynq",
-       .unmask = vlynq_irq_unmask,
-       .mask = vlynq_irq_mask,
-       .set_type = vlynq_irq_type,
+       .irq_unmask = vlynq_irq_unmask,
+       .irq_mask = vlynq_irq_mask,
+       .irq_set_type = vlynq_irq_type,
 };
 
 static struct irq_chip vlynq_local_chip = {
        .name = "vlynq local error",
-       .unmask = vlynq_irq_unmask,
-       .mask = vlynq_irq_mask,
-       .ack = vlynq_local_ack,
+       .irq_unmask = vlynq_irq_unmask,
+       .irq_mask = vlynq_irq_mask,
+       .irq_ack = vlynq_local_ack,
 };
 
 static struct irq_chip vlynq_remote_chip = {
        .name = "vlynq local error",
-       .unmask = vlynq_irq_unmask,
-       .mask = vlynq_irq_mask,
-       .ack = vlynq_remote_ack,
+       .irq_unmask = vlynq_irq_unmask,
+       .irq_mask = vlynq_irq_mask,
+       .irq_ack = vlynq_remote_ack,
 };
 
 static int vlynq_setup_irq(struct vlynq_device *dev)
@@ -291,17 +289,17 @@ static int vlynq_setup_irq(struct vlynq_device *dev)
        for (i = dev->irq_start; i <= dev->irq_end; i++) {
                virq = i - dev->irq_start;
                if (virq == dev->local_irq) {
-                       set_irq_chip_and_handler(i, &vlynq_local_chip,
+                       irq_set_chip_and_handler(i, &vlynq_local_chip,
                                                 handle_level_irq);
-                       set_irq_chip_data(i, dev);
+                       irq_set_chip_data(i, dev);
                } else if (virq == dev->remote_irq) {
-                       set_irq_chip_and_handler(i, &vlynq_remote_chip,
+                       irq_set_chip_and_handler(i, &vlynq_remote_chip,
                                                 handle_level_irq);
-                       set_irq_chip_data(i, dev);
+                       irq_set_chip_data(i, dev);
                } else {
-                       set_irq_chip_and_handler(i, &vlynq_irq_chip,
+                       irq_set_chip_and_handler(i, &vlynq_irq_chip,
                                                 handle_simple_irq);
-                       set_irq_chip_data(i, dev);
+                       irq_set_chip_data(i, dev);
                        writel(0, &dev->remote->int_device[virq >> 2]);
                }
        }
index 95921b77cf8650068f2641816f267eb97da9acfc..2f4fa02744a5680673625f48192a7111008053a3 100644 (file)
@@ -368,9 +368,9 @@ static int ds1wm_probe(struct platform_device *pdev)
        ds1wm_data->active_high = plat->active_high;
 
        if (res->flags & IORESOURCE_IRQ_HIGHEDGE)
-               set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING);
+               irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING);
        if (res->flags & IORESOURCE_IRQ_LOWEDGE)
-               set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
+               irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
 
        ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED,
                          "ds1wm", ds1wm_data);
index 596ba604e78d11cdc1e451d80281c69de1825e32..51b5551b4e3fe219d7f934970898024216fab3c3 100644 (file)
@@ -202,7 +202,6 @@ static struct miscdevice davinci_wdt_miscdev = {
 static int __devinit davinci_wdt_probe(struct platform_device *pdev)
 {
        int ret = 0, size;
-       struct resource *res;
        struct device *dev = &pdev->dev;
 
        wdt_clk = clk_get(dev, NULL);
@@ -216,31 +215,31 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
 
        dev_info(dev, "heartbeat %d sec\n", heartbeat);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
+       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (wdt_mem == NULL) {
                dev_err(dev, "failed to get memory region resource\n");
                return -ENOENT;
        }
 
-       size = resource_size(res);
-       wdt_mem = request_mem_region(res->start, size, pdev->name);
-
-       if (wdt_mem == NULL) {
+       size = resource_size(wdt_mem);
+       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
                dev_err(dev, "failed to get memory region\n");
                return -ENOENT;
        }
 
-       wdt_base = ioremap(res->start, size);
+       wdt_base = ioremap(wdt_mem->start, size);
        if (!wdt_base) {
                dev_err(dev, "failed to map memory region\n");
+               release_mem_region(wdt_mem->start, size);
+               wdt_mem = NULL;
                return -ENOMEM;
        }
 
        ret = misc_register(&davinci_wdt_miscdev);
        if (ret < 0) {
                dev_err(dev, "cannot register misc device\n");
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, size);
+               wdt_mem = NULL;
        } else {
                set_bit(WDT_DEVICE_INITED, &wdt_status);
        }
@@ -253,8 +252,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev)
 {
        misc_deregister(&davinci_wdt_miscdev);
        if (wdt_mem) {
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
                wdt_mem = NULL;
        }
 
index 7a82ce5a6337e3948adc1d9e42eab5c72aecf654..73ba2fd8e591435c485bfa2574d2d8b2d70bf274 100644 (file)
@@ -270,7 +270,6 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 {
        int ret = 0;
        int size;
-       struct resource *res;
        struct device *dev = &pdev->dev;
        struct max63xx_timeout *table;
 
@@ -294,21 +293,19 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 
        max63xx_pdev = pdev;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
+       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (wdt_mem == NULL) {
                dev_err(dev, "failed to get memory region resource\n");
                return -ENOENT;
        }
 
-       size = resource_size(res);
-       wdt_mem = request_mem_region(res->start, size, pdev->name);
-
-       if (wdt_mem == NULL) {
+       size = resource_size(wdt_mem);
+       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
                dev_err(dev, "failed to get memory region\n");
                return -ENOENT;
        }
 
-       wdt_base = ioremap(res->start, size);
+       wdt_base = ioremap(wdt_mem->start, size);
        if (!wdt_base) {
                dev_err(dev, "failed to map memory region\n");
                ret = -ENOMEM;
@@ -326,8 +323,8 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 out_unmap:
        iounmap(wdt_base);
 out_request:
-       release_resource(wdt_mem);
-       kfree(wdt_mem);
+       release_mem_region(wdt_mem->start, size);
+       wdt_mem = NULL;
 
        return ret;
 }
@@ -336,8 +333,7 @@ static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
 {
        misc_deregister(&max63xx_wdt_miscdev);
        if (wdt_mem) {
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
                wdt_mem = NULL;
        }
 
index 267377a5a83ebf9311995541c92bc2adf5740086..afa78a54711e1f51097eb9425ebe3f4b8fa0b72a 100644 (file)
@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
  *     Init & exit routines
  */
 
-static unsigned char __init nv_tco_getdevice(void)
+static unsigned char __devinit nv_tco_getdevice(void)
 {
        struct pci_dev *dev = NULL;
        u32 val;
index c7cf4cbf8ab3f302c2efc75bebf7f5a752d2d08b..614933225560ca5c9b6f2f30bf76d81dec68235d 100644 (file)
@@ -254,7 +254,6 @@ static struct miscdevice pnx4008_wdt_miscdev = {
 static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
 {
        int ret = 0, size;
-       struct resource *res;
 
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
@@ -262,42 +261,42 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
        printk(KERN_INFO MODULE_NAME
                "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
+       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (wdt_mem == NULL) {
                printk(KERN_INFO MODULE_NAME
                        "failed to get memory region resouce\n");
                return -ENOENT;
        }
 
-       size = resource_size(res);
-       wdt_mem = request_mem_region(res->start, size, pdev->name);
+       size = resource_size(wdt_mem);
 
-       if (wdt_mem == NULL) {
+       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
                printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
                return -ENOENT;
        }
-       wdt_base = (void __iomem *)IO_ADDRESS(res->start);
+       wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
 
        wdt_clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(wdt_clk)) {
                ret = PTR_ERR(wdt_clk);
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, size);
+               wdt_mem = NULL;
                goto out;
        }
 
        ret = clk_enable(wdt_clk);
        if (ret) {
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, size);
+               wdt_mem = NULL;
+               clk_put(wdt_clk);
                goto out;
        }
 
        ret = misc_register(&pnx4008_wdt_miscdev);
        if (ret < 0) {
                printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, size);
+               wdt_mem = NULL;
                clk_disable(wdt_clk);
                clk_put(wdt_clk);
        } else {
@@ -320,8 +319,7 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
        clk_put(wdt_clk);
 
        if (wdt_mem) {
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
+               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
                wdt_mem = NULL;
        }
        return 0;
index 25b39bf35925b11bc1b1f4c2edc2c15dfd6c66cc..f7f5aa00df609e2a39ad328418ef1840ec3c7157 100644 (file)
@@ -402,7 +402,6 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
 
 static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 {
-       struct resource *res;
        struct device *dev;
        unsigned int wtcon;
        int started = 0;
@@ -416,20 +415,19 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        /* get the memory region for the watchdog timer */
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
+       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (wdt_mem == NULL) {
                dev_err(dev, "no memory resource specified\n");
                return -ENOENT;
        }
 
-       size = resource_size(res);
-       wdt_mem = request_mem_region(res->start, size, pdev->name);
-       if (wdt_mem == NULL) {
+       size = resource_size(wdt_mem);
+       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
                dev_err(dev, "failed to get memory region\n");
                return -EBUSY;
        }
 
-       wdt_base = ioremap(res->start, size);
+       wdt_base = ioremap(wdt_mem->start, size);
        if (wdt_base == NULL) {
                dev_err(dev, "failed to ioremap() region\n");
                ret = -EINVAL;
@@ -524,8 +522,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
        iounmap(wdt_base);
 
  err_req:
-       release_resource(wdt_mem);
-       kfree(wdt_mem);
+       release_mem_region(wdt_mem->start, size);
+       wdt_mem = NULL;
 
        return ret;
 }
@@ -545,8 +543,7 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
 
        iounmap(wdt_base);
 
-       release_resource(wdt_mem);
-       kfree(wdt_mem);
+       release_mem_region(wdt_mem->start, resource_size(wdt_mem));
        wdt_mem = NULL;
        return 0;
 }
index 100b114e3c3c754bcffe7fb7b1abb28c951c9bf3..bf16ffb4d21e122b48c6b63075c235573bf7c159 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
+#include <linux/kernel.h>
 
 #define PFX "SoftDog: "
 
@@ -75,6 +76,11 @@ MODULE_PARM_DESC(soft_noboot,
        "Softdog action, set to 1 to ignore reboots, 0 to reboot "
                                        "(default depends on ONLY_TESTING)");
 
+static int soft_panic;
+module_param(soft_panic, int, 0);
+MODULE_PARM_DESC(soft_panic,
+       "Softdog action, set to 1 to panic, 0 to reboot (default=0)");
+
 /*
  *     Our timer
  */
@@ -98,7 +104,10 @@ static void watchdog_fire(unsigned long data)
 
        if (soft_noboot)
                printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
-       else {
+       else if (soft_panic) {
+               printk(KERN_CRIT PFX "Initiating panic.\n");
+               panic("Software Watchdog Timer expired.");
+       } else {
                printk(KERN_CRIT PFX "Initiating system reboot.\n");
                emergency_restart();
                printk(KERN_CRIT PFX "Reboot didn't ?????\n");
@@ -267,7 +276,8 @@ static struct notifier_block softdog_notifier = {
 };
 
 static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 "
-       "initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";
+       "initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d "
+       "(nowayout= %d)\n";
 
 static int __init watchdog_init(void)
 {
@@ -298,7 +308,7 @@ static int __init watchdog_init(void)
                return ret;
        }
 
-       printk(banner, soft_noboot, soft_margin, nowayout);
+       printk(banner, soft_noboot, soft_margin, soft_panic, nowayout);
 
        return 0;
 }
index 1bc493848ed4f7bdd5cd0d2117c6238ecded933b..87e0527669d8c0860c091ffb3412621fae126a7f 100644 (file)
@@ -42,6 +42,7 @@
 #define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
+static u32 tcobase_phys;
 static void __iomem *tcobase;
 static unsigned int pm_iobase;
 static DEFINE_SPINLOCK(tco_lock);      /* Guards the hardware */
@@ -305,10 +306,18 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
        /* Low three bits of BASE0 are reserved. */
        val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
 
+       if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
+                                                               "SP5100 TCO")) {
+               printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
+                       val);
+               goto unreg_region;
+       }
+       tcobase_phys = val;
+
        tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
        if (tcobase == 0) {
                printk(KERN_ERR PFX "failed to get tcobase address\n");
-               goto unreg_region;
+               goto unreg_mem_region;
        }
 
        /* Enable watchdog decode bit */
@@ -346,7 +355,8 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
        /* Done */
        return 1;
 
-       iounmap(tcobase);
+unreg_mem_region:
+       release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
 unreg_region:
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 exit:
@@ -401,6 +411,7 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
 
 exit:
        iounmap(tcobase);
+       release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
        return ret;
 }
@@ -414,6 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
        /* Deregister */
        misc_deregister(&sp5100_tco_miscdev);
        iounmap(tcobase);
+       release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
index 02b5a9c05cfab1fc32033f669ff3a2c912db3828..036343ba204eaab47758641c8657cb37bba08f54 100644 (file)
@@ -122,7 +122,7 @@ static struct irq_chip xen_pirq_chip;
 /* Get info for IRQ */
 static struct irq_info *info_for_irq(unsigned irq)
 {
-       return get_irq_data(irq);
+       return irq_get_handler_data(irq);
 }
 
 /* Constructors for packed IRQ information. */
@@ -403,7 +403,7 @@ static void xen_irq_init(unsigned irq)
 
        info->type = IRQT_UNBOUND;
 
-       set_irq_data(irq, info);
+       irq_set_handler_data(irq, info);
 
        list_add_tail(&info->list, &xen_irq_list_head);
 }
@@ -458,11 +458,11 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
 
 static void xen_free_irq(unsigned irq)
 {
-       struct irq_info *info = get_irq_data(irq);
+       struct irq_info *info = irq_get_handler_data(irq);
 
        list_del(&info->list);
 
-       set_irq_data(irq, NULL);
+       irq_set_handler_data(irq, NULL);
 
        kfree(info);
 
@@ -585,7 +585,7 @@ static void ack_pirq(struct irq_data *data)
 {
        int evtchn = evtchn_from_irq(data->irq);
 
-       move_native_irq(data->irq);
+       irq_move_irq(data);
 
        if (VALID_EVTCHN(evtchn)) {
                mask_evtchn(evtchn);
@@ -639,8 +639,8 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
        if (irq < 0)
                goto out;
 
-       set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-                                     handle_level_irq, name);
+       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
+                                     name);
 
        irq_op.irq = irq;
        irq_op.vector = 0;
@@ -690,8 +690,8 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
        if (irq == -1)
                goto out;
 
-       set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-                                     handle_level_irq, name);
+       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
+                                     name);
 
        xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
        ret = irq_set_msi_desc(irq, msidesc);
@@ -772,7 +772,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
                if (irq == -1)
                        goto out;
 
-               set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+               irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
                                              handle_fasteoi_irq, "event");
 
                xen_irq_info_evtchn_init(irq, evtchn);
@@ -799,7 +799,7 @@ 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_percpu_chip,
+               irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
                                              handle_percpu_irq, "ipi");
 
                bind_ipi.vcpu = cpu;
@@ -848,7 +848,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
                if (irq == -1)
                        goto out;
 
-               set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
+               irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
                                              handle_percpu_irq, "virq");
 
                bind_virq.virq = virq;
@@ -1339,7 +1339,7 @@ static void ack_dynirq(struct irq_data *data)
 {
        int evtchn = evtchn_from_irq(data->irq);
 
-       move_masked_irq(data->irq);
+       irq_move_masked_irq(data);
 
        if (VALID_EVTCHN(evtchn))
                unmask_evtchn(evtchn);
index 017ce600fbc65b43438d6163130b7402bb3eae3c..b0f9e8fb005255d0f49ddf9e2aa3584dbbbd9d7b 100644 (file)
@@ -273,7 +273,7 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
                                map->vma->vm_start + map->notify.addr;
                        err = copy_to_user(tmp, &err, 1);
                        if (err)
-                               return err;
+                               return -EFAULT;
                        map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
                } else if (pgno >= offset && pgno < offset + pages) {
                        uint8_t *tmp = kmap(map->pages[pgno]);
@@ -662,7 +662,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        if (map->flags) {
                if ((vma->vm_flags & VM_WRITE) &&
                                (map->flags & GNTMAP_readonly))
-                       return -EINVAL;
+                       goto out_unlock_put;
        } else {
                map->flags = GNTMAP_host_map;
                if (!(vma->vm_flags & VM_WRITE))
@@ -700,6 +700,8 @@ unlock_out:
        spin_unlock(&priv->lock);
        return err;
 
+out_unlock_put:
+       spin_unlock(&priv->lock);
 out_put_map:
        if (use_ptemod)
                map->vma = NULL;
index ccc991c542df39ca152f53950aa98ec75aa1d7a9..57c3bb2884ceabd2ea4be939557a6c273c9e8626 100644 (file)
@@ -136,9 +136,8 @@ struct btrfs_inode {
         * items we think we'll end up using, and reserved_extents is the number
         * of extent items we've reserved metadata for.
         */
-       spinlock_t accounting_lock;
        atomic_t outstanding_extents;
-       int reserved_extents;
+       atomic_t reserved_extents;
 
        /*
         * ordered_data_close is set by truncate when a file that used
index 4d2110eafe2927e455e1e6a107019d7c2b483676..41d1d7c70e29d2aed3a347e5b9d74d2a810d7b46 100644 (file)
@@ -340,6 +340,8 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
        WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1));
        cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
+       if (!cb)
+               return -ENOMEM;
        atomic_set(&cb->pending_bios, 0);
        cb->errors = 0;
        cb->inode = inode;
@@ -354,6 +356,10 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
 
        bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
+       if(!bio) {
+               kfree(cb);
+               return -ENOMEM;
+       }
        bio->bi_private = cb;
        bio->bi_end_io = end_compressed_bio_write;
        atomic_inc(&cb->pending_bios);
@@ -657,8 +663,9 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
                        atomic_inc(&cb->pending_bios);
 
                        if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
-                               btrfs_lookup_bio_sums(root, inode, comp_bio,
-                                                     sums);
+                               ret = btrfs_lookup_bio_sums(root, inode,
+                                                       comp_bio, sums);
+                               BUG_ON(ret);
                        }
                        sums += (comp_bio->bi_size + root->sectorsize - 1) /
                                root->sectorsize;
@@ -683,8 +690,10 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0);
        BUG_ON(ret);
 
-       if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
-               btrfs_lookup_bio_sums(root, inode, comp_bio, sums);
+       if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
+               ret = btrfs_lookup_bio_sums(root, inode, comp_bio, sums);
+               BUG_ON(ret);
+       }
 
        ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0);
        BUG_ON(ret);
index b5baff0dccfec40c360397c0d1e47380aea51ae2..84d7ca1fe0bac42a58c9115f2dccaa68efb6b3b6 100644 (file)
@@ -147,10 +147,11 @@ noinline void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
 struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
 {
        struct extent_buffer *eb;
-       spin_lock(&root->node_lock);
-       eb = root->node;
+
+       rcu_read_lock();
+       eb = rcu_dereference(root->node);
        extent_buffer_get(eb);
-       spin_unlock(&root->node_lock);
+       rcu_read_unlock();
        return eb;
 }
 
@@ -165,14 +166,8 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
        while (1) {
                eb = btrfs_root_node(root);
                btrfs_tree_lock(eb);
-
-               spin_lock(&root->node_lock);
-               if (eb == root->node) {
-                       spin_unlock(&root->node_lock);
+               if (eb == root->node)
                        break;
-               }
-               spin_unlock(&root->node_lock);
-
                btrfs_tree_unlock(eb);
                free_extent_buffer(eb);
        }
@@ -458,10 +453,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                else
                        parent_start = 0;
 
-               spin_lock(&root->node_lock);
-               root->node = cow;
                extent_buffer_get(cow);
-               spin_unlock(&root->node_lock);
+               rcu_assign_pointer(root->node, cow);
 
                btrfs_free_tree_block(trans, root, buf, parent_start,
                                      last_ref);
@@ -542,6 +535,9 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
 
        ret = __btrfs_cow_block(trans, root, buf, parent,
                                 parent_slot, cow_ret, search_start, 0);
+
+       trace_btrfs_cow_block(root, buf, *cow_ret);
+
        return ret;
 }
 
@@ -686,6 +682,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
                        if (!cur) {
                                cur = read_tree_block(root, blocknr,
                                                         blocksize, gen);
+                               if (!cur)
+                                       return -EIO;
                        } else if (!uptodate) {
                                btrfs_read_buffer(cur, gen);
                        }
@@ -732,122 +730,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
        return btrfs_item_offset_nr(leaf, nr - 1);
 }
 
-/*
- * extra debugging checks to make sure all the items in a key are
- * well formed and in the proper order
- */
-static int check_node(struct btrfs_root *root, struct btrfs_path *path,
-                     int level)
-{
-       struct extent_buffer *parent = NULL;
-       struct extent_buffer *node = path->nodes[level];
-       struct btrfs_disk_key parent_key;
-       struct btrfs_disk_key node_key;
-       int parent_slot;
-       int slot;
-       struct btrfs_key cpukey;
-       u32 nritems = btrfs_header_nritems(node);
-
-       if (path->nodes[level + 1])
-               parent = path->nodes[level + 1];
-
-       slot = path->slots[level];
-       BUG_ON(nritems == 0);
-       if (parent) {
-               parent_slot = path->slots[level + 1];
-               btrfs_node_key(parent, &parent_key, parent_slot);
-               btrfs_node_key(node, &node_key, 0);
-               BUG_ON(memcmp(&parent_key, &node_key,
-                             sizeof(struct btrfs_disk_key)));
-               BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
-                      btrfs_header_bytenr(node));
-       }
-       BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
-       if (slot != 0) {
-               btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
-               btrfs_node_key(node, &node_key, slot);
-               BUG_ON(comp_keys(&node_key, &cpukey) <= 0);
-       }
-       if (slot < nritems - 1) {
-               btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
-               btrfs_node_key(node, &node_key, slot);
-               BUG_ON(comp_keys(&node_key, &cpukey) >= 0);
-       }
-       return 0;
-}
-
-/*
- * extra checking to make sure all the items in a leaf are
- * well formed and in the proper order
- */
-static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
-                     int level)
-{
-       struct extent_buffer *leaf = path->nodes[level];
-       struct extent_buffer *parent = NULL;
-       int parent_slot;
-       struct btrfs_key cpukey;
-       struct btrfs_disk_key parent_key;
-       struct btrfs_disk_key leaf_key;
-       int slot = path->slots[0];
-
-       u32 nritems = btrfs_header_nritems(leaf);
-
-       if (path->nodes[level + 1])
-               parent = path->nodes[level + 1];
-
-       if (nritems == 0)
-               return 0;
-
-       if (parent) {
-               parent_slot = path->slots[level + 1];
-               btrfs_node_key(parent, &parent_key, parent_slot);
-               btrfs_item_key(leaf, &leaf_key, 0);
-
-               BUG_ON(memcmp(&parent_key, &leaf_key,
-                      sizeof(struct btrfs_disk_key)));
-               BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
-                      btrfs_header_bytenr(leaf));
-       }
-       if (slot != 0 && slot < nritems - 1) {
-               btrfs_item_key(leaf, &leaf_key, slot);
-               btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
-               if (comp_keys(&leaf_key, &cpukey) <= 0) {
-                       btrfs_print_leaf(root, leaf);
-                       printk(KERN_CRIT "slot %d offset bad key\n", slot);
-                       BUG_ON(1);
-               }
-               if (btrfs_item_offset_nr(leaf, slot - 1) !=
-                      btrfs_item_end_nr(leaf, slot)) {
-                       btrfs_print_leaf(root, leaf);
-                       printk(KERN_CRIT "slot %d offset bad\n", slot);
-                       BUG_ON(1);
-               }
-       }
-       if (slot < nritems - 1) {
-               btrfs_item_key(leaf, &leaf_key, slot);
-               btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
-               BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0);
-               if (btrfs_item_offset_nr(leaf, slot) !=
-                       btrfs_item_end_nr(leaf, slot + 1)) {
-                       btrfs_print_leaf(root, leaf);
-                       printk(KERN_CRIT "slot %d offset bad\n", slot);
-                       BUG_ON(1);
-               }
-       }
-       BUG_ON(btrfs_item_offset_nr(leaf, 0) +
-              btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
-       return 0;
-}
-
-static noinline int check_block(struct btrfs_root *root,
-                               struct btrfs_path *path, int level)
-{
-       return 0;
-       if (level == 0)
-               return check_leaf(root, path, level);
-       return check_node(root, path, level);
-}
 
 /*
  * search for key in the extent_buffer.  The items start at offset p,
@@ -1046,9 +928,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
-               spin_lock(&root->node_lock);
-               root->node = child;
-               spin_unlock(&root->node_lock);
+               rcu_assign_pointer(root->node, child);
 
                add_root_to_dirty_list(root);
                btrfs_tree_unlock(child);
@@ -1188,7 +1068,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                }
        }
        /* double check we haven't messed things up */
-       check_block(root, path, level);
        if (orig_ptr !=
            btrfs_node_blockptr(path->nodes[level], path->slots[level]))
                BUG();
@@ -1798,12 +1677,6 @@ cow_done:
                if (!cow)
                        btrfs_unlock_up_safe(p, level + 1);
 
-               ret = check_block(root, p, level);
-               if (ret) {
-                       ret = -1;
-                       goto done;
-               }
-
                ret = bin_search(b, key, level, &slot);
 
                if (level != 0) {
@@ -2130,10 +2003,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
 
        btrfs_mark_buffer_dirty(c);
 
-       spin_lock(&root->node_lock);
        old = root->node;
-       root->node = c;
-       spin_unlock(&root->node_lock);
+       rcu_assign_pointer(root->node, c);
 
        /* the super has an extra ref to root->node */
        free_extent_buffer(old);
@@ -3840,7 +3711,8 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
        unsigned long ptr;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
        ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
        if (!ret) {
                leaf = path->nodes[0];
@@ -4217,6 +4089,7 @@ find_next_key:
                }
                btrfs_set_path_blocking(path);
                cur = read_node_slot(root, cur, slot);
+               BUG_ON(!cur);
 
                btrfs_tree_lock(cur);
 
index 7f78cc78fdd0a3dcc77218be33be516b5f2ac038..d47ce83078545e747e2567f8b1d3e3407e48aabd 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/kobject.h>
+#include <trace/events/btrfs.h>
 #include <asm/kmap_types.h>
 #include "extent_io.h"
 #include "extent_map.h"
@@ -40,6 +41,7 @@ extern struct kmem_cache *btrfs_trans_handle_cachep;
 extern struct kmem_cache *btrfs_transaction_cachep;
 extern struct kmem_cache *btrfs_bit_radix_cachep;
 extern struct kmem_cache *btrfs_path_cachep;
+extern struct kmem_cache *btrfs_free_space_cachep;
 struct btrfs_ordered_sum;
 
 #define BTRFS_MAGIC "_BHRfS_M"
@@ -782,9 +784,6 @@ struct btrfs_free_cluster {
        /* first extent starting offset */
        u64 window_start;
 
-       /* if this cluster simply points at a bitmap in the block group */
-       bool points_to_bitmap;
-
        struct btrfs_block_group_cache *block_group;
        /*
         * when a cluster is allocated from a block group, we put the
@@ -1283,6 +1282,7 @@ struct btrfs_root {
 #define BTRFS_INODE_NODUMP             (1 << 8)
 #define BTRFS_INODE_NOATIME            (1 << 9)
 #define BTRFS_INODE_DIRSYNC            (1 << 10)
+#define BTRFS_INODE_COMPRESS           (1 << 11)
 
 /* some macros to generate set/get funcs for the struct fields.  This
  * assumes there is a lefoo_to_cpu for every type, so lets make a simple
@@ -2157,6 +2157,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
                      u64 root_objectid, u64 owner, u64 offset);
 
 int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len);
+int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
+                               u64 num_bytes, int reserve, int sinfo);
 int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root);
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
@@ -2227,10 +2229,12 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
 int btrfs_error_unpin_extent_range(struct btrfs_root *root,
                                   u64 start, u64 end);
 int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
-                              u64 num_bytes);
+                              u64 num_bytes, u64 *actual_bytes);
 int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root, u64 type);
+int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range);
 
+int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
 /* ctree.c */
 int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
                     int level, int *slot);
@@ -2392,6 +2396,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
                                          struct btrfs_path *path, u64 dir,
                                          const char *name, u16 name_len,
                                          int mod);
+int verify_dir_item(struct btrfs_root *root,
+                   struct extent_buffer *leaf,
+                   struct btrfs_dir_item *dir_item);
 
 /* orphan.c */
 int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans,
@@ -2528,7 +2535,7 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans,
                              struct inode *inode);
 int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
-void btrfs_orphan_cleanup(struct btrfs_root *root);
+int btrfs_orphan_cleanup(struct btrfs_root *root);
 void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans,
                                struct btrfs_pending_snapshot *pending,
                                u64 *bytes_to_reserve);
@@ -2536,7 +2543,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans,
                                struct btrfs_pending_snapshot *pending);
 void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root);
-int btrfs_cont_expand(struct inode *inode, loff_t size);
+int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size);
 int btrfs_invalidate_inodes(struct btrfs_root *root);
 void btrfs_add_delayed_iput(struct inode *inode);
 void btrfs_run_delayed_iputs(struct btrfs_root *root);
index e807b143b8578a5ed58d3f90dfeec06fa5af7f20..bce28f6538995bc908a6b2dee331e59aba91f651 100644 (file)
@@ -483,6 +483,8 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
        INIT_LIST_HEAD(&head_ref->cluster);
        mutex_init(&head_ref->mutex);
 
+       trace_btrfs_delayed_ref_head(ref, head_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {
@@ -537,6 +539,8 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
        }
        full_ref->level = level;
 
+       trace_btrfs_delayed_tree_ref(ref, full_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {
@@ -591,6 +595,8 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
        full_ref->objectid = owner;
        full_ref->offset = offset;
 
+       trace_btrfs_delayed_data_ref(ref, full_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {
index f0cad5ae5be75679c273583b6c6f535118acc093..c62f02f6ae693728ce9286d963b78708428a86fb 100644 (file)
@@ -151,7 +151,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
                ret = PTR_ERR(dir_item);
                if (ret == -EEXIST)
                        goto second_insert;
-               goto out;
+               goto out_free;
        }
 
        leaf = path->nodes[0];
@@ -170,7 +170,7 @@ second_insert:
        /* FIXME, use some real flag for selecting the extra index */
        if (root == root->fs_info->tree_root) {
                ret = 0;
-               goto out;
+               goto out_free;
        }
        btrfs_release_path(root, path);
 
@@ -180,7 +180,7 @@ second_insert:
                                        name, name_len);
        if (IS_ERR(dir_item)) {
                ret2 = PTR_ERR(dir_item);
-               goto out;
+               goto out_free;
        }
        leaf = path->nodes[0];
        btrfs_cpu_key_to_disk(&disk_key, location);
@@ -192,7 +192,9 @@ second_insert:
        name_ptr = (unsigned long)(dir_item + 1);
        write_extent_buffer(leaf, name, name_ptr, name_len);
        btrfs_mark_buffer_dirty(leaf);
-out:
+
+out_free:
+
        btrfs_free_path(path);
        if (ret)
                return ret;
@@ -377,6 +379,9 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
 
        leaf = path->nodes[0];
        dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
+       if (verify_dir_item(root, leaf, dir_item))
+               return NULL;
+
        total_len = btrfs_item_size_nr(leaf, path->slots[0]);
        while (cur < total_len) {
                this_len = sizeof(*dir_item) +
@@ -429,3 +434,35 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
        }
        return ret;
 }
+
+int verify_dir_item(struct btrfs_root *root,
+                   struct extent_buffer *leaf,
+                   struct btrfs_dir_item *dir_item)
+{
+       u16 namelen = BTRFS_NAME_LEN;
+       u8 type = btrfs_dir_type(leaf, dir_item);
+
+       if (type >= BTRFS_FT_MAX) {
+               printk(KERN_CRIT "btrfs: invalid dir item type: %d\n",
+                      (int)type);
+               return 1;
+       }
+
+       if (type == BTRFS_FT_XATTR)
+               namelen = XATTR_NAME_MAX;
+
+       if (btrfs_dir_name_len(leaf, dir_item) > namelen) {
+               printk(KERN_CRIT "btrfS: invalid dir item name len: %u\n",
+                      (unsigned)btrfs_dir_data_len(leaf, dir_item));
+               return 1;
+       }
+
+       /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */
+       if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) {
+               printk(KERN_CRIT "btrfs: invalid dir item data len: %u\n",
+                      (unsigned)btrfs_dir_data_len(leaf, dir_item));
+               return 1;
+       }
+
+       return 0;
+}
index 830d261d0e6b9a7faba479160edb72df3d8a6d2a..d7a7315bd031a095c4f9f405afbb2b096a1e6f3e 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/crc32c.h>
 #include <linux/slab.h>
 #include <linux/migrate.h>
+#include <asm/unaligned.h>
 #include "compat.h"
 #include "ctree.h"
 #include "disk-io.h"
@@ -198,7 +199,7 @@ u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
 
 void btrfs_csum_final(u32 crc, char *result)
 {
-       *(__le32 *)result = ~cpu_to_le32(crc);
+       put_unaligned_le32(~crc, result);
 }
 
 /*
@@ -323,6 +324,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
        int num_copies = 0;
        int mirror_num = 0;
 
+       clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
        io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
        while (1) {
                ret = read_extent_buffer_pages(io_tree, eb, start, 1,
@@ -331,6 +333,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
                    !verify_parent_transid(io_tree, eb, parent_transid))
                        return ret;
 
+               /*
+                * This buffer's crc is fine, but its contents are corrupted, so
+                * there is no reason to read the other copies, they won't be
+                * any less wrong.
+                */
+               if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
+                       return ret;
+
                num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
                                              eb->start, eb->len);
                if (num_copies == 1)
@@ -419,6 +429,73 @@ static int check_tree_block_fsid(struct btrfs_root *root,
        return ret;
 }
 
+#define CORRUPT(reason, eb, root, slot)                                \
+       printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \
+              "root=%llu, slot=%d\n", reason,                  \
+              (unsigned long long)btrfs_header_bytenr(eb),     \
+              (unsigned long long)root->objectid, slot)
+
+static noinline int check_leaf(struct btrfs_root *root,
+                              struct extent_buffer *leaf)
+{
+       struct btrfs_key key;
+       struct btrfs_key leaf_key;
+       u32 nritems = btrfs_header_nritems(leaf);
+       int slot;
+
+       if (nritems == 0)
+               return 0;
+
+       /* Check the 0 item */
+       if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
+           BTRFS_LEAF_DATA_SIZE(root)) {
+               CORRUPT("invalid item offset size pair", leaf, root, 0);
+               return -EIO;
+       }
+
+       /*
+        * Check to make sure each items keys are in the correct order and their
+        * offsets make sense.  We only have to loop through nritems-1 because
+        * we check the current slot against the next slot, which verifies the
+        * next slot's offset+size makes sense and that the current's slot
+        * offset is correct.
+        */
+       for (slot = 0; slot < nritems - 1; slot++) {
+               btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
+               btrfs_item_key_to_cpu(leaf, &key, slot + 1);
+
+               /* Make sure the keys are in the right order */
+               if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
+                       CORRUPT("bad key order", leaf, root, slot);
+                       return -EIO;
+               }
+
+               /*
+                * Make sure the offset and ends are right, remember that the
+                * item data starts at the end of the leaf and grows towards the
+                * front.
+                */
+               if (btrfs_item_offset_nr(leaf, slot) !=
+                       btrfs_item_end_nr(leaf, slot + 1)) {
+                       CORRUPT("slot offset bad", leaf, root, slot);
+                       return -EIO;
+               }
+
+               /*
+                * Check to make sure that we don't point outside of the leaf,
+                * just incase all the items are consistent to eachother, but
+                * all point outside of the leaf.
+                */
+               if (btrfs_item_end_nr(leaf, slot) >
+                   BTRFS_LEAF_DATA_SIZE(root)) {
+                       CORRUPT("slot end outside of leaf", leaf, root, slot);
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
 {
@@ -485,8 +562,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
        btrfs_set_buffer_lockdep_class(eb, found_level);
 
        ret = csum_tree_block(root, eb, 1);
-       if (ret)
+       if (ret) {
                ret = -EIO;
+               goto err;
+       }
+
+       /*
+        * If this is a leaf block and it is corrupt, set the corrupt bit so
+        * that we don't try and read the other copies of this block, just
+        * return -EIO.
+        */
+       if (found_level == 0 && check_leaf(root, eb)) {
+               set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
+               ret = -EIO;
+       }
 
        end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
        end = eb->start + end - 1;
@@ -1159,7 +1248,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
                     root, fs_info, location->objectid);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               kfree(root);
+               return ERR_PTR(-ENOMEM);
+       }
        ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
        if (ret == 0) {
                l = path->nodes[0];
@@ -1553,6 +1645,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                goto fail_bdi;
        }
 
+       fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS;
+
        INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
        INIT_LIST_HEAD(&fs_info->trans_list);
        INIT_LIST_HEAD(&fs_info->dead_roots);
@@ -1683,6 +1777,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 
        btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY);
 
+       /*
+        * In the long term, we'll store the compression type in the super
+        * block, and it'll be used for per file compression control.
+        */
+       fs_info->compress_type = BTRFS_COMPRESS_ZLIB;
+
        ret = btrfs_parse_options(tree_root, options);
        if (ret) {
                err = ret;
@@ -1888,6 +1988,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->metadata_alloc_profile = (u64)-1;
        fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
 
+       ret = btrfs_init_space_info(fs_info);
+       if (ret) {
+               printk(KERN_ERR "Failed to initial space info: %d\n", ret);
+               goto fail_block_groups;
+       }
+
        ret = btrfs_read_block_groups(extent_root);
        if (ret) {
                printk(KERN_ERR "Failed to read block groups: %d\n", ret);
@@ -1979,9 +2085,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 
        if (!(sb->s_flags & MS_RDONLY)) {
                down_read(&fs_info->cleanup_work_sem);
-               btrfs_orphan_cleanup(fs_info->fs_root);
-               btrfs_orphan_cleanup(fs_info->tree_root);
+               err = btrfs_orphan_cleanup(fs_info->fs_root);
+               if (!err)
+                       err = btrfs_orphan_cleanup(fs_info->tree_root);
                up_read(&fs_info->cleanup_work_sem);
+               if (err) {
+                       close_ctree(tree_root);
+                       return ERR_PTR(err);
+               }
        }
 
        return tree_root;
@@ -2356,8 +2467,12 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)
 
                root_objectid = gang[ret - 1]->root_key.objectid + 1;
                for (i = 0; i < ret; i++) {
+                       int err;
+
                        root_objectid = gang[i]->root_key.objectid;
-                       btrfs_orphan_cleanup(gang[i]);
+                       err = btrfs_orphan_cleanup(gang[i]);
+                       if (err)
+                               return err;
                }
                root_objectid++;
        }
@@ -2868,7 +2983,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root,
                        break;
 
                /* opt_discard */
-               ret = btrfs_error_discard_extent(root, start, end + 1 - start);
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_error_discard_extent(root, start,
+                                                        end + 1 - start,
+                                                        NULL);
 
                clear_extent_dirty(unpin, start, end, GFP_NOFS);
                btrfs_error_unpin_extent_range(root, start, end);
index 7b3089b5c2df816522e2356d3064f0b2bdb40c4f..f619c3cb13b7006cc7f95e273996917bbcebcf67 100644 (file)
@@ -36,8 +36,6 @@
 static int update_block_group(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              u64 bytenr, u64 num_bytes, int alloc);
-static int update_reserved_bytes(struct btrfs_block_group_cache *cache,
-                                u64 num_bytes, int reserve, int sinfo);
 static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                u64 bytenr, u64 num_bytes, u64 parent,
@@ -442,7 +440,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
         * allocate blocks for the tree root we can't do the fast caching since
         * we likely hold important locks.
         */
-       if (!trans->transaction->in_commit &&
+       if (trans && (!trans->transaction->in_commit) &&
            (root && root != root->fs_info->tree_root)) {
                spin_lock(&cache->lock);
                if (cache->cached != BTRFS_CACHE_NO) {
@@ -471,7 +469,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        if (load_cache_only)
                return 0;
 
-       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL);
+       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
        BUG_ON(!caching_ctl);
 
        INIT_LIST_HEAD(&caching_ctl->list);
@@ -1740,39 +1738,45 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-static void btrfs_issue_discard(struct block_device *bdev,
+static int btrfs_issue_discard(struct block_device *bdev,
                                u64 start, u64 len)
 {
-       blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0);
+       return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0);
 }
 
 static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
-                               u64 num_bytes)
+                               u64 num_bytes, u64 *actual_bytes)
 {
        int ret;
-       u64 map_length = num_bytes;
+       u64 discarded_bytes = 0;
        struct btrfs_multi_bio *multi = NULL;
 
-       if (!btrfs_test_opt(root, DISCARD))
-               return 0;
 
        /* Tell the block device(s) that the sectors can be discarded */
-       ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
-                             bytenr, &map_length, &multi, 0);
+       ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD,
+                             bytenr, &num_bytes, &multi, 0);
        if (!ret) {
                struct btrfs_bio_stripe *stripe = multi->stripes;
                int i;
 
-               if (map_length > num_bytes)
-                       map_length = num_bytes;
 
                for (i = 0; i < multi->num_stripes; i++, stripe++) {
-                       btrfs_issue_discard(stripe->dev->bdev,
-                                           stripe->physical,
-                                           map_length);
+                       ret = btrfs_issue_discard(stripe->dev->bdev,
+                                                 stripe->physical,
+                                                 stripe->length);
+                       if (!ret)
+                               discarded_bytes += stripe->length;
+                       else if (ret != -EOPNOTSUPP)
+                               break;
                }
                kfree(multi);
        }
+       if (discarded_bytes && ret == -EOPNOTSUPP)
+               ret = 0;
+
+       if (actual_bytes)
+               *actual_bytes = discarded_bytes;
+
 
        return ret;
 }
@@ -3996,6 +4000,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
        u64 to_reserve;
        int nr_extents;
+       int reserved_extents;
        int ret;
 
        if (btrfs_transaction_in_commit(root->fs_info))
@@ -4003,25 +4008,24 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
 
        num_bytes = ALIGN(num_bytes, root->sectorsize);
 
-       spin_lock(&BTRFS_I(inode)->accounting_lock);
        nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1;
-       if (nr_extents > BTRFS_I(inode)->reserved_extents) {
-               nr_extents -= BTRFS_I(inode)->reserved_extents;
+       reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
+
+       if (nr_extents > reserved_extents) {
+               nr_extents -= reserved_extents;
                to_reserve = calc_trans_metadata_size(root, nr_extents);
        } else {
                nr_extents = 0;
                to_reserve = 0;
        }
-       spin_unlock(&BTRFS_I(inode)->accounting_lock);
+
        to_reserve += calc_csum_metadata_size(inode, num_bytes);
        ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1);
        if (ret)
                return ret;
 
-       spin_lock(&BTRFS_I(inode)->accounting_lock);
-       BTRFS_I(inode)->reserved_extents += nr_extents;
+       atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents);
        atomic_inc(&BTRFS_I(inode)->outstanding_extents);
-       spin_unlock(&BTRFS_I(inode)->accounting_lock);
 
        block_rsv_add_bytes(block_rsv, to_reserve, 1);
 
@@ -4036,20 +4040,30 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 to_free;
        int nr_extents;
+       int reserved_extents;
 
        num_bytes = ALIGN(num_bytes, root->sectorsize);
        atomic_dec(&BTRFS_I(inode)->outstanding_extents);
        WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0);
 
-       spin_lock(&BTRFS_I(inode)->accounting_lock);
-       nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents);
-       if (nr_extents < BTRFS_I(inode)->reserved_extents) {
-               nr_extents = BTRFS_I(inode)->reserved_extents - nr_extents;
-               BTRFS_I(inode)->reserved_extents -= nr_extents;
-       } else {
-               nr_extents = 0;
-       }
-       spin_unlock(&BTRFS_I(inode)->accounting_lock);
+       reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
+       do {
+               int old, new;
+
+               nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents);
+               if (nr_extents >= reserved_extents) {
+                       nr_extents = 0;
+                       break;
+               }
+               old = reserved_extents;
+               nr_extents = reserved_extents - nr_extents;
+               new = reserved_extents - nr_extents;
+               old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents,
+                                    reserved_extents, new);
+               if (likely(old == reserved_extents))
+                       break;
+               reserved_extents = old;
+       } while (1);
 
        to_free = calc_csum_metadata_size(inode, num_bytes);
        if (nr_extents > 0)
@@ -4223,8 +4237,8 @@ int btrfs_pin_extent(struct btrfs_root *root,
  * update size of reserved extents. this function may return -EAGAIN
  * if 'reserve' is true or 'sinfo' is false.
  */
-static int update_reserved_bytes(struct btrfs_block_group_cache *cache,
-                                u64 num_bytes, int reserve, int sinfo)
+int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
+                               u64 num_bytes, int reserve, int sinfo)
 {
        int ret = 0;
        if (sinfo) {
@@ -4363,7 +4377,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
                if (ret)
                        break;
 
-               ret = btrfs_discard_extent(root, start, end + 1 - start);
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start,
+                                                  end + 1 - start, NULL);
 
                clear_extent_dirty(unpin, start, end, GFP_NOFS);
                unpin_extent_range(root, start, end);
@@ -4704,10 +4720,10 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
 
                btrfs_add_free_space(cache, buf->start, buf->len);
-               ret = update_reserved_bytes(cache, buf->len, 0, 0);
+               ret = btrfs_update_reserved_bytes(cache, buf->len, 0, 0);
                if (ret == -EAGAIN) {
                        /* block group became read-only */
-                       update_reserved_bytes(cache, buf->len, 0, 1);
+                       btrfs_update_reserved_bytes(cache, buf->len, 0, 1);
                        goto out;
                }
 
@@ -4744,6 +4760,11 @@ pin:
                }
        }
 out:
+       /*
+        * Deleting the buffer, clear the corrupt flag since it doesn't matter
+        * anymore.
+        */
+       clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
        btrfs_put_block_group(cache);
 }
 
@@ -5191,7 +5212,7 @@ checks:
                                             search_start - offset);
                BUG_ON(offset > search_start);
 
-               ret = update_reserved_bytes(block_group, num_bytes, 1,
+               ret = btrfs_update_reserved_bytes(block_group, num_bytes, 1,
                                            (data & BTRFS_BLOCK_GROUP_DATA));
                if (ret == -EAGAIN) {
                        btrfs_add_free_space(block_group, offset, num_bytes);
@@ -5397,6 +5418,8 @@ again:
                dump_space_info(sinfo, num_bytes, 1);
        }
 
+       trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
+
        return ret;
 }
 
@@ -5412,12 +5435,15 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len)
                return -ENOSPC;
        }
 
-       ret = btrfs_discard_extent(root, start, len);
+       if (btrfs_test_opt(root, DISCARD))
+               ret = btrfs_discard_extent(root, start, len, NULL);
 
        btrfs_add_free_space(cache, start, len);
-       update_reserved_bytes(cache, len, 0, 1);
+       btrfs_update_reserved_bytes(cache, len, 0, 1);
        btrfs_put_block_group(cache);
 
+       trace_btrfs_reserved_extent_free(root, start, len);
+
        return ret;
 }
 
@@ -5444,7 +5470,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
        size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
@@ -5614,7 +5641,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
                put_caching_control(caching_ctl);
        }
 
-       ret = update_reserved_bytes(block_group, ins->offset, 1, 1);
+       ret = btrfs_update_reserved_bytes(block_group, ins->offset, 1, 1);
        BUG_ON(ret);
        btrfs_put_block_group(block_group);
        ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,
@@ -6047,6 +6074,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
                if (reada && level == 1)
                        reada_walk_down(trans, root, wc, path);
                next = read_tree_block(root, bytenr, blocksize, generation);
+               if (!next)
+                       return -EIO;
                btrfs_tree_lock(next);
                btrfs_set_lock_blocking(next);
        }
@@ -6438,10 +6467,14 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
        BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        wc = kzalloc(sizeof(*wc), GFP_NOFS);
-       BUG_ON(!wc);
+       if (!wc) {
+               btrfs_free_path(path);
+               return -ENOMEM;
+       }
 
        btrfs_assert_tree_locked(parent);
        parent_level = btrfs_header_level(parent);
@@ -6899,7 +6932,11 @@ static noinline int get_new_locations(struct inode *reloc_inode,
        }
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               if (exts != *extents)
+                       kfree(exts);
+               return -ENOMEM;
+       }
 
        cur_pos = extent_key->objectid - offset;
        last_byte = extent_key->objectid + extent_key->offset;
@@ -6941,6 +6978,10 @@ static noinline int get_new_locations(struct inode *reloc_inode,
                        struct disk_extent *old = exts;
                        max *= 2;
                        exts = kzalloc(sizeof(*exts) * max, GFP_NOFS);
+                       if (!exts) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        memcpy(exts, old, sizeof(*exts) * nr);
                        if (old != *extents)
                                kfree(old);
@@ -7423,7 +7464,8 @@ static noinline int replace_extents_in_leaf(struct btrfs_trans_handle *trans,
        int ret;
 
        new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS);
-       BUG_ON(!new_extent);
+       if (!new_extent)
+               return -ENOMEM;
 
        ref = btrfs_lookup_leaf_ref(root, leaf->start);
        BUG_ON(!ref);
@@ -7609,7 +7651,8 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root)
 
        reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
        BUG_ON(!reloc_root);
-       btrfs_orphan_cleanup(reloc_root);
+       ret = btrfs_orphan_cleanup(reloc_root);
+       BUG_ON(ret);
        return 0;
 }
 
@@ -7627,7 +7670,8 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans,
                return 0;
 
        root_item = kmalloc(sizeof(*root_item), GFP_NOFS);
-       BUG_ON(!root_item);
+       if (!root_item)
+               return -ENOMEM;
 
        ret = btrfs_copy_root(trans, root, root->commit_root,
                              &eb, BTRFS_TREE_RELOC_OBJECTID);
@@ -7653,7 +7697,7 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans,
 
        reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
                                                 &root_key);
-       BUG_ON(!reloc_root);
+       BUG_ON(IS_ERR(reloc_root));
        reloc_root->last_trans = trans->transid;
        reloc_root->commit_root = NULL;
        reloc_root->ref_tree = &root->fs_info->reloc_ref_tree;
@@ -7906,6 +7950,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
 
                        eb = read_tree_block(found_root, block_start,
                                             block_size, 0);
+                       if (!eb) {
+                               ret = -EIO;
+                               goto out;
+                       }
                        btrfs_tree_lock(eb);
                        BUG_ON(level != btrfs_header_level(eb));
 
@@ -8621,6 +8669,12 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        BUG_ON(!block_group);
        BUG_ON(!block_group->ro);
 
+       /*
+        * Free the reserved super bytes from this block group before
+        * remove it.
+        */
+       free_excluded_extents(root, block_group);
+
        memcpy(&key, &block_group->key, sizeof(key));
        if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP |
                                  BTRFS_BLOCK_GROUP_RAID1 |
@@ -8724,13 +8778,84 @@ out:
        return ret;
 }
 
+int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_space_info *space_info;
+       int ret;
+
+       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0,
+                                                                &space_info);
+       if (ret)
+               return ret;
+
+       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0,
+                                                                &space_info);
+       if (ret)
+               return ret;
+
+       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0,
+                                                                &space_info);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
 int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
 {
        return unpin_extent_range(root, start, end);
 }
 
 int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
-                              u64 num_bytes)
+                              u64 num_bytes, u64 *actual_bytes)
+{
+       return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes);
+}
+
+int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
 {
-       return btrfs_discard_extent(root, bytenr, num_bytes);
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_block_group_cache *cache = NULL;
+       u64 group_trimmed;
+       u64 start;
+       u64 end;
+       u64 trimmed = 0;
+       int ret = 0;
+
+       cache = btrfs_lookup_block_group(fs_info, range->start);
+
+       while (cache) {
+               if (cache->key.objectid >= (range->start + range->len)) {
+                       btrfs_put_block_group(cache);
+                       break;
+               }
+
+               start = max(range->start, cache->key.objectid);
+               end = min(range->start + range->len,
+                               cache->key.objectid + cache->key.offset);
+
+               if (end - start >= range->minlen) {
+                       if (!block_group_cache_done(cache)) {
+                               ret = cache_block_group(cache, NULL, root, 0);
+                               if (!ret)
+                                       wait_block_group_cache_done(cache);
+                       }
+                       ret = btrfs_trim_block_group(cache,
+                                                    &group_trimmed,
+                                                    start,
+                                                    end,
+                                                    range->minlen);
+
+                       trimmed += group_trimmed;
+                       if (ret) {
+                               btrfs_put_block_group(cache);
+                               break;
+                       }
+               }
+
+               cache = next_block_group(fs_info->tree_root, cache);
+       }
+
+       range->len = trimmed;
+       return ret;
 }
index b5b92824a27137980287ad2418c565b425dd1bfa..20ddb28602a8fa0c0eb4c082966741f2f7fd15c8 100644 (file)
@@ -2192,6 +2192,8 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
        else
                write_flags = WRITE;
 
+       trace___extent_writepage(page, inode, wbc);
+
        WARN_ON(!PageLocked(page));
        pg_offset = i_size & (PAGE_CACHE_SIZE - 1);
        if (page->index > end_index ||
@@ -3690,6 +3692,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
                       "wanted %lu %lu\n", (unsigned long long)eb->start,
                       eb->len, start, min_len);
                WARN_ON(1);
+               return -EINVAL;
        }
 
        p = extent_buffer_page(eb, i);
index 9318dfefd59c50d8d87db399d70c5932e06f8d60..f62c5442835d1ab70da88d510ef6e073d050c794 100644 (file)
@@ -31,6 +31,7 @@
 #define EXTENT_BUFFER_UPTODATE 0
 #define EXTENT_BUFFER_BLOCKING 1
 #define EXTENT_BUFFER_DIRTY 2
+#define EXTENT_BUFFER_CORRUPT 3
 
 /* these are flags for extent_clear_unlock_delalloc */
 #define EXTENT_CLEAR_UNLOCK_PAGE 0x1
index 4f19a3e1bf328dc39ab763dc6f604095aa5d76c7..a6a9d4e8b491eee488316c97f6f975e167bf13db 100644 (file)
@@ -48,7 +48,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
        file_key.objectid = objectid;
        file_key.offset = pos;
        btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
@@ -169,6 +170,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 
        path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
        if (bio->bi_size > PAGE_CACHE_SIZE * 8)
                path->reada = 2;
 
index f447b783bb84ce25af44cb2276b3d49684948166..656bc0a892b14c6b6a420cda879e3b3e1fc9acf7 100644 (file)
  * and be replaced with calls into generic code.
  */
 static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
-                                        int write_bytes,
+                                        size_t write_bytes,
                                         struct page **prepared_pages,
                                         struct iov_iter *i)
 {
        size_t copied = 0;
+       size_t total_copied = 0;
        int pg = 0;
        int offset = pos & (PAGE_CACHE_SIZE - 1);
-       int total_copied = 0;
 
        while (write_bytes > 0) {
                size_t count = min_t(size_t,
@@ -88,9 +88,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
                total_copied += copied;
 
                /* Return to btrfs_file_aio_write to fault page */
-               if (unlikely(copied == 0)) {
+               if (unlikely(copied == 0))
                        break;
-               }
 
                if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
                        offset += copied;
@@ -109,8 +108,6 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
 {
        size_t i;
        for (i = 0; i < num_pages; i++) {
-               if (!pages[i])
-                       break;
                /* page checked is some magic around finding pages that
                 * have been modified without going through btrfs_set_page_dirty
                 * clear it here
@@ -130,13 +127,12 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
  * this also makes the decision about creating an inline extent vs
  * doing real data extents, marking pages dirty and delalloc as required.
  */
-static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans,
-                                  struct btrfs_root *root,
-                                  struct file *file,
-                                  struct page **pages,
-                                  size_t num_pages,
-                                  loff_t pos,
-                                  size_t write_bytes)
+static noinline int dirty_and_release_pages(struct btrfs_root *root,
+                                           struct file *file,
+                                           struct page **pages,
+                                           size_t num_pages,
+                                           loff_t pos,
+                                           size_t write_bytes)
 {
        int err = 0;
        int i;
@@ -154,7 +150,8 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans,
        end_of_last_block = start_pos + num_bytes - 1;
        err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
                                        NULL);
-       BUG_ON(err);
+       if (err)
+               return err;
 
        for (i = 0; i < num_pages; i++) {
                struct page *p = pages[i];
@@ -162,13 +159,14 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans,
                ClearPageChecked(p);
                set_page_dirty(p);
        }
-       if (end_pos > isize) {
+
+       /*
+        * we've only changed i_size in ram, and we haven't updated
+        * the disk i_size.  There is no need to log the inode
+        * at this time.
+        */
+       if (end_pos > isize)
                i_size_write(inode, end_pos);
-               /* we've only changed i_size in ram, and we haven't updated
-                * the disk i_size.  There is no need to log the inode
-                * at this time.
-                */
-       }
        return 0;
 }
 
@@ -610,6 +608,8 @@ again:
        key.offset = split;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+       if (ret < 0)
+               goto out;
        if (ret > 0 && path->slots[0] > 0)
                path->slots[0]--;
 
@@ -819,12 +819,11 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
        last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT;
 
        if (start_pos > inode->i_size) {
-               err = btrfs_cont_expand(inode, start_pos);
+               err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
                if (err)
                        return err;
        }
 
-       memset(pages, 0, num_pages * sizeof(struct page *));
 again:
        for (i = 0; i < num_pages; i++) {
                pages[i] = grab_cache_page(inode->i_mapping, index + i);
@@ -896,156 +895,71 @@ fail:
 
 }
 
-static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
-                                   const struct iovec *iov,
-                                   unsigned long nr_segs, loff_t pos)
+static noinline ssize_t __btrfs_buffered_write(struct file *file,
+                                              struct iov_iter *i,
+                                              loff_t pos)
 {
-       struct file *file = iocb->ki_filp;
        struct inode *inode = fdentry(file)->d_inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct page **pages = NULL;
-       struct iov_iter i;
-       loff_t *ppos = &iocb->ki_pos;
-       loff_t start_pos;
-       ssize_t num_written = 0;
-       ssize_t err = 0;
-       size_t count;
-       size_t ocount;
-       int ret = 0;
-       int nrptrs;
        unsigned long first_index;
        unsigned long last_index;
-       int will_write;
-       int buffered = 0;
-       int copied = 0;
-       int dirty_pages = 0;
-
-       will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
-                     (file->f_flags & O_DIRECT));
-
-       start_pos = pos;
-
-       vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
-
-       mutex_lock(&inode->i_mutex);
-
-       err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
-       if (err)
-               goto out;
-       count = ocount;
-
-       current->backing_dev_info = inode->i_mapping->backing_dev_info;
-       err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
-       if (err)
-               goto out;
-
-       if (count == 0)
-               goto out;
-
-       err = file_remove_suid(file);
-       if (err)
-               goto out;
-
-       /*
-        * If BTRFS flips readonly due to some impossible error
-        * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR),
-        * although we have opened a file as writable, we have
-        * to stop this write operation to ensure FS consistency.
-        */
-       if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
-               err = -EROFS;
-               goto out;
-       }
-
-       file_update_time(file);
-       BTRFS_I(inode)->sequence++;
-
-       if (unlikely(file->f_flags & O_DIRECT)) {
-               num_written = generic_file_direct_write(iocb, iov, &nr_segs,
-                                                       pos, ppos, count,
-                                                       ocount);
-               /*
-                * the generic O_DIRECT will update in-memory i_size after the
-                * DIOs are done.  But our endio handlers that update the on
-                * disk i_size never update past the in memory i_size.  So we
-                * need one more update here to catch any additions to the
-                * file
-                */
-               if (inode->i_size != BTRFS_I(inode)->disk_i_size) {
-                       btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
-                       mark_inode_dirty(inode);
-               }
-
-               if (num_written < 0) {
-                       ret = num_written;
-                       num_written = 0;
-                       goto out;
-               } else if (num_written == count) {
-                       /* pick up pos changes done by the generic code */
-                       pos = *ppos;
-                       goto out;
-               }
-               /*
-                * We are going to do buffered for the rest of the range, so we
-                * need to make sure to invalidate the buffered pages when we're
-                * done.
-                */
-               buffered = 1;
-               pos += num_written;
-       }
+       size_t num_written = 0;
+       int nrptrs;
+       int ret;
 
-       iov_iter_init(&i, iov, nr_segs, count, num_written);
-       nrptrs = min((iov_iter_count(&i) + PAGE_CACHE_SIZE - 1) /
+       nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) /
                     PAGE_CACHE_SIZE, PAGE_CACHE_SIZE /
                     (sizeof(struct page *)));
        pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
-       if (!pages) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       /* generic_write_checks can change our pos */
-       start_pos = pos;
+       if (!pages)
+               return -ENOMEM;
 
        first_index = pos >> PAGE_CACHE_SHIFT;
-       last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT;
+       last_index = (pos + iov_iter_count(i)) >> PAGE_CACHE_SHIFT;
 
-       while (iov_iter_count(&i) > 0) {
+       while (iov_iter_count(i) > 0) {
                size_t offset = pos & (PAGE_CACHE_SIZE - 1);
-               size_t write_bytes = min(iov_iter_count(&i),
+               size_t write_bytes = min(iov_iter_count(i),
                                         nrptrs * (size_t)PAGE_CACHE_SIZE -
                                         offset);
                size_t num_pages = (write_bytes + offset +
                                    PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+               size_t dirty_pages;
+               size_t copied;
 
                WARN_ON(num_pages > nrptrs);
-               memset(pages, 0, sizeof(struct page *) * nrptrs);
 
                /*
                 * Fault pages before locking them in prepare_pages
                 * to avoid recursive lock
                 */
-               if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+               if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) {
                        ret = -EFAULT;
-                       goto out;
+                       break;
                }
 
                ret = btrfs_delalloc_reserve_space(inode,
                                        num_pages << PAGE_CACHE_SHIFT);
                if (ret)
-                       goto out;
+                       break;
 
+               /*
+                * This is going to setup the pages array with the number of
+                * pages we want, so we don't really need to worry about the
+                * contents of pages from loop to loop
+                */
                ret = prepare_pages(root, file, pages, num_pages,
                                    pos, first_index, last_index,
                                    write_bytes);
                if (ret) {
                        btrfs_delalloc_release_space(inode,
                                        num_pages << PAGE_CACHE_SHIFT);
-                       goto out;
+                       break;
                }
 
                copied = btrfs_copy_from_user(pos, num_pages,
-                                          write_bytes, pages, &i);
+                                          write_bytes, pages, i);
 
                /*
                 * if we have trouble faulting in the pages, fall
@@ -1061,6 +975,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                                       PAGE_CACHE_SIZE - 1) >>
                                       PAGE_CACHE_SHIFT;
 
+               /*
+                * If we had a short copy we need to release the excess delaloc
+                * bytes we reserved.  We need to increment outstanding_extents
+                * because btrfs_delalloc_release_space will decrement it, but
+                * we still have an outstanding extent for the chunk we actually
+                * managed to copy.
+                */
                if (num_pages > dirty_pages) {
                        if (copied > 0)
                                atomic_inc(
@@ -1071,39 +992,157 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                }
 
                if (copied > 0) {
-                       dirty_and_release_pages(NULL, root, file, pages,
-                                               dirty_pages, pos, copied);
+                       ret = dirty_and_release_pages(root, file, pages,
+                                                     dirty_pages, pos,
+                                                     copied);
+                       if (ret) {
+                               btrfs_delalloc_release_space(inode,
+                                       dirty_pages << PAGE_CACHE_SHIFT);
+                               btrfs_drop_pages(pages, num_pages);
+                               break;
+                       }
                }
 
                btrfs_drop_pages(pages, num_pages);
 
-               if (copied > 0) {
-                       if (will_write) {
-                               filemap_fdatawrite_range(inode->i_mapping, pos,
-                                                        pos + copied - 1);
-                       } else {
-                               balance_dirty_pages_ratelimited_nr(
-                                                       inode->i_mapping,
-                                                       dirty_pages);
-                               if (dirty_pages <
-                               (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
-                                       btrfs_btree_balance_dirty(root, 1);
-                               btrfs_throttle(root);
-                       }
-               }
+               cond_resched();
+
+               balance_dirty_pages_ratelimited_nr(inode->i_mapping,
+                                                  dirty_pages);
+               if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+                       btrfs_btree_balance_dirty(root, 1);
+               btrfs_throttle(root);
 
                pos += copied;
                num_written += copied;
+       }
 
-               cond_resched();
+       kfree(pages);
+
+       return num_written ? num_written : ret;
+}
+
+static ssize_t __btrfs_direct_write(struct kiocb *iocb,
+                                   const struct iovec *iov,
+                                   unsigned long nr_segs, loff_t pos,
+                                   loff_t *ppos, size_t count, size_t ocount)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = fdentry(file)->d_inode;
+       struct iov_iter i;
+       ssize_t written;
+       ssize_t written_buffered;
+       loff_t endbyte;
+       int err;
+
+       written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos,
+                                           count, ocount);
+
+       /*
+        * the generic O_DIRECT will update in-memory i_size after the
+        * DIOs are done.  But our endio handlers that update the on
+        * disk i_size never update past the in memory i_size.  So we
+        * need one more update here to catch any additions to the
+        * file
+        */
+       if (inode->i_size != BTRFS_I(inode)->disk_i_size) {
+               btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
+               mark_inode_dirty(inode);
        }
+
+       if (written < 0 || written == count)
+               return written;
+
+       pos += written;
+       count -= written;
+       iov_iter_init(&i, iov, nr_segs, count, written);
+       written_buffered = __btrfs_buffered_write(file, &i, pos);
+       if (written_buffered < 0) {
+               err = written_buffered;
+               goto out;
+       }
+       endbyte = pos + written_buffered - 1;
+       err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
+       if (err)
+               goto out;
+       written += written_buffered;
+       *ppos = pos + written_buffered;
+       invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT,
+                                endbyte >> PAGE_CACHE_SHIFT);
 out:
-       mutex_unlock(&inode->i_mutex);
-       if (ret)
-               err = ret;
+       return written ? written : err;
+}
 
-       kfree(pages);
-       *ppos = pos;
+static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
+                                   const struct iovec *iov,
+                                   unsigned long nr_segs, loff_t pos)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = fdentry(file)->d_inode;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       loff_t *ppos = &iocb->ki_pos;
+       ssize_t num_written = 0;
+       ssize_t err = 0;
+       size_t count, ocount;
+
+       vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+       mutex_lock(&inode->i_mutex);
+
+       err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
+       if (err) {
+               mutex_unlock(&inode->i_mutex);
+               goto out;
+       }
+       count = ocount;
+
+       current->backing_dev_info = inode->i_mapping->backing_dev_info;
+       err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+       if (err) {
+               mutex_unlock(&inode->i_mutex);
+               goto out;
+       }
+
+       if (count == 0) {
+               mutex_unlock(&inode->i_mutex);
+               goto out;
+       }
+
+       err = file_remove_suid(file);
+       if (err) {
+               mutex_unlock(&inode->i_mutex);
+               goto out;
+       }
+
+       /*
+        * If BTRFS flips readonly due to some impossible error
+        * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR),
+        * although we have opened a file as writable, we have
+        * to stop this write operation to ensure FS consistency.
+        */
+       if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
+               mutex_unlock(&inode->i_mutex);
+               err = -EROFS;
+               goto out;
+       }
+
+       file_update_time(file);
+       BTRFS_I(inode)->sequence++;
+
+       if (unlikely(file->f_flags & O_DIRECT)) {
+               num_written = __btrfs_direct_write(iocb, iov, nr_segs,
+                                                  pos, ppos, count, ocount);
+       } else {
+               struct iov_iter i;
+
+               iov_iter_init(&i, iov, nr_segs, count, num_written);
+
+               num_written = __btrfs_buffered_write(file, &i, pos);
+               if (num_written > 0)
+                       *ppos = pos + num_written;
+       }
+
+       mutex_unlock(&inode->i_mutex);
 
        /*
         * we want to make sure fsync finds this change
@@ -1118,43 +1157,12 @@ out:
         * one running right now.
         */
        BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
-
-       if (num_written > 0 && will_write) {
-               struct btrfs_trans_handle *trans;
-
-               err = btrfs_wait_ordered_range(inode, start_pos, num_written);
-               if (err)
+       if (num_written > 0 || num_written == -EIOCBQUEUED) {
+               err = generic_write_sync(file, pos, num_written);
+               if (err < 0 && num_written > 0)
                        num_written = err;
-
-               if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
-                       trans = btrfs_start_transaction(root, 0);
-                       if (IS_ERR(trans)) {
-                               num_written = PTR_ERR(trans);
-                               goto done;
-                       }
-                       mutex_lock(&inode->i_mutex);
-                       ret = btrfs_log_dentry_safe(trans, root,
-                                                   file->f_dentry);
-                       mutex_unlock(&inode->i_mutex);
-                       if (ret == 0) {
-                               ret = btrfs_sync_log(trans, root);
-                               if (ret == 0)
-                                       btrfs_end_transaction(trans, root);
-                               else
-                                       btrfs_commit_transaction(trans, root);
-                       } else if (ret != BTRFS_NO_LOG_SYNC) {
-                               btrfs_commit_transaction(trans, root);
-                       } else {
-                               btrfs_end_transaction(trans, root);
-                       }
-               }
-               if (file->f_flags & O_DIRECT && buffered) {
-                       invalidate_mapping_pages(inode->i_mapping,
-                             start_pos >> PAGE_CACHE_SHIFT,
-                            (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT);
-               }
        }
-done:
+out:
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
 }
@@ -1197,6 +1205,7 @@ int btrfs_sync_file(struct file *file, int datasync)
        int ret = 0;
        struct btrfs_trans_handle *trans;
 
+       trace_btrfs_sync_file(file, datasync);
 
        /* we wait first, since the writeback may change the inode */
        root->log_batch++;
@@ -1324,7 +1333,8 @@ static long btrfs_fallocate(struct file *file, int mode,
                goto out;
 
        if (alloc_start > inode->i_size) {
-               ret = btrfs_cont_expand(inode, alloc_start);
+               ret = btrfs_cont_expand(inode, i_size_read(inode),
+                                       alloc_start);
                if (ret)
                        goto out;
        }
index a0390657451b920dac20e17aa04bcc86a0b583e0..0037427d8a9d27b6a14b980898b01ca39209f51a 100644 (file)
@@ -393,7 +393,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                                break;
 
                        need_loop = 1;
-                       e = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS);
+                       e = kmem_cache_zalloc(btrfs_free_space_cachep,
+                                             GFP_NOFS);
                        if (!e) {
                                kunmap(page);
                                unlock_page(page);
@@ -405,7 +406,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                        e->bytes = le64_to_cpu(entry->bytes);
                        if (!e->bytes) {
                                kunmap(page);
-                               kfree(e);
+                               kmem_cache_free(btrfs_free_space_cachep, e);
                                unlock_page(page);
                                page_cache_release(page);
                                goto free_cache;
@@ -420,7 +421,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                                e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
                                if (!e->bitmap) {
                                        kunmap(page);
-                                       kfree(e);
+                                       kmem_cache_free(
+                                               btrfs_free_space_cachep, e);
                                        unlock_page(page);
                                        page_cache_release(page);
                                        goto free_cache;
@@ -1187,7 +1189,7 @@ static void free_bitmap(struct btrfs_block_group_cache *block_group,
 {
        unlink_free_space(block_group, bitmap_info);
        kfree(bitmap_info->bitmap);
-       kfree(bitmap_info);
+       kmem_cache_free(btrfs_free_space_cachep, bitmap_info);
        block_group->total_bitmaps--;
        recalculate_thresholds(block_group);
 }
@@ -1285,9 +1287,22 @@ static int insert_into_bitmap(struct btrfs_block_group_cache *block_group,
         * If we are below the extents threshold then we can add this as an
         * extent, and don't have to deal with the bitmap
         */
-       if (block_group->free_extents < block_group->extents_thresh &&
-           info->bytes > block_group->sectorsize * 4)
-               return 0;
+       if (block_group->free_extents < block_group->extents_thresh) {
+               /*
+                * If this block group has some small extents we don't want to
+                * use up all of our free slots in the cache with them, we want
+                * to reserve them to larger extents, however if we have plent
+                * of cache left then go ahead an dadd them, no sense in adding
+                * the overhead of a bitmap if we don't have to.
+                */
+               if (info->bytes <= block_group->sectorsize * 4) {
+                       if (block_group->free_extents * 2 <=
+                           block_group->extents_thresh)
+                               return 0;
+               } else {
+                       return 0;
+               }
+       }
 
        /*
         * some block groups are so tiny they can't be enveloped by a bitmap, so
@@ -1342,8 +1357,8 @@ new_bitmap:
 
                /* no pre-allocated info, allocate a new one */
                if (!info) {
-                       info = kzalloc(sizeof(struct btrfs_free_space),
-                                      GFP_NOFS);
+                       info = kmem_cache_zalloc(btrfs_free_space_cachep,
+                                                GFP_NOFS);
                        if (!info) {
                                spin_lock(&block_group->tree_lock);
                                ret = -ENOMEM;
@@ -1365,7 +1380,7 @@ out:
        if (info) {
                if (info->bitmap)
                        kfree(info->bitmap);
-               kfree(info);
+               kmem_cache_free(btrfs_free_space_cachep, info);
        }
 
        return ret;
@@ -1398,7 +1413,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group,
                else
                        __unlink_free_space(block_group, right_info);
                info->bytes += right_info->bytes;
-               kfree(right_info);
+               kmem_cache_free(btrfs_free_space_cachep, right_info);
                merged = true;
        }
 
@@ -1410,7 +1425,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group,
                        __unlink_free_space(block_group, left_info);
                info->offset = left_info->offset;
                info->bytes += left_info->bytes;
-               kfree(left_info);
+               kmem_cache_free(btrfs_free_space_cachep, left_info);
                merged = true;
        }
 
@@ -1423,7 +1438,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
        struct btrfs_free_space *info;
        int ret = 0;
 
-       info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS);
+       info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS);
        if (!info)
                return -ENOMEM;
 
@@ -1450,7 +1465,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
 link:
        ret = link_free_space(block_group, info);
        if (ret)
-               kfree(info);
+               kmem_cache_free(btrfs_free_space_cachep, info);
 out:
        spin_unlock(&block_group->tree_lock);
 
@@ -1520,7 +1535,7 @@ again:
                        kfree(info->bitmap);
                        block_group->total_bitmaps--;
                }
-               kfree(info);
+               kmem_cache_free(btrfs_free_space_cachep, info);
                goto out_lock;
        }
 
@@ -1556,7 +1571,7 @@ again:
                        /* the hole we're creating ends at the end
                         * of the info struct, just free the info
                         */
-                       kfree(info);
+                       kmem_cache_free(btrfs_free_space_cachep, info);
                }
                spin_unlock(&block_group->tree_lock);
 
@@ -1629,30 +1644,28 @@ __btrfs_return_cluster_to_free_space(
 {
        struct btrfs_free_space *entry;
        struct rb_node *node;
-       bool bitmap;
 
        spin_lock(&cluster->lock);
        if (cluster->block_group != block_group)
                goto out;
 
-       bitmap = cluster->points_to_bitmap;
        cluster->block_group = NULL;
        cluster->window_start = 0;
        list_del_init(&cluster->block_group_list);
-       cluster->points_to_bitmap = false;
-
-       if (bitmap)
-               goto out;
 
        node = rb_first(&cluster->root);
        while (node) {
+               bool bitmap;
+
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
                node = rb_next(&entry->offset_index);
                rb_erase(&entry->offset_index, &cluster->root);
-               BUG_ON(entry->bitmap);
-               try_merge_free_space(block_group, entry, false);
+
+               bitmap = (entry->bitmap != NULL);
+               if (!bitmap)
+                       try_merge_free_space(block_group, entry, false);
                tree_insert_offset(&block_group->free_space_offset,
-                                  entry->offset, &entry->offset_index, 0);
+                                  entry->offset, &entry->offset_index, bitmap);
        }
        cluster->root = RB_ROOT;
 
@@ -1689,7 +1702,7 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
                unlink_free_space(block_group, info);
                if (info->bitmap)
                        kfree(info->bitmap);
-               kfree(info);
+               kmem_cache_free(btrfs_free_space_cachep, info);
                if (need_resched()) {
                        spin_unlock(&block_group->tree_lock);
                        cond_resched();
@@ -1722,7 +1735,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
                entry->offset += bytes;
                entry->bytes -= bytes;
                if (!entry->bytes)
-                       kfree(entry);
+                       kmem_cache_free(btrfs_free_space_cachep, entry);
                else
                        link_free_space(block_group, entry);
        }
@@ -1775,50 +1788,24 @@ int btrfs_return_cluster_to_free_space(
 
 static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
                                   struct btrfs_free_cluster *cluster,
+                                  struct btrfs_free_space *entry,
                                   u64 bytes, u64 min_start)
 {
-       struct btrfs_free_space *entry;
        int err;
        u64 search_start = cluster->window_start;
        u64 search_bytes = bytes;
        u64 ret = 0;
 
-       spin_lock(&block_group->tree_lock);
-       spin_lock(&cluster->lock);
-
-       if (!cluster->points_to_bitmap)
-               goto out;
-
-       if (cluster->block_group != block_group)
-               goto out;
-
-       /*
-        * search_start is the beginning of the bitmap, but at some point it may
-        * be a good idea to point to the actual start of the free area in the
-        * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only
-        * to 1 to make sure we get the bitmap entry
-        */
-       entry = tree_search_offset(block_group,
-                                  offset_to_bitmap(block_group, search_start),
-                                  1, 0);
-       if (!entry || !entry->bitmap)
-               goto out;
-
        search_start = min_start;
        search_bytes = bytes;
 
        err = search_bitmap(block_group, entry, &search_start,
                            &search_bytes);
        if (err)
-               goto out;
+               return 0;
 
        ret = search_start;
        bitmap_clear_bits(block_group, entry, ret, bytes);
-       if (entry->bytes == 0)
-               free_bitmap(block_group, entry);
-out:
-       spin_unlock(&cluster->lock);
-       spin_unlock(&block_group->tree_lock);
 
        return ret;
 }
@@ -1836,10 +1823,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
        struct rb_node *node;
        u64 ret = 0;
 
-       if (cluster->points_to_bitmap)
-               return btrfs_alloc_from_bitmap(block_group, cluster, bytes,
-                                              min_start);
-
        spin_lock(&cluster->lock);
        if (bytes > cluster->max_size)
                goto out;
@@ -1852,9 +1835,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                goto out;
 
        entry = rb_entry(node, struct btrfs_free_space, offset_index);
-
        while(1) {
-               if (entry->bytes < bytes || entry->offset < min_start) {
+               if (entry->bytes < bytes ||
+                   (!entry->bitmap && entry->offset < min_start)) {
                        struct rb_node *node;
 
                        node = rb_next(&entry->offset_index);
@@ -1864,10 +1847,27 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                                         offset_index);
                        continue;
                }
-               ret = entry->offset;
 
-               entry->offset += bytes;
-               entry->bytes -= bytes;
+               if (entry->bitmap) {
+                       ret = btrfs_alloc_from_bitmap(block_group,
+                                                     cluster, entry, bytes,
+                                                     min_start);
+                       if (ret == 0) {
+                               struct rb_node *node;
+                               node = rb_next(&entry->offset_index);
+                               if (!node)
+                                       break;
+                               entry = rb_entry(node, struct btrfs_free_space,
+                                                offset_index);
+                               continue;
+                       }
+               } else {
+
+                       ret = entry->offset;
+
+                       entry->offset += bytes;
+                       entry->bytes -= bytes;
+               }
 
                if (entry->bytes == 0)
                        rb_erase(&entry->offset_index, &cluster->root);
@@ -1884,7 +1884,12 @@ out:
        block_group->free_space -= bytes;
        if (entry->bytes == 0) {
                block_group->free_extents--;
-               kfree(entry);
+               if (entry->bitmap) {
+                       kfree(entry->bitmap);
+                       block_group->total_bitmaps--;
+                       recalculate_thresholds(block_group);
+               }
+               kmem_cache_free(btrfs_free_space_cachep, entry);
        }
 
        spin_unlock(&block_group->tree_lock);
@@ -1904,12 +1909,13 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group,
        unsigned long found_bits;
        unsigned long start = 0;
        unsigned long total_found = 0;
+       int ret;
        bool found = false;
 
        i = offset_to_bit(entry->offset, block_group->sectorsize,
                          max_t(u64, offset, entry->offset));
-       search_bits = bytes_to_bits(min_bytes, block_group->sectorsize);
-       total_bits = bytes_to_bits(bytes, block_group->sectorsize);
+       search_bits = bytes_to_bits(bytes, block_group->sectorsize);
+       total_bits = bytes_to_bits(min_bytes, block_group->sectorsize);
 
 again:
        found_bits = 0;
@@ -1926,7 +1932,7 @@ again:
        }
 
        if (!found_bits)
-               return -1;
+               return -ENOSPC;
 
        if (!found) {
                start = i;
@@ -1950,189 +1956,208 @@ again:
 
        cluster->window_start = start * block_group->sectorsize +
                entry->offset;
-       cluster->points_to_bitmap = true;
+       rb_erase(&entry->offset_index, &block_group->free_space_offset);
+       ret = tree_insert_offset(&cluster->root, entry->offset,
+                                &entry->offset_index, 1);
+       BUG_ON(ret);
 
        return 0;
 }
 
 /*
- * here we try to find a cluster of blocks in a block group.  The goal
- * is to find at least bytes free and up to empty_size + bytes free.
- * We might not find them all in one contiguous area.
- *
- * returns zero and sets up cluster if things worked out, otherwise
- * it returns -enospc
+ * This searches the block group for just extents to fill the cluster with.
  */
-int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *root,
-                            struct btrfs_block_group_cache *block_group,
-                            struct btrfs_free_cluster *cluster,
-                            u64 offset, u64 bytes, u64 empty_size)
+static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
+                                  struct btrfs_free_cluster *cluster,
+                                  u64 offset, u64 bytes, u64 min_bytes)
 {
+       struct btrfs_free_space *first = NULL;
        struct btrfs_free_space *entry = NULL;
+       struct btrfs_free_space *prev = NULL;
+       struct btrfs_free_space *last;
        struct rb_node *node;
-       struct btrfs_free_space *next;
-       struct btrfs_free_space *last = NULL;
-       u64 min_bytes;
        u64 window_start;
        u64 window_free;
-       u64 max_extent = 0;
-       bool found_bitmap = false;
-       int ret;
+       u64 max_extent;
+       u64 max_gap = 128 * 1024;
 
-       /* for metadata, allow allocates with more holes */
-       if (btrfs_test_opt(root, SSD_SPREAD)) {
-               min_bytes = bytes + empty_size;
-       } else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) {
-               /*
-                * we want to do larger allocations when we are
-                * flushing out the delayed refs, it helps prevent
-                * making more work as we go along.
-                */
-               if (trans->transaction->delayed_refs.flushing)
-                       min_bytes = max(bytes, (bytes + empty_size) >> 1);
-               else
-                       min_bytes = max(bytes, (bytes + empty_size) >> 4);
-       } else
-               min_bytes = max(bytes, (bytes + empty_size) >> 2);
-
-       spin_lock(&block_group->tree_lock);
-       spin_lock(&cluster->lock);
-
-       /* someone already found a cluster, hooray */
-       if (cluster->block_group) {
-               ret = 0;
-               goto out;
-       }
-again:
-       entry = tree_search_offset(block_group, offset, found_bitmap, 1);
-       if (!entry) {
-               ret = -ENOSPC;
-               goto out;
-       }
+       entry = tree_search_offset(block_group, offset, 0, 1);
+       if (!entry)
+               return -ENOSPC;
 
        /*
-        * If found_bitmap is true, we exhausted our search for extent entries,
-        * and we just want to search all of the bitmaps that we can find, and
-        * ignore any extent entries we find.
+        * We don't want bitmaps, so just move along until we find a normal
+        * extent entry.
         */
-       while (entry->bitmap || found_bitmap ||
-              (!entry->bitmap && entry->bytes < min_bytes)) {
-               struct rb_node *node = rb_next(&entry->offset_index);
-
-               if (entry->bitmap && entry->bytes > bytes + empty_size) {
-                       ret = btrfs_bitmap_cluster(block_group, entry, cluster,
-                                                  offset, bytes + empty_size,
-                                                  min_bytes);
-                       if (!ret)
-                               goto got_it;
-               }
-
-               if (!node) {
-                       ret = -ENOSPC;
-                       goto out;
-               }
+       while (entry->bitmap) {
+               node = rb_next(&entry->offset_index);
+               if (!node)
+                       return -ENOSPC;
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
        }
 
-       /*
-        * We already searched all the extent entries from the passed in offset
-        * to the end and didn't find enough space for the cluster, and we also
-        * didn't find any bitmaps that met our criteria, just go ahead and exit
-        */
-       if (found_bitmap) {
-               ret = -ENOSPC;
-               goto out;
-       }
-
-       cluster->points_to_bitmap = false;
        window_start = entry->offset;
        window_free = entry->bytes;
-       last = entry;
        max_extent = entry->bytes;
+       first = entry;
+       last = entry;
+       prev = entry;
 
-       while (1) {
-               /* out window is just right, lets fill it */
-               if (window_free >= bytes + empty_size)
-                       break;
-
-               node = rb_next(&last->offset_index);
-               if (!node) {
-                       if (found_bitmap)
-                               goto again;
-                       ret = -ENOSPC;
-                       goto out;
-               }
-               next = rb_entry(node, struct btrfs_free_space, offset_index);
+       while (window_free <= min_bytes) {
+               node = rb_next(&entry->offset_index);
+               if (!node)
+                       return -ENOSPC;
+               entry = rb_entry(node, struct btrfs_free_space, offset_index);
 
-               /*
-                * we found a bitmap, so if this search doesn't result in a
-                * cluster, we know to go and search again for the bitmaps and
-                * start looking for space there
-                */
-               if (next->bitmap) {
-                       if (!found_bitmap)
-                               offset = next->offset;
-                       found_bitmap = true;
-                       last = next;
+               if (entry->bitmap)
                        continue;
-               }
-
                /*
                 * we haven't filled the empty size and the window is
                 * very large.  reset and try again
                 */
-               if (next->offset - (last->offset + last->bytes) > 128 * 1024 ||
-                   next->offset - window_start > (bytes + empty_size) * 2) {
-                       entry = next;
+               if (entry->offset - (prev->offset + prev->bytes) > max_gap ||
+                   entry->offset - window_start > (min_bytes * 2)) {
+                       first = entry;
                        window_start = entry->offset;
                        window_free = entry->bytes;
                        last = entry;
                        max_extent = entry->bytes;
                } else {
-                       last = next;
-                       window_free += next->bytes;
+                       last = entry;
+                       window_free += entry->bytes;
                        if (entry->bytes > max_extent)
                                max_extent = entry->bytes;
                }
+               prev = entry;
        }
 
-       cluster->window_start = entry->offset;
+       cluster->window_start = first->offset;
+
+       node = &first->offset_index;
 
        /*
         * now we've found our entries, pull them out of the free space
         * cache and put them into the cluster rbtree
-        *
-        * The cluster includes an rbtree, but only uses the offset index
-        * of each free space cache entry.
         */
-       while (1) {
+       do {
+               int ret;
+
+               entry = rb_entry(node, struct btrfs_free_space, offset_index);
                node = rb_next(&entry->offset_index);
-               if (entry->bitmap && node) {
-                       entry = rb_entry(node, struct btrfs_free_space,
-                                        offset_index);
+               if (entry->bitmap)
                        continue;
-               } else if (entry->bitmap && !node) {
-                       break;
-               }
 
                rb_erase(&entry->offset_index, &block_group->free_space_offset);
                ret = tree_insert_offset(&cluster->root, entry->offset,
                                         &entry->offset_index, 0);
                BUG_ON(ret);
+       } while (node && entry != last);
 
-               if (!node || entry == last)
-                       break;
+       cluster->max_size = max_extent;
+
+       return 0;
+}
+
+/*
+ * This specifically looks for bitmaps that may work in the cluster, we assume
+ * that we have already failed to find extents that will work.
+ */
+static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
+                               struct btrfs_free_cluster *cluster,
+                               u64 offset, u64 bytes, u64 min_bytes)
+{
+       struct btrfs_free_space *entry;
+       struct rb_node *node;
+       int ret = -ENOSPC;
+
+       if (block_group->total_bitmaps == 0)
+               return -ENOSPC;
 
+       entry = tree_search_offset(block_group,
+                                  offset_to_bitmap(block_group, offset),
+                                  0, 1);
+       if (!entry)
+               return -ENOSPC;
+
+       node = &entry->offset_index;
+       do {
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
+               node = rb_next(&entry->offset_index);
+               if (!entry->bitmap)
+                       continue;
+               if (entry->bytes < min_bytes)
+                       continue;
+               ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
+                                          bytes, min_bytes);
+       } while (ret && node);
+
+       return ret;
+}
+
+/*
+ * here we try to find a cluster of blocks in a block group.  The goal
+ * is to find at least bytes free and up to empty_size + bytes free.
+ * We might not find them all in one contiguous area.
+ *
+ * returns zero and sets up cluster if things worked out, otherwise
+ * it returns -enospc
+ */
+int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
+                            struct btrfs_root *root,
+                            struct btrfs_block_group_cache *block_group,
+                            struct btrfs_free_cluster *cluster,
+                            u64 offset, u64 bytes, u64 empty_size)
+{
+       u64 min_bytes;
+       int ret;
+
+       /* for metadata, allow allocates with more holes */
+       if (btrfs_test_opt(root, SSD_SPREAD)) {
+               min_bytes = bytes + empty_size;
+       } else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) {
+               /*
+                * we want to do larger allocations when we are
+                * flushing out the delayed refs, it helps prevent
+                * making more work as we go along.
+                */
+               if (trans->transaction->delayed_refs.flushing)
+                       min_bytes = max(bytes, (bytes + empty_size) >> 1);
+               else
+                       min_bytes = max(bytes, (bytes + empty_size) >> 4);
+       } else
+               min_bytes = max(bytes, (bytes + empty_size) >> 2);
+
+       spin_lock(&block_group->tree_lock);
+
+       /*
+        * If we know we don't have enough space to make a cluster don't even
+        * bother doing all the work to try and find one.
+        */
+       if (block_group->free_space < min_bytes) {
+               spin_unlock(&block_group->tree_lock);
+               return -ENOSPC;
        }
 
-       cluster->max_size = max_extent;
-got_it:
-       ret = 0;
-       atomic_inc(&block_group->count);
-       list_add_tail(&cluster->block_group_list, &block_group->cluster_list);
-       cluster->block_group = block_group;
+       spin_lock(&cluster->lock);
+
+       /* someone already found a cluster, hooray */
+       if (cluster->block_group) {
+               ret = 0;
+               goto out;
+       }
+
+       ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes,
+                                     min_bytes);
+       if (ret)
+               ret = setup_cluster_bitmap(block_group, cluster, offset,
+                                          bytes, min_bytes);
+
+       if (!ret) {
+               atomic_inc(&block_group->count);
+               list_add_tail(&cluster->block_group_list,
+                             &block_group->cluster_list);
+               cluster->block_group = block_group;
+       }
 out:
        spin_unlock(&cluster->lock);
        spin_unlock(&block_group->tree_lock);
@@ -2149,8 +2174,99 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster)
        spin_lock_init(&cluster->refill_lock);
        cluster->root = RB_ROOT;
        cluster->max_size = 0;
-       cluster->points_to_bitmap = false;
        INIT_LIST_HEAD(&cluster->block_group_list);
        cluster->block_group = NULL;
 }
 
+int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
+                          u64 *trimmed, u64 start, u64 end, u64 minlen)
+{
+       struct btrfs_free_space *entry = NULL;
+       struct btrfs_fs_info *fs_info = block_group->fs_info;
+       u64 bytes = 0;
+       u64 actually_trimmed;
+       int ret = 0;
+
+       *trimmed = 0;
+
+       while (start < end) {
+               spin_lock(&block_group->tree_lock);
+
+               if (block_group->free_space < minlen) {
+                       spin_unlock(&block_group->tree_lock);
+                       break;
+               }
+
+               entry = tree_search_offset(block_group, start, 0, 1);
+               if (!entry)
+                       entry = tree_search_offset(block_group,
+                                                  offset_to_bitmap(block_group,
+                                                                   start),
+                                                  1, 1);
+
+               if (!entry || entry->offset >= end) {
+                       spin_unlock(&block_group->tree_lock);
+                       break;
+               }
+
+               if (entry->bitmap) {
+                       ret = search_bitmap(block_group, entry, &start, &bytes);
+                       if (!ret) {
+                               if (start >= end) {
+                                       spin_unlock(&block_group->tree_lock);
+                                       break;
+                               }
+                               bytes = min(bytes, end - start);
+                               bitmap_clear_bits(block_group, entry,
+                                                 start, bytes);
+                               if (entry->bytes == 0)
+                                       free_bitmap(block_group, entry);
+                       } else {
+                               start = entry->offset + BITS_PER_BITMAP *
+                                       block_group->sectorsize;
+                               spin_unlock(&block_group->tree_lock);
+                               ret = 0;
+                               continue;
+                       }
+               } else {
+                       start = entry->offset;
+                       bytes = min(entry->bytes, end - start);
+                       unlink_free_space(block_group, entry);
+                       kfree(entry);
+               }
+
+               spin_unlock(&block_group->tree_lock);
+
+               if (bytes >= minlen) {
+                       int update_ret;
+                       update_ret = btrfs_update_reserved_bytes(block_group,
+                                                                bytes, 1, 1);
+
+                       ret = btrfs_error_discard_extent(fs_info->extent_root,
+                                                        start,
+                                                        bytes,
+                                                        &actually_trimmed);
+
+                       btrfs_add_free_space(block_group,
+                                            start, bytes);
+                       if (!update_ret)
+                               btrfs_update_reserved_bytes(block_group,
+                                                           bytes, 0, 1);
+
+                       if (ret)
+                               break;
+                       *trimmed += actually_trimmed;
+               }
+               start += bytes;
+               bytes = 0;
+
+               if (fatal_signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+
+               cond_resched();
+       }
+
+       return ret;
+}
index e49ca5c321b571e5886c557e76d131441f1acc87..65c3b935289f3814747947e8967e091cf0e4b1a3 100644 (file)
@@ -68,4 +68,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
 int btrfs_return_cluster_to_free_space(
                               struct btrfs_block_group_cache *block_group,
                               struct btrfs_free_cluster *cluster);
+int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
+                          u64 *trimmed, u64 start, u64 end, u64 minlen);
 #endif
index c56eb5909172956da6354eef29ea36f7f698a8fc..c05a08f4c4111fdfa4157e9447005523f256fb67 100644 (file)
@@ -30,7 +30,8 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
        int slot;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        search_key.objectid = BTRFS_LAST_FREE_OBJECTID;
        search_key.type = -1;
index 119520bdb9a540d8dc0f9bcf94d66b01df0af068..93c28a1d6bdc758b5270e6b8c7b448d106f1ab7b 100644 (file)
@@ -50,6 +50,7 @@
 #include "tree-log.h"
 #include "compression.h"
 #include "locking.h"
+#include "free-space-cache.h"
 
 struct btrfs_iget_args {
        u64 ino;
@@ -70,6 +71,7 @@ static struct kmem_cache *btrfs_inode_cachep;
 struct kmem_cache *btrfs_trans_handle_cachep;
 struct kmem_cache *btrfs_transaction_cachep;
 struct kmem_cache *btrfs_path_cachep;
+struct kmem_cache *btrfs_free_space_cachep;
 
 #define S_SHIFT 12
 static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -82,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
        [S_IFLNK >> S_SHIFT]    = BTRFS_FT_SYMLINK,
 };
 
-static void btrfs_truncate(struct inode *inode);
+static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
 static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
@@ -288,6 +291,7 @@ static noinline int add_async_extent(struct async_cow *cow,
        struct async_extent *async_extent;
 
        async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS);
+       BUG_ON(!async_extent);
        async_extent->start = start;
        async_extent->ram_size = ram_size;
        async_extent->compressed_size = compressed_size;
@@ -382,9 +386,11 @@ again:
         */
        if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) &&
            (btrfs_test_opt(root, COMPRESS) ||
-            (BTRFS_I(inode)->force_compress))) {
+            (BTRFS_I(inode)->force_compress) ||
+            (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) {
                WARN_ON(pages);
                pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+               BUG_ON(!pages);
 
                if (BTRFS_I(inode)->force_compress)
                        compress_type = BTRFS_I(inode)->force_compress;
@@ -1254,7 +1260,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
                ret = run_delalloc_nocow(inode, locked_page, start, end,
                                         page_started, 0, nr_written);
        else if (!btrfs_test_opt(root, COMPRESS) &&
-                !(BTRFS_I(inode)->force_compress))
+                !(BTRFS_I(inode)->force_compress) &&
+                !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))
                ret = cow_file_range(inode, locked_page, start, end,
                                      page_started, nr_written, 1);
        else
@@ -1461,8 +1468,11 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                if (bio_flags & EXTENT_BIO_COMPRESSED) {
                        return btrfs_submit_compressed_read(inode, bio,
                                                    mirror_num, bio_flags);
-               } else if (!skip_sum)
-                       btrfs_lookup_bio_sums(root, inode, bio, NULL);
+               } else if (!skip_sum) {
+                       ret = btrfs_lookup_bio_sums(root, inode, bio, NULL);
+                       if (ret)
+                               return ret;
+               }
                goto mapit;
        } else if (!skip_sum) {
                /* csum items have already been cloned */
@@ -1785,6 +1795,8 @@ out:
 static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
                                struct extent_state *state, int uptodate)
 {
+       trace_btrfs_writepage_end_io_hook(page, start, end, uptodate);
+
        ClearPagePrivate2(page);
        return btrfs_finish_ordered_io(page->mapping->host, start, end);
 }
@@ -1895,10 +1907,10 @@ static int btrfs_io_failed_hook(struct bio *failed_bio,
        else
                rw = READ;
 
-       BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio,
+       ret = BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio,
                                                      failrec->last_mirror,
                                                      failrec->bio_flags, 0);
-       return 0;
+       return ret;
 }
 
 /*
@@ -2282,7 +2294,7 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode)
  * this cleans up any orphans that may be left on the list from the last use
  * of this root.
  */
-void btrfs_orphan_cleanup(struct btrfs_root *root)
+int btrfs_orphan_cleanup(struct btrfs_root *root)
 {
        struct btrfs_path *path;
        struct extent_buffer *leaf;
@@ -2292,10 +2304,13 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
        int ret = 0, nr_unlink = 0, nr_truncate = 0;
 
        if (cmpxchg(&root->orphan_cleanup_state, 0, ORPHAN_CLEANUP_STARTED))
-               return;
+               return 0;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
        path->reada = -1;
 
        key.objectid = BTRFS_ORPHAN_OBJECTID;
@@ -2304,11 +2319,8 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
 
        while (1) {
                ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-               if (ret < 0) {
-                       printk(KERN_ERR "Error searching slot for orphan: %d"
-                              "\n", ret);
-                       break;
-               }
+               if (ret < 0)
+                       goto out;
 
                /*
                 * if ret == 0 means we found what we were searching for, which
@@ -2316,6 +2328,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
                 * find the key and see if we have stuff that matches
                 */
                if (ret > 0) {
+                       ret = 0;
                        if (path->slots[0] == 0)
                                break;
                        path->slots[0]--;
@@ -2343,7 +2356,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
                found_key.type = BTRFS_INODE_ITEM_KEY;
                found_key.offset = 0;
                inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
-               BUG_ON(IS_ERR(inode));
+               if (IS_ERR(inode)) {
+                       ret = PTR_ERR(inode);
+                       goto out;
+               }
 
                /*
                 * add this inode to the orphan list so btrfs_orphan_del does
@@ -2361,7 +2377,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
                 */
                if (is_bad_inode(inode)) {
                        trans = btrfs_start_transaction(root, 0);
-                       BUG_ON(IS_ERR(trans));
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                               goto out;
+                       }
                        btrfs_orphan_del(trans, inode);
                        btrfs_end_transaction(trans, root);
                        iput(inode);
@@ -2370,17 +2389,22 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
 
                /* if we have links, this was a truncate, lets do that */
                if (inode->i_nlink) {
+                       if (!S_ISREG(inode->i_mode)) {
+                               WARN_ON(1);
+                               iput(inode);
+                               continue;
+                       }
                        nr_truncate++;
-                       btrfs_truncate(inode);
+                       ret = btrfs_truncate(inode);
                } else {
                        nr_unlink++;
                }
 
                /* this will do delete_inode and everything for us */
                iput(inode);
+               if (ret)
+                       goto out;
        }
-       btrfs_free_path(path);
-
        root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE;
 
        if (root->orphan_block_rsv)
@@ -2389,14 +2413,20 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
 
        if (root->orphan_block_rsv || root->orphan_item_inserted) {
                trans = btrfs_join_transaction(root, 1);
-               BUG_ON(IS_ERR(trans));
-               btrfs_end_transaction(trans, root);
+               if (!IS_ERR(trans))
+                       btrfs_end_transaction(trans, root);
        }
 
        if (nr_unlink)
                printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink);
        if (nr_truncate)
                printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate);
+
+out:
+       if (ret)
+               printk(KERN_CRIT "btrfs: could not do orphan cleanup %d\n", ret);
+       btrfs_free_path(path);
+       return ret;
 }
 
 /*
@@ -2507,6 +2537,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
        BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
 
        alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
+       if (location.objectid == BTRFS_FREE_SPACE_OBJECTID)
+               inode->i_mapping->flags &= ~__GFP_FS;
 
        /*
         * try to precache a NULL acl entry for files that don't have
@@ -2635,10 +2667,10 @@ failed:
  * recovery code.  It remove a link in a directory with a given name, and
  * also drops the back refs in the inode to the directory
  */
-int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
-                      struct btrfs_root *root,
-                      struct inode *dir, struct inode *inode,
-                      const char *name, int name_len)
+static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root,
+                               struct inode *dir, struct inode *inode,
+                               const char *name, int name_len)
 {
        struct btrfs_path *path;
        int ret = 0;
@@ -2710,12 +2742,25 @@ err:
        btrfs_i_size_write(dir, dir->i_size - name_len * 2);
        inode->i_ctime = dir->i_mtime = dir->i_ctime = CURRENT_TIME;
        btrfs_update_inode(trans, root, dir);
-       btrfs_drop_nlink(inode);
-       ret = btrfs_update_inode(trans, root, inode);
 out:
        return ret;
 }
 
+int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root,
+                      struct inode *dir, struct inode *inode,
+                      const char *name, int name_len)
+{
+       int ret;
+       ret = __btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
+       if (!ret) {
+               btrfs_drop_nlink(inode);
+               ret = btrfs_update_inode(trans, root, inode);
+       }
+       return ret;
+}
+               
+
 /* helper to check if there is any shared block in the path */
 static int check_path_shared(struct btrfs_root *root,
                             struct btrfs_path *path)
@@ -3537,7 +3582,13 @@ out:
        return ret;
 }
 
-int btrfs_cont_expand(struct inode *inode, loff_t size)
+/*
+ * This function puts in dummy file extents for the area we're creating a hole
+ * for.  So if we are truncating this file to a larger size we need to insert
+ * these file extents so that btrfs_get_extent will return a EXTENT_MAP_HOLE for
+ * the range between oldsize and size
+ */
+int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -3545,7 +3596,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        struct extent_map *em = NULL;
        struct extent_state *cached_state = NULL;
        u64 mask = root->sectorsize - 1;
-       u64 hole_start = (inode->i_size + mask) & ~mask;
+       u64 hole_start = (oldsize + mask) & ~mask;
        u64 block_end = (size + mask) & ~mask;
        u64 last_byte;
        u64 cur_offset;
@@ -3590,13 +3641,15 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
                        err = btrfs_drop_extents(trans, inode, cur_offset,
                                                 cur_offset + hole_size,
                                                 &hint_byte, 1);
-                       BUG_ON(err);
+                       if (err)
+                               break;
 
                        err = btrfs_insert_file_extent(trans, root,
                                        inode->i_ino, cur_offset, 0,
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
-                       BUG_ON(err);
+                       if (err)
+                               break;
 
                        btrfs_drop_extent_cache(inode, hole_start,
                                        last_byte - 1, 0);
@@ -3616,81 +3669,41 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        return err;
 }
 
-static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
+static int btrfs_setsize(struct inode *inode, loff_t newsize)
 {
-       struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct btrfs_trans_handle *trans;
-       unsigned long nr;
+       loff_t oldsize = i_size_read(inode);
        int ret;
 
-       if (attr->ia_size == inode->i_size)
+       if (newsize == oldsize)
                return 0;
 
-       if (attr->ia_size > inode->i_size) {
-               unsigned long limit;
-               limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
-               if (attr->ia_size > inode->i_sb->s_maxbytes)
-                       return -EFBIG;
-               if (limit != RLIM_INFINITY && attr->ia_size > limit) {
-                       send_sig(SIGXFSZ, current, 0);
-                       return -EFBIG;
-               }
-       }
-
-       trans = btrfs_start_transaction(root, 5);
-       if (IS_ERR(trans))
-               return PTR_ERR(trans);
-
-       btrfs_set_trans_block_group(trans, inode);
-
-       ret = btrfs_orphan_add(trans, inode);
-       BUG_ON(ret);
-
-       nr = trans->blocks_used;
-       btrfs_end_transaction(trans, root);
-       btrfs_btree_balance_dirty(root, nr);
-
-       if (attr->ia_size > inode->i_size) {
-               ret = btrfs_cont_expand(inode, attr->ia_size);
+       if (newsize > oldsize) {
+               i_size_write(inode, newsize);
+               btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
+               truncate_pagecache(inode, oldsize, newsize);
+               ret = btrfs_cont_expand(inode, oldsize, newsize);
                if (ret) {
-                       btrfs_truncate(inode);
+                       btrfs_setsize(inode, oldsize);
                        return ret;
                }
 
-               i_size_write(inode, attr->ia_size);
-               btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
+               mark_inode_dirty(inode);
+       } else {
 
-               trans = btrfs_start_transaction(root, 0);
-               BUG_ON(IS_ERR(trans));
-               btrfs_set_trans_block_group(trans, inode);
-               trans->block_rsv = root->orphan_block_rsv;
-               BUG_ON(!trans->block_rsv);
+               /*
+                * We're truncating a file that used to have good data down to
+                * zero. Make sure it gets into the ordered flush list so that
+                * any new writes get down to disk quickly.
+                */
+               if (newsize == 0)
+                       BTRFS_I(inode)->ordered_data_close = 1;
 
-               ret = btrfs_update_inode(trans, root, inode);
-               BUG_ON(ret);
-               if (inode->i_nlink > 0) {
-                       ret = btrfs_orphan_del(trans, inode);
-                       BUG_ON(ret);
-               }
-               nr = trans->blocks_used;
-               btrfs_end_transaction(trans, root);
-               btrfs_btree_balance_dirty(root, nr);
-               return 0;
+               /* we don't support swapfiles, so vmtruncate shouldn't fail */
+               truncate_setsize(inode, newsize);
+               ret = btrfs_truncate(inode);
        }
 
-       /*
-        * We're truncating a file that used to have good data down to
-        * zero. Make sure it gets into the ordered flush list so that
-        * any new writes get down to disk quickly.
-        */
-       if (attr->ia_size == 0)
-               BTRFS_I(inode)->ordered_data_close = 1;
-
-       /* we don't support swapfiles, so vmtruncate shouldn't fail */
-       ret = vmtruncate(inode, attr->ia_size);
-       BUG_ON(ret);
-
-       return 0;
+       return ret;
 }
 
 static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -3707,7 +3720,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               err = btrfs_setattr_size(inode, attr);
+               err = btrfs_setsize(inode, attr->ia_size);
                if (err)
                        return err;
        }
@@ -3730,6 +3743,8 @@ void btrfs_evict_inode(struct inode *inode)
        unsigned long nr;
        int ret;
 
+       trace_btrfs_inode_evict(inode);
+
        truncate_inode_pages(&inode->i_data, 0);
        if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 ||
                               root == root->fs_info->tree_root))
@@ -4072,7 +4087,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                BTRFS_I(inode)->root = root;
                memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
                btrfs_read_locked_inode(inode);
-
                inode_tree_add(inode);
                unlock_new_inode(inode);
                if (new)
@@ -4147,8 +4161,10 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
        if (!IS_ERR(inode) && root != sub_root) {
                down_read(&root->fs_info->cleanup_work_sem);
                if (!(inode->i_sb->s_flags & MS_RDONLY))
-                       btrfs_orphan_cleanup(sub_root);
+                       ret = btrfs_orphan_cleanup(sub_root);
                up_read(&root->fs_info->cleanup_work_sem);
+               if (ret)
+                       inode = ERR_PTR(ret);
        }
 
        return inode;
@@ -4282,6 +4298,9 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
                while (di_cur < di_total) {
                        struct btrfs_key location;
 
+                       if (verify_dir_item(root, leaf, di))
+                               break;
+
                        name_len = btrfs_dir_name_len(leaf, di);
                        if (name_len <= sizeof(tmp_name)) {
                                name_ptr = tmp_name;
@@ -4517,6 +4536,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                return ERR_PTR(-ENOMEM);
 
        if (dir) {
+               trace_btrfs_inode_request(dir);
+
                ret = btrfs_set_inode_index(dir, index);
                if (ret) {
                        iput(inode);
@@ -4585,12 +4606,16 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        if ((mode & S_IFREG)) {
                if (btrfs_test_opt(root, NODATASUM))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-               if (btrfs_test_opt(root, NODATACOW))
+               if (btrfs_test_opt(root, NODATACOW) ||
+                   (BTRFS_I(dir)->flags & BTRFS_INODE_NODATACOW))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
        }
 
        insert_inode_hash(inode);
        inode_tree_add(inode);
+
+       trace_btrfs_inode_new(inode);
+
        return inode;
 fail:
        if (dir)
@@ -4809,7 +4834,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 
        /* do not allow sys_link's with other subvols of the same device */
        if (root->objectid != BTRFS_I(inode)->root->objectid)
-               return -EPERM;
+               return -EXDEV;
+
+       if (inode->i_nlink == ~0U)
+               return -EMLINK;
 
        btrfs_inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
@@ -5265,6 +5293,9 @@ insert:
        }
        write_unlock(&em_tree->lock);
 out:
+
+       trace_btrfs_get_extent(root, em);
+
        if (path)
                btrfs_free_path(path);
        if (trans) {
@@ -5748,6 +5779,10 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
 
        kfree(dip->csums);
        kfree(dip);
+
+       /* If we had a csum failure make sure to clear the uptodate flag */
+       if (err)
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
        dio_end_io(bio, err);
 }
 
@@ -5849,6 +5884,10 @@ out_done:
 
        kfree(dip->csums);
        kfree(dip);
+
+       /* If we had an error make sure to clear the uptodate flag */
+       if (err)
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
        dio_end_io(bio, err);
 }
 
@@ -5922,9 +5961,12 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
                                   __btrfs_submit_bio_start_direct_io,
                                   __btrfs_submit_bio_done);
                goto err;
-       } else if (!skip_sum)
-               btrfs_lookup_bio_sums_dio(root, inode, bio,
+       } else if (!skip_sum) {
+               ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
                                          file_offset, csums);
+               if (ret)
+                       goto err;
+       }
 
        ret = btrfs_map_bio(root, rw, bio, 0, 1);
 err:
@@ -5948,6 +5990,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        int nr_pages = 0;
        u32 *csums = dip->csums;
        int ret = 0;
+       int write = rw & REQ_WRITE;
 
        bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
        if (!bio)
@@ -5984,7 +6027,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                                goto out_err;
                        }
 
-                       if (!skip_sum)
+                       /* Write's use the ordered csums */
+                       if (!write && !skip_sum)
                                csums = csums + nr_pages;
                        start_sector += submit_len >> 9;
                        file_offset += submit_len;
@@ -6052,7 +6096,8 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
        }
        dip->csums = NULL;
 
-       if (!skip_sum) {
+       /* Write's use the ordered csum stuff, so we don't need dip->csums */
+       if (!write && !skip_sum) {
                dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS);
                if (!dip->csums) {
                        kfree(dip);
@@ -6474,28 +6519,42 @@ out:
        return ret;
 }
 
-static void btrfs_truncate(struct inode *inode)
+static int btrfs_truncate(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int ret;
+       int err = 0;
        struct btrfs_trans_handle *trans;
        unsigned long nr;
        u64 mask = root->sectorsize - 1;
 
-       if (!S_ISREG(inode->i_mode)) {
-               WARN_ON(1);
-               return;
-       }
-
        ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
        if (ret)
-               return;
+               return ret;
 
        btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
        btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
 
+       trans = btrfs_start_transaction(root, 5);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
+
+       btrfs_set_trans_block_group(trans, inode);
+
+       ret = btrfs_orphan_add(trans, inode);
+       if (ret) {
+               btrfs_end_transaction(trans, root);
+               return ret;
+       }
+
+       nr = trans->blocks_used;
+       btrfs_end_transaction(trans, root);
+       btrfs_btree_balance_dirty(root, nr);
+
+       /* Now start a transaction for the truncate */
        trans = btrfs_start_transaction(root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
        btrfs_set_trans_block_group(trans, inode);
        trans->block_rsv = root->orphan_block_rsv;
 
@@ -6522,29 +6581,38 @@ static void btrfs_truncate(struct inode *inode)
        while (1) {
                if (!trans) {
                        trans = btrfs_start_transaction(root, 0);
-                       BUG_ON(IS_ERR(trans));
+                       if (IS_ERR(trans))
+                               return PTR_ERR(trans);
                        btrfs_set_trans_block_group(trans, inode);
                        trans->block_rsv = root->orphan_block_rsv;
                }
 
                ret = btrfs_block_rsv_check(trans, root,
                                            root->orphan_block_rsv, 0, 5);
-               if (ret) {
-                       BUG_ON(ret != -EAGAIN);
+               if (ret == -EAGAIN) {
                        ret = btrfs_commit_transaction(trans, root);
-                       BUG_ON(ret);
+                       if (ret)
+                               return ret;
                        trans = NULL;
                        continue;
+               } else if (ret) {
+                       err = ret;
+                       break;
                }
 
                ret = btrfs_truncate_inode_items(trans, root, inode,
                                                 inode->i_size,
                                                 BTRFS_EXTENT_DATA_KEY);
-               if (ret != -EAGAIN)
+               if (ret != -EAGAIN) {
+                       err = ret;
                        break;
+               }
 
                ret = btrfs_update_inode(trans, root, inode);
-               BUG_ON(ret);
+               if (ret) {
+                       err = ret;
+                       break;
+               }
 
                nr = trans->blocks_used;
                btrfs_end_transaction(trans, root);
@@ -6554,16 +6622,27 @@ static void btrfs_truncate(struct inode *inode)
 
        if (ret == 0 && inode->i_nlink > 0) {
                ret = btrfs_orphan_del(trans, inode);
-               BUG_ON(ret);
+               if (ret)
+                       err = ret;
+       } else if (ret && inode->i_nlink > 0) {
+               /*
+                * Failed to do the truncate, remove us from the in memory
+                * orphan list.
+                */
+               ret = btrfs_orphan_del(NULL, inode);
        }
 
        ret = btrfs_update_inode(trans, root, inode);
-       BUG_ON(ret);
+       if (ret && !err)
+               err = ret;
 
        nr = trans->blocks_used;
        ret = btrfs_end_transaction_throttle(trans, root);
-       BUG_ON(ret);
+       if (ret && !err)
+               err = ret;
        btrfs_btree_balance_dirty(root, nr);
+
+       return err;
 }
 
 /*
@@ -6630,9 +6709,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->index_cnt = (u64)-1;
        ei->last_unlink_trans = 0;
 
-       spin_lock_init(&ei->accounting_lock);
        atomic_set(&ei->outstanding_extents, 0);
-       ei->reserved_extents = 0;
+       atomic_set(&ei->reserved_extents, 0);
 
        ei->ordered_data_close = 0;
        ei->orphan_meta_reserved = 0;
@@ -6668,7 +6746,7 @@ void btrfs_destroy_inode(struct inode *inode)
        WARN_ON(!list_empty(&inode->i_dentry));
        WARN_ON(inode->i_data.nrpages);
        WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents));
-       WARN_ON(BTRFS_I(inode)->reserved_extents);
+       WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents));
 
        /*
         * This can happen where we create an inode, but somebody else also
@@ -6760,6 +6838,8 @@ void btrfs_destroy_cachep(void)
                kmem_cache_destroy(btrfs_transaction_cachep);
        if (btrfs_path_cachep)
                kmem_cache_destroy(btrfs_path_cachep);
+       if (btrfs_free_space_cachep)
+               kmem_cache_destroy(btrfs_free_space_cachep);
 }
 
 int btrfs_init_cachep(void)
@@ -6788,6 +6868,12 @@ int btrfs_init_cachep(void)
        if (!btrfs_path_cachep)
                goto fail;
 
+       btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space_cache",
+                       sizeof(struct btrfs_free_space), 0,
+                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+       if (!btrfs_free_space_cachep)
+               goto fail;
+
        return 0;
 fail:
        btrfs_destroy_cachep();
@@ -6806,6 +6892,26 @@ static int btrfs_getattr(struct vfsmount *mnt,
        return 0;
 }
 
+/*
+ * If a file is moved, it will inherit the cow and compression flags of the new
+ * directory.
+ */
+static void fixup_inode_flags(struct inode *dir, struct inode *inode)
+{
+       struct btrfs_inode *b_dir = BTRFS_I(dir);
+       struct btrfs_inode *b_inode = BTRFS_I(inode);
+
+       if (b_dir->flags & BTRFS_INODE_NODATACOW)
+               b_inode->flags |= BTRFS_INODE_NODATACOW;
+       else
+               b_inode->flags &= ~BTRFS_INODE_NODATACOW;
+
+       if (b_dir->flags & BTRFS_INODE_COMPRESS)
+               b_inode->flags |= BTRFS_INODE_COMPRESS;
+       else
+               b_inode->flags &= ~BTRFS_INODE_COMPRESS;
+}
+
 static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry)
 {
@@ -6908,11 +7014,12 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                        old_dentry->d_name.name,
                                        old_dentry->d_name.len);
        } else {
-               btrfs_inc_nlink(old_dentry->d_inode);
-               ret = btrfs_unlink_inode(trans, root, old_dir,
-                                        old_dentry->d_inode,
-                                        old_dentry->d_name.name,
-                                        old_dentry->d_name.len);
+               ret = __btrfs_unlink_inode(trans, root, old_dir,
+                                       old_dentry->d_inode,
+                                       old_dentry->d_name.name,
+                                       old_dentry->d_name.len);
+               if (!ret)
+                       ret = btrfs_update_inode(trans, root, old_inode);
        }
        BUG_ON(ret);
 
@@ -6939,6 +7046,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
        }
 
+       fixup_inode_flags(new_dir, old_inode);
+
        ret = btrfs_add_link(trans, new_dir, old_inode,
                             new_dentry->d_name.name,
                             new_dentry->d_name.len, 0, index);
@@ -7355,7 +7464,6 @@ static const struct address_space_operations btrfs_symlink_aops = {
 };
 
 static const struct inode_operations btrfs_file_inode_operations = {
-       .truncate       = btrfs_truncate,
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .setxattr       = btrfs_setxattr,
index d1bace3df9b61fab21ca50a9e84ff427fedc75ea..7c07fe26b7cfcf7e7872686da07f5676e87549c4 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/xattr.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
 #include "compat.h"
 #include "ctree.h"
 #include "disk-io.h"
@@ -138,6 +139,24 @@ static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
        return 0;
 }
 
+static int check_flags(unsigned int flags)
+{
+       if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+                     FS_NOATIME_FL | FS_NODUMP_FL | \
+                     FS_SYNC_FL | FS_DIRSYNC_FL | \
+                     FS_NOCOMP_FL | FS_COMPR_FL | \
+                     FS_NOCOW_FL | FS_COW_FL))
+               return -EOPNOTSUPP;
+
+       if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
+               return -EINVAL;
+
+       if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
@@ -153,10 +172,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        if (copy_from_user(&flags, arg, sizeof(flags)))
                return -EFAULT;
 
-       if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
-                     FS_NOATIME_FL | FS_NODUMP_FL | \
-                     FS_SYNC_FL | FS_DIRSYNC_FL))
-               return -EOPNOTSUPP;
+       ret = check_flags(flags);
+       if (ret)
+               return ret;
 
        if (!inode_owner_or_capable(inode))
                return -EACCES;
@@ -201,6 +219,22 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        else
                ip->flags &= ~BTRFS_INODE_DIRSYNC;
 
+       /*
+        * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
+        * flag may be changed automatically if compression code won't make
+        * things smaller.
+        */
+       if (flags & FS_NOCOMP_FL) {
+               ip->flags &= ~BTRFS_INODE_COMPRESS;
+               ip->flags |= BTRFS_INODE_NOCOMPRESS;
+       } else if (flags & FS_COMPR_FL) {
+               ip->flags |= BTRFS_INODE_COMPRESS;
+               ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
+       }
+       if (flags & FS_NOCOW_FL)
+               ip->flags |= BTRFS_INODE_NODATACOW;
+       else if (flags & FS_COW_FL)
+               ip->flags &= ~BTRFS_INODE_NODATACOW;
 
        trans = btrfs_join_transaction(root, 1);
        BUG_ON(IS_ERR(trans));
@@ -213,9 +247,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        btrfs_end_transaction(trans, root);
 
        mnt_drop_write(file->f_path.mnt);
+
+       ret = 0;
  out_unlock:
        mutex_unlock(&inode->i_mutex);
-       return 0;
+       return ret;
 }
 
 static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
@@ -225,6 +261,49 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
        return put_user(inode->i_generation, arg);
 }
 
+static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
+{
+       struct btrfs_root *root = fdentry(file)->d_sb->s_fs_info;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_device *device;
+       struct request_queue *q;
+       struct fstrim_range range;
+       u64 minlen = ULLONG_MAX;
+       u64 num_devices = 0;
+       int ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       mutex_lock(&fs_info->fs_devices->device_list_mutex);
+       list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) {
+               if (!device->bdev)
+                       continue;
+               q = bdev_get_queue(device->bdev);
+               if (blk_queue_discard(q)) {
+                       num_devices++;
+                       minlen = min((u64)q->limits.discard_granularity,
+                                    minlen);
+               }
+       }
+       mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+       if (!num_devices)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&range, arg, sizeof(range)))
+               return -EFAULT;
+
+       range.minlen = max(range.minlen, minlen);
+       ret = btrfs_trim_fs(root, &range);
+       if (ret < 0)
+               return ret;
+
+       if (copy_to_user(arg, &range, sizeof(range)))
+               return -EFAULT;
+
+       return 0;
+}
+
 static noinline int create_subvol(struct btrfs_root *root,
                                  struct dentry *dentry,
                                  char *name, int namelen,
@@ -409,7 +488,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        if (ret)
                goto fail;
 
-       btrfs_orphan_cleanup(pending_snapshot->snap);
+       ret = btrfs_orphan_cleanup(pending_snapshot->snap);
+       if (ret)
+               goto fail;
 
        parent = dget_parent(dentry);
        inode = btrfs_lookup_dentry(parent->d_inode, dentry);
@@ -2348,12 +2429,15 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp
        struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
        struct btrfs_trans_handle *trans;
        u64 transid;
+       int ret;
 
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
        transid = trans->transid;
-       btrfs_commit_transaction_async(trans, root, 0);
+       ret = btrfs_commit_transaction_async(trans, root, 0);
+       if (ret)
+               return ret;
 
        if (argp)
                if (copy_to_user(argp, &transid, sizeof(transid)))
@@ -2388,6 +2472,8 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_setflags(file, argp);
        case FS_IOC_GETVERSION:
                return btrfs_ioctl_getversion(file, argp);
+       case FITRIM:
+               return btrfs_ioctl_fitrim(file, argp);
        case BTRFS_IOC_SNAP_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 0);
        case BTRFS_IOC_SNAP_CREATE_V2:
index 083a55477375c7c6b2c83e68fbbb642d4176ae3e..a1c94042530787539350c72e9449c314a8899e9e 100644 (file)
@@ -202,6 +202,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
        INIT_LIST_HEAD(&entry->list);
        INIT_LIST_HEAD(&entry->root_extent_list);
 
+       trace_btrfs_ordered_extent_add(inode, entry);
+
        spin_lock(&tree->lock);
        node = tree_insert(&tree->tree, file_offset,
                           &entry->rb_node);
@@ -387,6 +389,8 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
        struct list_head *cur;
        struct btrfs_ordered_sum *sum;
 
+       trace_btrfs_ordered_extent_put(entry->inode, entry);
+
        if (atomic_dec_and_test(&entry->refs)) {
                while (!list_empty(&entry->list)) {
                        cur = entry->list.next;
@@ -420,6 +424,8 @@ static int __btrfs_remove_ordered_extent(struct inode *inode,
        spin_lock(&root->fs_info->ordered_extent_lock);
        list_del_init(&entry->root_extent_list);
 
+       trace_btrfs_ordered_extent_remove(inode, entry);
+
        /*
         * we have no more ordered extents for this inode and
         * no dirty pages.  We can safely remove it from the
@@ -585,6 +591,8 @@ void btrfs_start_ordered_extent(struct inode *inode,
        u64 start = entry->file_offset;
        u64 end = start + entry->len - 1;
 
+       trace_btrfs_ordered_extent_start(inode, entry);
+
        /*
         * pages in the range can be dirty, clean or writeback.  We
         * start IO on any dirty ones so the wait doesn't stall waiting
index 31ade5802ae8a31f8ab48c5bdcbba0cebcddfe96..58250e09eb056213944db6703d78679fbb94d35f 100644 (file)
@@ -1724,6 +1724,7 @@ again:
 
                        eb = read_tree_block(dest, old_bytenr, blocksize,
                                             old_ptr_gen);
+                       BUG_ON(!eb);
                        btrfs_tree_lock(eb);
                        if (cow) {
                                ret = btrfs_cow_block(trans, dest, eb, parent,
@@ -2513,6 +2514,10 @@ static int do_relocation(struct btrfs_trans_handle *trans,
                blocksize = btrfs_level_size(root, node->level);
                generation = btrfs_node_ptr_generation(upper->eb, slot);
                eb = read_tree_block(root, bytenr, blocksize, generation);
+               if (!eb) {
+                       err = -EIO;
+                       goto next;
+               }
                btrfs_tree_lock(eb);
                btrfs_set_lock_blocking(eb);
 
@@ -2670,6 +2675,7 @@ static int get_tree_block_key(struct reloc_control *rc,
        BUG_ON(block->key_ready);
        eb = read_tree_block(rc->extent_root, block->bytenr,
                             block->key.objectid, block->key.offset);
+       BUG_ON(!eb);
        WARN_ON(btrfs_header_level(eb) != block->level);
        if (block->level == 0)
                btrfs_item_key_to_cpu(eb, &block->key, 0);
@@ -4209,7 +4215,7 @@ out:
                if (IS_ERR(fs_root))
                        err = PTR_ERR(fs_root);
                else
-                       btrfs_orphan_cleanup(fs_root);
+                       err = btrfs_orphan_cleanup(fs_root);
        }
        return err;
 }
index 6a1086e83ffc898ff3ab7f7b33d91c2c442019d7..29b2d7c930eb3f9242e7df8734a1651844285fcf 100644 (file)
@@ -88,7 +88,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
        search_key.offset = (u64)-1;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
        ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
        if (ret < 0)
                goto out;
@@ -332,7 +333,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        struct extent_buffer *leaf;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
        ret = btrfs_search_slot(trans, root, key, path, -1, 1);
        if (ret < 0)
                goto out;
index d39a9895d93288a6315e838cfe05dc1e1a65e7f4..2edfc039f098531bac7f3320e1fc6c3a3b52f074 100644 (file)
@@ -52,6 +52,9 @@
 #include "export.h"
 #include "compression.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/btrfs.h>
+
 static const struct super_operations btrfs_super_ops;
 
 static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno,
@@ -620,6 +623,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
        struct btrfs_root *root = btrfs_sb(sb);
        int ret;
 
+       trace_btrfs_sync_fs(wait);
+
        if (!wait) {
                filemap_flush(root->fs_info->btree_inode->i_mapping);
                return 0;
index 3d73c8d93bbb1c3f20c1d10dfa076e8dd887bd16..ce48eb59d6156dd72b8cfe4344e50411abe47d98 100644 (file)
@@ -57,7 +57,8 @@ static noinline int join_transaction(struct btrfs_root *root)
        if (!cur_trans) {
                cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
                                             GFP_NOFS);
-               BUG_ON(!cur_trans);
+               if (!cur_trans)
+                       return -ENOMEM;
                root->fs_info->generation++;
                cur_trans->num_writers = 1;
                cur_trans->num_joined = 0;
@@ -195,7 +196,11 @@ again:
                wait_current_trans(root);
 
        ret = join_transaction(root);
-       BUG_ON(ret);
+       if (ret < 0) {
+               if (type != TRANS_JOIN_NOLOCK)
+                       mutex_unlock(&root->fs_info->trans_mutex);
+               return ERR_PTR(ret);
+       }
 
        cur_trans = root->fs_info->running_transaction;
        cur_trans->use_count++;
@@ -1156,7 +1161,8 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
        struct btrfs_transaction *cur_trans;
 
        ac = kmalloc(sizeof(*ac), GFP_NOFS);
-       BUG_ON(!ac);
+       if (!ac)
+               return -ENOMEM;
 
        INIT_DELAYED_WORK(&ac->work, do_async_commit);
        ac->root = root;
@@ -1389,6 +1395,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        put_transaction(cur_trans);
        put_transaction(cur_trans);
 
+       trace_btrfs_transaction_commit(root);
+
        mutex_unlock(&root->fs_info->trans_mutex);
 
        if (current->journal_info == trans)
index a4bbb854dfd21eea39614d5f79b66bd6d237564e..c50271ad3157675059656d8113e9804cf3872dfb 100644 (file)
@@ -799,12 +799,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
        struct inode *dir;
        int ret;
        struct btrfs_inode_ref *ref;
-       struct btrfs_dir_item *di;
        struct inode *inode;
        char *name;
        int namelen;
        unsigned long ref_ptr;
        unsigned long ref_end;
+       int search_done = 0;
 
        /*
         * it is possible that we didn't log all the parent directories
@@ -845,7 +845,10 @@ again:
         * existing back reference, and we don't want to create
         * dangling pointers in the directory.
         */
-conflict_again:
+
+       if (search_done)
+               goto insert;
+
        ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
        if (ret == 0) {
                char *victim_name;
@@ -886,37 +889,21 @@ conflict_again:
                                ret = btrfs_unlink_inode(trans, root, dir,
                                                         inode, victim_name,
                                                         victim_name_len);
-                               kfree(victim_name);
-                               btrfs_release_path(root, path);
-                               goto conflict_again;
                        }
                        kfree(victim_name);
                        ptr = (unsigned long)(victim_ref + 1) + victim_name_len;
                }
                BUG_ON(ret);
-       }
-       btrfs_release_path(root, path);
-
-       /* look for a conflicting sequence number */
-       di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
-                                        btrfs_inode_ref_index(eb, ref),
-                                        name, namelen, 0);
-       if (di && !IS_ERR(di)) {
-               ret = drop_one_dir_item(trans, root, path, dir, di);
-               BUG_ON(ret);
-       }
-       btrfs_release_path(root, path);
 
-
-       /* look for a conflicting name */
-       di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
-                                  name, namelen, 0);
-       if (di && !IS_ERR(di)) {
-               ret = drop_one_dir_item(trans, root, path, dir, di);
-               BUG_ON(ret);
+               /*
+                * NOTE: we have searched root tree and checked the
+                * coresponding ref, it does not need to check again.
+                */
+               search_done = 1;
        }
        btrfs_release_path(root, path);
 
+insert:
        /* insert our name */
        ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
                             btrfs_inode_ref_index(eb, ref));
@@ -1286,6 +1273,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
        ptr_end = ptr + item_size;
        while (ptr < ptr_end) {
                di = (struct btrfs_dir_item *)ptr;
+               if (verify_dir_item(root, eb, di))
+                       return -EIO;
                name_len = btrfs_dir_name_len(eb, di);
                ret = replay_one_name(trans, root, path, eb, di, key);
                BUG_ON(ret);
@@ -1412,6 +1401,11 @@ again:
        ptr_end = ptr + item_size;
        while (ptr < ptr_end) {
                di = (struct btrfs_dir_item *)ptr;
+               if (verify_dir_item(root, eb, di)) {
+                       ret = -EIO;
+                       goto out;
+               }
+
                name_len = btrfs_dir_name_len(eb, di);
                name = kmalloc(name_len, GFP_NOFS);
                if (!name) {
@@ -1821,7 +1815,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
        int orig_level;
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        level = btrfs_header_level(log->node);
        orig_level = level;
@@ -3107,9 +3102,11 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
                .stage = 0,
        };
 
-       fs_info->log_root_recovering = 1;
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
+
+       fs_info->log_root_recovering = 1;
 
        trans = btrfs_start_transaction(fs_info->tree_root, 0);
        BUG_ON(IS_ERR(trans));
@@ -3117,7 +3114,8 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
        wc.trans = trans;
        wc.pin = 1;
 
-       walk_log_tree(trans, log_root_tree, &wc);
+       ret = walk_log_tree(trans, log_root_tree, &wc);
+       BUG_ON(ret);
 
 again:
        key.objectid = BTRFS_TREE_LOG_OBJECTID;
@@ -3141,8 +3139,7 @@ again:
 
                log = btrfs_read_fs_root_no_radix(log_root_tree,
                                                  &found_key);
-               BUG_ON(!log);
-
+               BUG_ON(IS_ERR(log));
 
                tmp_key.objectid = found_key.offset;
                tmp_key.type = BTRFS_ROOT_ITEM_KEY;
index 9d554e8e6583e62a277eaa906ebd8dbe03d0f39f..309a57b9fc85e3a6f09809da14d0cd9e1df55fb5 100644 (file)
 #include "volumes.h"
 #include "async-thread.h"
 
-struct map_lookup {
-       u64 type;
-       int io_align;
-       int io_width;
-       int stripe_len;
-       int sector_size;
-       int num_stripes;
-       int sub_stripes;
-       struct btrfs_bio_stripe stripes[];
-};
-
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                struct btrfs_device *device);
@@ -1879,6 +1868,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
 
        BUG_ON(ret);
 
+       trace_btrfs_chunk_free(root, map, chunk_offset, em->len);
+
        if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
                ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset);
                BUG_ON(ret);
@@ -2606,6 +2597,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        *num_bytes = chunk_bytes_by_type(type, calc_size,
                                         map->num_stripes, sub_stripes);
 
+       trace_btrfs_chunk_alloc(info->chunk_root, map, start, *num_bytes);
+
        em = alloc_extent_map(GFP_NOFS);
        if (!em) {
                ret = -ENOMEM;
@@ -2714,6 +2707,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans,
                                             item_size);
                BUG_ON(ret);
        }
+
        kfree(chunk);
        return 0;
 }
@@ -2918,7 +2912,10 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
        struct extent_map_tree *em_tree = &map_tree->map_tree;
        u64 offset;
        u64 stripe_offset;
+       u64 stripe_end_offset;
        u64 stripe_nr;
+       u64 stripe_nr_orig;
+       u64 stripe_nr_end;
        int stripes_allocated = 8;
        int stripes_required = 1;
        int stripe_index;
@@ -2927,7 +2924,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
        int max_errors = 0;
        struct btrfs_multi_bio *multi = NULL;
 
-       if (multi_ret && !(rw & REQ_WRITE))
+       if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD)))
                stripes_allocated = 1;
 again:
        if (multi_ret) {
@@ -2968,7 +2965,15 @@ again:
                        max_errors = 1;
                }
        }
-       if (multi_ret && (rw & REQ_WRITE) &&
+       if (rw & REQ_DISCARD) {
+               if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+                                BTRFS_BLOCK_GROUP_RAID1 |
+                                BTRFS_BLOCK_GROUP_DUP |
+                                BTRFS_BLOCK_GROUP_RAID10)) {
+                       stripes_required = map->num_stripes;
+               }
+       }
+       if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) &&
            stripes_allocated < stripes_required) {
                stripes_allocated = map->num_stripes;
                free_extent_map(em);
@@ -2988,12 +2993,15 @@ again:
        /* stripe_offset is the offset of this block in its stripe*/
        stripe_offset = offset - stripe_offset;
 
-       if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
-                        BTRFS_BLOCK_GROUP_RAID10 |
-                        BTRFS_BLOCK_GROUP_DUP)) {
+       if (rw & REQ_DISCARD)
+               *length = min_t(u64, em->len - offset, *length);
+       else if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+                             BTRFS_BLOCK_GROUP_RAID1 |
+                             BTRFS_BLOCK_GROUP_RAID10 |
+                             BTRFS_BLOCK_GROUP_DUP)) {
                /* we limit the length of each bio to what fits in a stripe */
                *length = min_t(u64, em->len - offset,
-                             map->stripe_len - stripe_offset);
+                               map->stripe_len - stripe_offset);
        } else {
                *length = em->len - offset;
        }
@@ -3003,8 +3011,19 @@ again:
 
        num_stripes = 1;
        stripe_index = 0;
-       if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
-               if (rw & REQ_WRITE)
+       stripe_nr_orig = stripe_nr;
+       stripe_nr_end = (offset + *length + map->stripe_len - 1) &
+                       (~(map->stripe_len - 1));
+       do_div(stripe_nr_end, map->stripe_len);
+       stripe_end_offset = stripe_nr_end * map->stripe_len -
+                           (offset + *length);
+       if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
+               if (rw & REQ_DISCARD)
+                       num_stripes = min_t(u64, map->num_stripes,
+                                           stripe_nr_end - stripe_nr_orig);
+               stripe_index = do_div(stripe_nr, map->num_stripes);
+       } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
+               if (rw & (REQ_WRITE | REQ_DISCARD))
                        num_stripes = map->num_stripes;
                else if (mirror_num)
                        stripe_index = mirror_num - 1;
@@ -3015,7 +3034,7 @@ again:
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
-               if (rw & REQ_WRITE)
+               if (rw & (REQ_WRITE | REQ_DISCARD))
                        num_stripes = map->num_stripes;
                else if (mirror_num)
                        stripe_index = mirror_num - 1;
@@ -3028,6 +3047,10 @@ again:
 
                if (rw & REQ_WRITE)
                        num_stripes = map->sub_stripes;
+               else if (rw & REQ_DISCARD)
+                       num_stripes = min_t(u64, map->sub_stripes *
+                                           (stripe_nr_end - stripe_nr_orig),
+                                           map->num_stripes);
                else if (mirror_num)
                        stripe_index += mirror_num - 1;
                else {
@@ -3045,12 +3068,101 @@ again:
        }
        BUG_ON(stripe_index >= map->num_stripes);
 
-       for (i = 0; i < num_stripes; i++) {
-               multi->stripes[i].physical =
-                       map->stripes[stripe_index].physical +
-                       stripe_offset + stripe_nr * map->stripe_len;
-               multi->stripes[i].dev = map->stripes[stripe_index].dev;
-               stripe_index++;
+       if (rw & REQ_DISCARD) {
+               for (i = 0; i < num_stripes; i++) {
+                       multi->stripes[i].physical =
+                               map->stripes[stripe_index].physical +
+                               stripe_offset + stripe_nr * map->stripe_len;
+                       multi->stripes[i].dev = map->stripes[stripe_index].dev;
+
+                       if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
+                               u64 stripes;
+                               u32 last_stripe = 0;
+                               int j;
+
+                               div_u64_rem(stripe_nr_end - 1,
+                                           map->num_stripes,
+                                           &last_stripe);
+
+                               for (j = 0; j < map->num_stripes; j++) {
+                                       u32 test;
+
+                                       div_u64_rem(stripe_nr_end - 1 - j,
+                                                   map->num_stripes, &test);
+                                       if (test == stripe_index)
+                                               break;
+                               }
+                               stripes = stripe_nr_end - 1 - j;
+                               do_div(stripes, map->num_stripes);
+                               multi->stripes[i].length = map->stripe_len *
+                                       (stripes - stripe_nr + 1);
+
+                               if (i == 0) {
+                                       multi->stripes[i].length -=
+                                               stripe_offset;
+                                       stripe_offset = 0;
+                               }
+                               if (stripe_index == last_stripe)
+                                       multi->stripes[i].length -=
+                                               stripe_end_offset;
+                       } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
+                               u64 stripes;
+                               int j;
+                               int factor = map->num_stripes /
+                                            map->sub_stripes;
+                               u32 last_stripe = 0;
+
+                               div_u64_rem(stripe_nr_end - 1,
+                                           factor, &last_stripe);
+                               last_stripe *= map->sub_stripes;
+
+                               for (j = 0; j < factor; j++) {
+                                       u32 test;
+
+                                       div_u64_rem(stripe_nr_end - 1 - j,
+                                                   factor, &test);
+
+                                       if (test ==
+                                           stripe_index / map->sub_stripes)
+                                               break;
+                               }
+                               stripes = stripe_nr_end - 1 - j;
+                               do_div(stripes, factor);
+                               multi->stripes[i].length = map->stripe_len *
+                                       (stripes - stripe_nr + 1);
+
+                               if (i < map->sub_stripes) {
+                                       multi->stripes[i].length -=
+                                               stripe_offset;
+                                       if (i == map->sub_stripes - 1)
+                                               stripe_offset = 0;
+                               }
+                               if (stripe_index >= last_stripe &&
+                                   stripe_index <= (last_stripe +
+                                                    map->sub_stripes - 1)) {
+                                       multi->stripes[i].length -=
+                                               stripe_end_offset;
+                               }
+                       } else
+                               multi->stripes[i].length = *length;
+
+                       stripe_index++;
+                       if (stripe_index == map->num_stripes) {
+                               /* This could only happen for RAID0/10 */
+                               stripe_index = 0;
+                               stripe_nr++;
+                       }
+               }
+       } else {
+               for (i = 0; i < num_stripes; i++) {
+                       multi->stripes[i].physical =
+                               map->stripes[stripe_index].physical +
+                               stripe_offset +
+                               stripe_nr * map->stripe_len;
+                       multi->stripes[i].dev =
+                               map->stripes[stripe_index].dev;
+                       stripe_index++;
+               }
        }
        if (multi_ret) {
                *multi_ret = multi;
index 7fb59d45fe8cac7e16cd1fa9295f14bd39848db0..cc2eadaf7a27b996af24eaea258b14c5c5c1cfe0 100644 (file)
@@ -126,6 +126,7 @@ struct btrfs_fs_devices {
 struct btrfs_bio_stripe {
        struct btrfs_device *dev;
        u64 physical;
+       u64 length; /* only used for discard mappings */
 };
 
 struct btrfs_multi_bio {
@@ -145,6 +146,17 @@ struct btrfs_device_info {
        u64 max_avail;
 };
 
+struct map_lookup {
+       u64 type;
+       int io_align;
+       int io_width;
+       int stripe_len;
+       int sector_size;
+       int num_stripes;
+       int sub_stripes;
+       struct btrfs_bio_stripe stripes[];
+};
+
 /* Used to sort the devices by max_avail(descending sort) */
 int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2);
 
index d779cefcfd7ddaace6928ae007d906293c5b24bf..a5303b871b13874d574edb6dec5642cf2286e7cb 100644 (file)
@@ -242,6 +242,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                        break;
 
                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
+               if (verify_dir_item(root, leaf, di))
+                       continue;
 
                name_len = btrfs_dir_name_len(leaf, di);
                total_size += name_len + 1;
index 561438b6a50cd3789b90d54e473562431d528ec8..37368ba2e67c111352287c379c1f7b0235595c1c 100644 (file)
@@ -92,7 +92,7 @@ static int ceph_set_page_dirty(struct page *page)
                ci->i_head_snapc = ceph_get_snap_context(snapc);
        ++ci->i_wrbuffer_ref_head;
        if (ci->i_wrbuffer_ref == 0)
-               igrab(inode);
+               ihold(inode);
        ++ci->i_wrbuffer_ref;
        dout("%p set_page_dirty %p idx %lu head %d/%d -> %d/%d "
             "snapc %p seq %lld (%d snaps)\n",
index f40b9139e43732ea94dc2dad363a7b3d6e910960..0aee66b92af3158ff5ce9055c0a0490068d0a219 100644 (file)
@@ -463,8 +463,8 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 
                dout("queue_cap_snap %p cap_snap %p queuing under %p\n", inode,
                     capsnap, snapc);
-               igrab(inode);
-               
+               ihold(inode);
+
                atomic_set(&capsnap->nref, 1);
                capsnap->ci = ci;
                INIT_LIST_HEAD(&capsnap->ci_item);
index bfd8b680e6481a205dd07d89f3ec401e057abf31..d2a70a4561f91257fe44d7cb867e9d14ec1ff908 100644 (file)
@@ -266,7 +266,6 @@ void ecryptfs_destroy_mount_crypt_stat(
                                 &mount_crypt_stat->global_auth_tok_list,
                                 mount_crypt_stat_list) {
                list_del(&auth_tok->mount_crypt_stat_list);
-               mount_crypt_stat->num_global_auth_toks--;
                if (auth_tok->global_auth_tok_key
                    && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID))
                        key_put(auth_tok->global_auth_tok_key);
@@ -1389,6 +1388,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                rc = -ENOMEM;
                goto out;
        }
+       /* Zeroed page ensures the in-header unencrypted i_size is set to 0 */
        rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat,
                                         ecryptfs_dentry);
        if (unlikely(rc)) {
index e00753496e3e061a3aa521b72c7c7a5ee86a2946..bd3cafd0949de6d22179ca5f91115edf18f38fda 100644 (file)
@@ -233,7 +233,7 @@ ecryptfs_get_key_payload_data(struct key *key)
 
 struct ecryptfs_key_sig {
        struct list_head crypt_stat_list;
-       char keysig[ECRYPTFS_SIG_SIZE_HEX];
+       char keysig[ECRYPTFS_SIG_SIZE_HEX + 1];
 };
 
 struct ecryptfs_filename {
@@ -257,19 +257,18 @@ struct ecryptfs_filename {
 struct ecryptfs_crypt_stat {
 #define ECRYPTFS_STRUCT_INITIALIZED   0x00000001
 #define ECRYPTFS_POLICY_APPLIED       0x00000002
-#define ECRYPTFS_NEW_FILE             0x00000004
-#define ECRYPTFS_ENCRYPTED            0x00000008
-#define ECRYPTFS_SECURITY_WARNING     0x00000010
-#define ECRYPTFS_ENABLE_HMAC          0x00000020
-#define ECRYPTFS_ENCRYPT_IV_PAGES     0x00000040
-#define ECRYPTFS_KEY_VALID            0x00000080
-#define ECRYPTFS_METADATA_IN_XATTR    0x00000100
-#define ECRYPTFS_VIEW_AS_ENCRYPTED    0x00000200
-#define ECRYPTFS_KEY_SET              0x00000400
-#define ECRYPTFS_ENCRYPT_FILENAMES    0x00000800
-#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000
-#define ECRYPTFS_ENCFN_USE_FEK        0x00002000
-#define ECRYPTFS_UNLINK_SIGS         0x00004000
+#define ECRYPTFS_ENCRYPTED            0x00000004
+#define ECRYPTFS_SECURITY_WARNING     0x00000008
+#define ECRYPTFS_ENABLE_HMAC          0x00000010
+#define ECRYPTFS_ENCRYPT_IV_PAGES     0x00000020
+#define ECRYPTFS_KEY_VALID            0x00000040
+#define ECRYPTFS_METADATA_IN_XATTR    0x00000080
+#define ECRYPTFS_VIEW_AS_ENCRYPTED    0x00000100
+#define ECRYPTFS_KEY_SET              0x00000200
+#define ECRYPTFS_ENCRYPT_FILENAMES    0x00000400
+#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800
+#define ECRYPTFS_ENCFN_USE_FEK        0x00001000
+#define ECRYPTFS_UNLINK_SIGS          0x00002000
        u32 flags;
        unsigned int file_version;
        size_t iv_bytes;
@@ -297,7 +296,6 @@ struct ecryptfs_inode_info {
        struct inode vfs_inode;
        struct inode *wii_inode;
        struct file *lower_file;
-       struct mutex lower_file_mutex;
        struct ecryptfs_crypt_stat crypt_stat;
 };
 
@@ -333,7 +331,6 @@ struct ecryptfs_global_auth_tok {
        u32 flags;
        struct list_head mount_crypt_stat_list;
        struct key *global_auth_tok_key;
-       struct ecryptfs_auth_tok *global_auth_tok;
        unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
 };
 
@@ -380,7 +377,6 @@ struct ecryptfs_mount_crypt_stat {
        u32 flags;
        struct list_head global_auth_tok_list;
        struct mutex global_auth_tok_list_mutex;
-       size_t num_global_auth_toks;
        size_t global_default_cipher_key_size;
        size_t global_default_fn_cipher_key_bytes;
        unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
index 7d1050e254f9c85a84bdab5cf8b5cf1bb36a8a5c..cedc913d11ba908f62be8711190a0883f4e95fbe 100644 (file)
@@ -273,7 +273,14 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
 static int
 ecryptfs_fsync(struct file *file, int datasync)
 {
-       return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
+       int rc = 0;
+
+       rc = generic_file_fsync(file, datasync);
+       if (rc)
+               goto out;
+       rc = vfs_fsync(ecryptfs_file_to_lower(file), datasync);
+out:
+       return rc;
 }
 
 static int ecryptfs_fasync(int fd, struct file *file, int flag)
index b592938a84bc40281d8ee80fc5585783bf7ed1d9..f99051b7adab1e7e107cc40e40bb39d57e20e5c1 100644 (file)
@@ -142,26 +142,6 @@ out:
        return rc;
 }
 
-/**
- * grow_file
- * @ecryptfs_dentry: the eCryptfs dentry
- *
- * This is the code which will grow the file to its correct size.
- */
-static int grow_file(struct dentry *ecryptfs_dentry)
-{
-       struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
-       char zero_virt[] = { 0x00 };
-       int rc = 0;
-
-       rc = ecryptfs_write(ecryptfs_inode, zero_virt, 0, 1);
-       i_size_write(ecryptfs_inode, 0);
-       rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
-       ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |=
-               ECRYPTFS_NEW_FILE;
-       return rc;
-}
-
 /**
  * ecryptfs_initialize_file
  *
@@ -181,7 +161,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
                goto out;
        }
-       crypt_stat->flags |= ECRYPTFS_NEW_FILE;
        ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
        rc = ecryptfs_new_file_context(ecryptfs_dentry);
        if (rc) {
@@ -202,9 +181,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
                goto out;
        }
-       rc = grow_file(ecryptfs_dentry);
-       if (rc)
-               printk(KERN_ERR "Error growing file; rc = [%d]\n", rc);
 out:
        return rc;
 }
index c1436cff6f2d77aa0776bb3dd4963868358a9770..03e609c450120674673a5a6e07460b2014751ed0 100644 (file)
@@ -65,6 +65,24 @@ static int process_request_key_err(long err_code)
        return rc;
 }
 
+static int process_find_global_auth_tok_for_sig_err(int err_code)
+{
+       int rc = err_code;
+
+       switch (err_code) {
+       case -ENOENT:
+               ecryptfs_printk(KERN_WARNING, "Missing auth tok\n");
+               break;
+       case -EINVAL:
+               ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n");
+               break;
+       default:
+               rc = process_request_key_err(err_code);
+               break;
+       }
+       return rc;
+}
+
 /**
  * ecryptfs_parse_packet_length
  * @data: Pointer to memory containing length at offset
@@ -403,27 +421,120 @@ out:
        return rc;
 }
 
+/**
+ * ecryptfs_verify_version
+ * @version: The version number to confirm
+ *
+ * Returns zero on good version; non-zero otherwise
+ */
+static int ecryptfs_verify_version(u16 version)
+{
+       int rc = 0;
+       unsigned char major;
+       unsigned char minor;
+
+       major = ((version >> 8) & 0xFF);
+       minor = (version & 0xFF);
+       if (major != ECRYPTFS_VERSION_MAJOR) {
+               ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
+                               "Expected [%d]; got [%d]\n",
+                               ECRYPTFS_VERSION_MAJOR, major);
+               rc = -EINVAL;
+               goto out;
+       }
+       if (minor != ECRYPTFS_VERSION_MINOR) {
+               ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
+                               "Expected [%d]; got [%d]\n",
+                               ECRYPTFS_VERSION_MINOR, minor);
+               rc = -EINVAL;
+               goto out;
+       }
+out:
+       return rc;
+}
+
+/**
+ * ecryptfs_verify_auth_tok_from_key
+ * @auth_tok_key: key containing the authentication token
+ * @auth_tok: authentication token
+ *
+ * Returns zero on valid auth tok; -EINVAL otherwise
+ */
+static int
+ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
+                                 struct ecryptfs_auth_tok **auth_tok)
+{
+       int rc = 0;
+
+       (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
+       if (ecryptfs_verify_version((*auth_tok)->version)) {
+               printk(KERN_ERR "Data structure version mismatch. Userspace "
+                      "tools must match eCryptfs kernel module with major "
+                      "version [%d] and minor version [%d]\n",
+                      ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR);
+               rc = -EINVAL;
+               goto out;
+       }
+       if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
+           && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
+               printk(KERN_ERR "Invalid auth_tok structure "
+                      "returned from key query\n");
+               rc = -EINVAL;
+               goto out;
+       }
+out:
+       return rc;
+}
+
 static int
 ecryptfs_find_global_auth_tok_for_sig(
-       struct ecryptfs_global_auth_tok **global_auth_tok,
+       struct key **auth_tok_key,
+       struct ecryptfs_auth_tok **auth_tok,
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
 {
        struct ecryptfs_global_auth_tok *walker;
        int rc = 0;
 
-       (*global_auth_tok) = NULL;
+       (*auth_tok_key) = NULL;
+       (*auth_tok) = NULL;
        mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
        list_for_each_entry(walker,
                            &mount_crypt_stat->global_auth_tok_list,
                            mount_crypt_stat_list) {
-               if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
-                       rc = key_validate(walker->global_auth_tok_key);
-                       if (!rc)
-                               (*global_auth_tok) = walker;
+               if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX))
+                       continue;
+
+               if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) {
+                       rc = -EINVAL;
                        goto out;
                }
+
+               rc = key_validate(walker->global_auth_tok_key);
+               if (rc) {
+                       if (rc == -EKEYEXPIRED)
+                               goto out;
+                       goto out_invalid_auth_tok;
+               }
+
+               down_write(&(walker->global_auth_tok_key->sem));
+               rc = ecryptfs_verify_auth_tok_from_key(
+                               walker->global_auth_tok_key, auth_tok);
+               if (rc)
+                       goto out_invalid_auth_tok_unlock;
+
+               (*auth_tok_key) = walker->global_auth_tok_key;
+               key_get(*auth_tok_key);
+               goto out;
        }
-       rc = -EINVAL;
+       rc = -ENOENT;
+       goto out;
+out_invalid_auth_tok_unlock:
+       up_write(&(walker->global_auth_tok_key->sem));
+out_invalid_auth_tok:
+       printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig);
+       walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
+       key_put(walker->global_auth_tok_key);
+       walker->global_auth_tok_key = NULL;
 out:
        mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
        return rc;
@@ -451,14 +562,11 @@ ecryptfs_find_auth_tok_for_sig(
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
        char *sig)
 {
-       struct ecryptfs_global_auth_tok *global_auth_tok;
        int rc = 0;
 
-       (*auth_tok_key) = NULL;
-       (*auth_tok) = NULL;
-       if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
-                                                 mount_crypt_stat, sig)) {
-
+       rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok,
+                                                  mount_crypt_stat, sig);
+       if (rc == -ENOENT) {
                /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the
                 * mount_crypt_stat structure, we prevent to use auth toks that
                 * are not inserted through the ecryptfs_add_global_auth_tok
@@ -470,8 +578,7 @@ ecryptfs_find_auth_tok_for_sig(
 
                rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,
                                                       sig);
-       } else
-               (*auth_tok) = global_auth_tok->global_auth_tok;
+       }
        return rc;
 }
 
@@ -531,6 +638,16 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
        }
        s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
        (*packet_size) = 0;
+       rc = ecryptfs_find_auth_tok_for_sig(
+               &auth_tok_key,
+               &s->auth_tok, mount_crypt_stat,
+               mount_crypt_stat->global_default_fnek_sig);
+       if (rc) {
+               printk(KERN_ERR "%s: Error attempting to find auth tok for "
+                      "fnek sig [%s]; rc = [%d]\n", __func__,
+                      mount_crypt_stat->global_default_fnek_sig, rc);
+               goto out;
+       }
        rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(
                &s->desc.tfm,
                &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name);
@@ -616,16 +733,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
                goto out_free_unlock;
        }
        dest[s->i++] = s->cipher_code;
-       rc = ecryptfs_find_auth_tok_for_sig(
-               &auth_tok_key,
-               &s->auth_tok, mount_crypt_stat,
-               mount_crypt_stat->global_default_fnek_sig);
-       if (rc) {
-               printk(KERN_ERR "%s: Error attempting to find auth tok for "
-                      "fnek sig [%s]; rc = [%d]\n", __func__,
-                      mount_crypt_stat->global_default_fnek_sig, rc);
-               goto out_free_unlock;
-       }
        /* TODO: Support other key modules than passphrase for
         * filename encryption */
        if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
@@ -765,8 +872,10 @@ out_free_unlock:
 out_unlock:
        mutex_unlock(s->tfm_mutex);
 out:
-       if (auth_tok_key)
+       if (auth_tok_key) {
+               up_write(&(auth_tok_key->sem));
                key_put(auth_tok_key);
+       }
        kfree(s);
        return rc;
 }
@@ -879,6 +988,15 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
                       __func__, s->cipher_code);
                goto out;
        }
+       rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
+                                           &s->auth_tok, mount_crypt_stat,
+                                           s->fnek_sig_hex);
+       if (rc) {
+               printk(KERN_ERR "%s: Error attempting to find auth tok for "
+                      "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
+                      rc);
+               goto out;
+       }
        rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm,
                                                        &s->tfm_mutex,
                                                        s->cipher_string);
@@ -925,15 +1043,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
         * >= ECRYPTFS_MAX_IV_BYTES. */
        memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);
        s->desc.info = s->iv;
-       rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
-                                           &s->auth_tok, mount_crypt_stat,
-                                           s->fnek_sig_hex);
-       if (rc) {
-               printk(KERN_ERR "%s: Error attempting to find auth tok for "
-                      "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
-                      rc);
-               goto out_free_unlock;
-       }
        /* TODO: Support other key modules than passphrase for
         * filename encryption */
        if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
@@ -1002,8 +1111,10 @@ out:
                (*filename_size) = 0;
                (*filename) = NULL;
        }
-       if (auth_tok_key)
+       if (auth_tok_key) {
+               up_write(&(auth_tok_key->sem));
                key_put(auth_tok_key);
+       }
        kfree(s);
        return rc;
 }
@@ -1520,38 +1631,6 @@ out:
        return rc;
 }
 
-/**
- * ecryptfs_verify_version
- * @version: The version number to confirm
- *
- * Returns zero on good version; non-zero otherwise
- */
-static int ecryptfs_verify_version(u16 version)
-{
-       int rc = 0;
-       unsigned char major;
-       unsigned char minor;
-
-       major = ((version >> 8) & 0xFF);
-       minor = (version & 0xFF);
-       if (major != ECRYPTFS_VERSION_MAJOR) {
-               ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
-                               "Expected [%d]; got [%d]\n",
-                               ECRYPTFS_VERSION_MAJOR, major);
-               rc = -EINVAL;
-               goto out;
-       }
-       if (minor != ECRYPTFS_VERSION_MINOR) {
-               ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
-                               "Expected [%d]; got [%d]\n",
-                               ECRYPTFS_VERSION_MINOR, minor);
-               rc = -EINVAL;
-               goto out;
-       }
-out:
-       return rc;
-}
-
 int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
                                      struct ecryptfs_auth_tok **auth_tok,
                                      char *sig)
@@ -1563,31 +1642,16 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
                printk(KERN_ERR "Could not find key with description: [%s]\n",
                       sig);
                rc = process_request_key_err(PTR_ERR(*auth_tok_key));
+               (*auth_tok_key) = NULL;
                goto out;
        }
-       (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
-       if (ecryptfs_verify_version((*auth_tok)->version)) {
-               printk(KERN_ERR
-                      "Data structure version mismatch. "
-                      "Userspace tools must match eCryptfs "
-                      "kernel module with major version [%d] "
-                      "and minor version [%d]\n",
-                      ECRYPTFS_VERSION_MAJOR,
-                      ECRYPTFS_VERSION_MINOR);
-               rc = -EINVAL;
-               goto out_release_key;
-       }
-       if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
-           && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
-               printk(KERN_ERR "Invalid auth_tok structure "
-                      "returned from key query\n");
-               rc = -EINVAL;
-               goto out_release_key;
-       }
-out_release_key:
+       down_write(&(*auth_tok_key)->sem);
+       rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
        if (rc) {
+               up_write(&(*auth_tok_key)->sem);
                key_put(*auth_tok_key);
                (*auth_tok_key) = NULL;
+               goto out;
        }
 out:
        return rc;
@@ -1809,6 +1873,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
 find_next_matching_auth_tok:
        found_auth_tok = 0;
        if (auth_tok_key) {
+               up_write(&(auth_tok_key->sem));
                key_put(auth_tok_key);
                auth_tok_key = NULL;
        }
@@ -1895,8 +1960,10 @@ found_matching_auth_tok:
 out_wipe_list:
        wipe_auth_tok_list(&auth_tok_list);
 out:
-       if (auth_tok_key)
+       if (auth_tok_key) {
+               up_write(&(auth_tok_key->sem));
                key_put(auth_tok_key);
+       }
        return rc;
 }
 
@@ -2324,7 +2391,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                                 size_t max)
 {
        struct ecryptfs_auth_tok *auth_tok;
-       struct ecryptfs_global_auth_tok *global_auth_tok;
+       struct key *auth_tok_key = NULL;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
                &ecryptfs_superblock_to_private(
                        ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -2343,21 +2410,16 @@ ecryptfs_generate_key_packet_set(char *dest_base,
        list_for_each_entry(key_sig, &crypt_stat->keysig_list,
                            crypt_stat_list) {
                memset(key_rec, 0, sizeof(*key_rec));
-               rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+               rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key,
+                                                          &auth_tok,
                                                           mount_crypt_stat,
                                                           key_sig->keysig);
                if (rc) {
-                       printk(KERN_ERR "Error attempting to get the global "
-                              "auth_tok; rc = [%d]\n", rc);
+                       printk(KERN_WARNING "Unable to retrieve auth tok with "
+                              "sig = [%s]\n", key_sig->keysig);
+                       rc = process_find_global_auth_tok_for_sig_err(rc);
                        goto out_free;
                }
-               if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) {
-                       printk(KERN_WARNING
-                              "Skipping invalid auth tok with sig = [%s]\n",
-                              global_auth_tok->sig);
-                       continue;
-               }
-               auth_tok = global_auth_tok->global_auth_tok;
                if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
                        rc = write_tag_3_packet((dest_base + (*len)),
                                                &max, auth_tok,
@@ -2395,6 +2457,9 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                        rc = -EINVAL;
                        goto out_free;
                }
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
+               auth_tok_key = NULL;
        }
        if (likely(max > 0)) {
                dest_base[(*len)] = 0x00;
@@ -2407,6 +2472,11 @@ out_free:
 out:
        if (rc)
                (*len) = 0;
+       if (auth_tok_key) {
+               up_write(&(auth_tok_key->sem));
+               key_put(auth_tok_key);
+       }
+
        mutex_unlock(&crypt_stat->keysig_list_mutex);
        return rc;
 }
@@ -2424,6 +2494,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
                return -ENOMEM;
        }
        memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
+       new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
        /* Caller must hold keysig_list_mutex */
        list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
 
@@ -2453,7 +2524,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
        mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
        list_add(&new_auth_tok->mount_crypt_stat_list,
                 &mount_crypt_stat->global_auth_tok_list);
-       mount_crypt_stat->num_global_auth_toks++;
        mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
 out:
        return rc;
index 758323a0f09a1a99101aee135d2a16e8289e78b9..c27c0ecf90bcec2394b5f44eece394fe3a7acb26 100644 (file)
@@ -122,7 +122,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
        int rc = 0;
 
-       mutex_lock(&inode_info->lower_file_mutex);
        if (!inode_info->lower_file) {
                struct dentry *lower_dentry;
                struct vfsmount *lower_mnt =
@@ -138,7 +137,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                        inode_info->lower_file = NULL;
                }
        }
-       mutex_unlock(&inode_info->lower_file_mutex);
        return rc;
 }
 
@@ -241,14 +239,14 @@ static int ecryptfs_init_global_auth_toks(
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
 {
        struct ecryptfs_global_auth_tok *global_auth_tok;
+       struct ecryptfs_auth_tok *auth_tok;
        int rc = 0;
 
        list_for_each_entry(global_auth_tok,
                            &mount_crypt_stat->global_auth_tok_list,
                            mount_crypt_stat_list) {
                rc = ecryptfs_keyring_auth_tok_for_sig(
-                       &global_auth_tok->global_auth_tok_key,
-                       &global_auth_tok->global_auth_tok,
+                       &global_auth_tok->global_auth_tok_key, &auth_tok,
                        global_auth_tok->sig);
                if (rc) {
                        printk(KERN_ERR "Could not find valid key in user "
@@ -256,8 +254,10 @@ static int ecryptfs_init_global_auth_toks(
                               "option: [%s]\n", global_auth_tok->sig);
                        global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
                        goto out;
-               } else
+               } else {
                        global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
+                       up_write(&(global_auth_tok->global_auth_tok_key)->sem);
+               }
        }
 out:
        return rc;
index cc64fca89f8dc995f8ca5af82d135c053c6d59b2..6a44148c5fb97e3cfb866a024de27dbea2fbff39 100644 (file)
@@ -62,6 +62,18 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
 {
        int rc;
 
+       /*
+        * Refuse to write the page out if we are called from reclaim context
+        * since our writepage() path may potentially allocate memory when
+        * calling into the lower fs vfs_write() which may in turn invoke
+        * us again.
+        */
+       if (current->flags & PF_MEMALLOC) {
+               redirty_page_for_writepage(wbc, page);
+               rc = 0;
+               goto out;
+       }
+
        rc = ecryptfs_encrypt_page(page);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error encrypting "
@@ -70,8 +82,8 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
                goto out;
        }
        SetPageUptodate(page);
-       unlock_page(page);
 out:
+       unlock_page(page);
        return rc;
 }
 
@@ -193,11 +205,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
                &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
        int rc = 0;
 
-       if (!crypt_stat
-           || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
-           || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
-               ecryptfs_printk(KERN_DEBUG,
-                               "Passing through unencrypted page\n");
+       if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
                rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
                                                      PAGE_CACHE_SIZE,
                                                      page->mapping->host);
@@ -295,8 +303,7 @@ static int ecryptfs_write_begin(struct file *file,
                struct ecryptfs_crypt_stat *crypt_stat =
                        &ecryptfs_inode_to_private(mapping->host)->crypt_stat;
 
-               if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
-                   || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
+               if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
                        rc = ecryptfs_read_lower_page_segment(
                                page, index, 0, PAGE_CACHE_SIZE, mapping->host);
                        if (rc) {
@@ -374,6 +381,11 @@ static int ecryptfs_write_begin(struct file *file,
            && (pos != 0))
                zero_user(page, 0, PAGE_CACHE_SIZE);
 out:
+       if (unlikely(rc)) {
+               unlock_page(page);
+               page_cache_release(page);
+               *pagep = NULL;
+       }
        return rc;
 }
 
@@ -486,13 +498,8 @@ static int ecryptfs_write_end(struct file *file,
        struct ecryptfs_crypt_stat *crypt_stat =
                &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        int rc;
+       int need_unlock_page = 1;
 
-       if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
-               ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
-                       "crypt_stat at memory location [%p]\n", crypt_stat);
-               crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
-       } else
-               ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
        ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
                        "(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
        if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
@@ -512,26 +519,26 @@ static int ecryptfs_write_end(struct file *file,
                        "zeros in page with index = [0x%.16lx]\n", index);
                goto out;
        }
-       rc = ecryptfs_encrypt_page(page);
-       if (rc) {
-               ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
-                               "index [0x%.16lx])\n", index);
-               goto out;
-       }
+       set_page_dirty(page);
+       unlock_page(page);
+       need_unlock_page = 0;
        if (pos + copied > i_size_read(ecryptfs_inode)) {
                i_size_write(ecryptfs_inode, pos + copied);
                ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
                        "[0x%.16llx]\n",
                        (unsigned long long)i_size_read(ecryptfs_inode));
+               balance_dirty_pages_ratelimited(mapping);
+               rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
+               if (rc) {
+                       printk(KERN_ERR "Error writing inode size to metadata; "
+                              "rc = [%d]\n", rc);
+                       goto out;
+               }
        }
-       rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
-       if (rc)
-               printk(KERN_ERR "Error writing inode size to metadata; "
-                      "rc = [%d]\n", rc);
-       else
-               rc = copied;
+       rc = copied;
 out:
-       unlock_page(page);
+       if (need_unlock_page)
+               unlock_page(page);
        page_cache_release(page);
        return rc;
 }
index db184ef15d3d8c012ce4586d7abf276efbf6eb8a..85d43096311625b37dd12beeeab7149a00899d0e 100644 (file)
@@ -44,15 +44,11 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
        ssize_t rc;
 
        inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
-       mutex_lock(&inode_info->lower_file_mutex);
        BUG_ON(!inode_info->lower_file);
-       inode_info->lower_file->f_pos = offset;
        fs_save = get_fs();
        set_fs(get_ds());
-       rc = vfs_write(inode_info->lower_file, data, size,
-                      &inode_info->lower_file->f_pos);
+       rc = vfs_write(inode_info->lower_file, data, size, &offset);
        set_fs(fs_save);
-       mutex_unlock(&inode_info->lower_file_mutex);
        mark_inode_dirty_sync(ecryptfs_inode);
        return rc;
 }
@@ -234,15 +230,11 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
        mm_segment_t fs_save;
        ssize_t rc;
 
-       mutex_lock(&inode_info->lower_file_mutex);
        BUG_ON(!inode_info->lower_file);
-       inode_info->lower_file->f_pos = offset;
        fs_save = get_fs();
        set_fs(get_ds());
-       rc = vfs_read(inode_info->lower_file, data, size,
-                     &inode_info->lower_file->f_pos);
+       rc = vfs_read(inode_info->lower_file, data, size, &offset);
        set_fs(fs_save);
-       mutex_unlock(&inode_info->lower_file_mutex);
        return rc;
 }
 
index 3042fe123a3426c30dba69e35a622738977bf105..bacc882e1ae40454f7623ac81e78968155d9ae55 100644 (file)
@@ -55,7 +55,6 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
        if (unlikely(!inode_info))
                goto out;
        ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
-       mutex_init(&inode_info->lower_file_mutex);
        inode_info->lower_file = NULL;
        inode = &inode_info->vfs_inode;
 out:
@@ -198,7 +197,7 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
 const struct super_operations ecryptfs_sops = {
        .alloc_inode = ecryptfs_alloc_inode,
        .destroy_inode = ecryptfs_destroy_inode,
-       .drop_inode = generic_delete_inode,
+       .drop_inode = generic_drop_inode,
        .statfs = ecryptfs_statfs,
        .remount_fs = NULL,
        .evict_inode = ecryptfs_evict_inode,
index 05a1f75ae79181cbb190b93a29c5fa4e03dff0d4..5f4e11aaeb5c6b7cb0bf045b3dd5b9a53fbcfc87 100644 (file)
@@ -1167,7 +1167,7 @@ EXPORT_SYMBOL(igrab);
  * Note: I_NEW is not waited upon so you have to be very careful what you do
  * with the returned inode.  You probably should be using ilookup5() instead.
  *
- * Note: @test is called with the inode_hash_lock held, so can't sleep.
+ * Note2: @test is called with the inode_hash_lock held, so can't sleep.
  */
 struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
                int (*test)(struct inode *, void *), void *data)
index 4f9cc04829492eff86aecbe7c4ecb263df78bb48..3e93cdd1900552d18e900f3b255eff3d356c6a48 100644 (file)
@@ -31,7 +31,7 @@
  *   is used to release xattr name/value pair and detach from c->xattrindex.
  * reclaim_xattr_datum(c)
  *   is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
- *   memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold 
+ *   memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold
  *   is hard coded as 32KiB.
  * do_verify_xattr_datum(c, xd)
  *   is used to load the xdatum informations without name/value pair from the medium.
index ad92bf731ff570a560919ef4eb22b3eb50f0027e..9166fcb66da219f4b9d2a8dc4445b5b945627b16 100644 (file)
@@ -192,13 +192,15 @@ static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct de
        auth   = rpcauth_create(flavor, clone);
        if (!auth) {
                flavor = -EIO;
-               goto out;
+               goto out_shutdown;
        }
        err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode,
                                                  &path->dentry->d_name,
                                                  fh, fattr);
        if (err < 0)
                flavor = err;
+out_shutdown:
+       rpc_shutdown_client(clone);
 out:
        return flavor;
 }
index ab1bf5bb021f55cfaf3c45dcbdb226acfc3da3e0..a6804f704d9d8656868b6492c66232020132fe6d 100644 (file)
@@ -590,7 +590,8 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
                state->owner = owner;
                atomic_inc(&owner->so_count);
                list_add(&state->inode_states, &nfsi->open_states);
-               state->inode = igrab(inode);
+               ihold(inode);
+               state->inode = inode;
                spin_unlock(&inode->i_lock);
                /* Note: The reclaim code dictates that we add stateless
                 * and read-only stateids to the end of the list */
index 87a593c2b055503e727c2cda93a396ecb2681fb5..c80add6e2213ab6d4f301a2ca06134b4a4f5581c 100644 (file)
@@ -135,14 +135,14 @@ void nfs_clear_page_tag_locked(struct nfs_page *req)
                nfs_unlock_request(req);
 }
 
-/**
+/*
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
  * Release page and open context resources associated with a read/write
  * request after it has completed.
  */
-void nfs_clear_request(struct nfs_page *req)
+static void nfs_clear_request(struct nfs_page *req)
 {
        struct page *page = req->wb_page;
        struct nfs_open_context *ctx = req->wb_context;
index 85d75254328ebd1c822187e51a3f5b5e9fc320b7..af0c6279a4a7c131cd9c2a80e0764ba8ea50a6c9 100644 (file)
@@ -389,11 +389,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
        spin_lock(&inode->i_lock);
        error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req);
        BUG_ON(error);
-       if (!nfsi->npages) {
-               igrab(inode);
-               if (nfs_have_delegation(inode, FMODE_WRITE))
-                       nfsi->change_attr++;
-       }
+       if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE))
+               nfsi->change_attr++;
        set_bit(PG_MAPPED, &req->wb_flags);
        SetPagePrivate(req->wb_page);
        set_page_private(req->wb_page, (unsigned long)req);
@@ -423,11 +420,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        clear_bit(PG_MAPPED, &req->wb_flags);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
-       if (!nfsi->npages) {
-               spin_unlock(&inode->i_lock);
-               iput(inode);
-       } else
-               spin_unlock(&inode->i_lock);
+       spin_unlock(&inode->i_lock);
        nfs_release_request(req);
 }
 
index 90f2729b7a5bc031e778fad1cf4b665409394247..e913ad130fdd2cf9eafa0e73e343bad5974583e9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
index e4984e259cb6b9eec82ed22ae376e51fad986029..b27a0d86f8c584fd9f15aff29a4ceb3032d8910a 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/swap.h>
 #include <linux/quotaops.h>
 
-#define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -50,6 +49,7 @@
 #include "uptodate.h"
 #include "xattr.h"
 #include "refcounttree.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -886,8 +886,7 @@ static int ocfs2_validate_extent_block(struct super_block *sb,
        struct ocfs2_extent_block *eb =
                (struct ocfs2_extent_block *)bh->b_data;
 
-       mlog(0, "Validating extent block %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_extent_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -965,8 +964,6 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
        struct buffer_head *eb_bh = NULL;
        u64 last_eb_blk = 0;
 
-       mlog_entry_void();
-
        el = et->et_root_el;
        last_eb_blk = ocfs2_et_get_last_eb_blk(et);
 
@@ -987,7 +984,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
 bail:
        brelse(eb_bh);
 
-       mlog_exit(retval);
+       trace_ocfs2_num_free_extents(retval);
        return retval;
 }
 
@@ -1010,8 +1007,6 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
                OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
        struct ocfs2_extent_block *eb;
 
-       mlog_entry_void();
-
        count = 0;
        while (count < wanted) {
                status = ocfs2_claim_metadata(handle,
@@ -1074,8 +1069,8 @@ bail:
                        brelse(bhs[i]);
                        bhs[i] = NULL;
                }
+               mlog_errno(status);
        }
-       mlog_exit(status);
        return status;
 }
 
@@ -1173,8 +1168,6 @@ static int ocfs2_add_branch(handle_t *handle,
        struct ocfs2_extent_list  *el;
        u32 new_cpos, root_end;
 
-       mlog_entry_void();
-
        BUG_ON(!last_eb_bh || !*last_eb_bh);
 
        if (eb_bh) {
@@ -1200,8 +1193,11 @@ static int ocfs2_add_branch(handle_t *handle,
         * from new_cpos).
         */
        if (root_end > new_cpos) {
-               mlog(0, "adjust the cluster end from %u to %u\n",
-                    root_end, new_cpos);
+               trace_ocfs2_adjust_rightmost_branch(
+                       (unsigned long long)
+                       ocfs2_metadata_cache_owner(et->et_ci),
+                       root_end, new_cpos);
+
                status = ocfs2_adjust_rightmost_branch(handle, et);
                if (status) {
                        mlog_errno(status);
@@ -1332,7 +1328,6 @@ bail:
                kfree(new_eb_bhs);
        }
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1353,8 +1348,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle,
        struct ocfs2_extent_list  *root_el;
        struct ocfs2_extent_list  *eb_el;
 
-       mlog_entry_void();
-
        status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac,
                                           &new_eb_bh);
        if (status < 0) {
@@ -1415,7 +1408,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle,
 bail:
        brelse(new_eb_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1446,8 +1438,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,
        struct buffer_head *bh = NULL;
        struct buffer_head *lowest_bh = NULL;
 
-       mlog_entry_void();
-
        *target_bh = NULL;
 
        el = et->et_root_el;
@@ -1503,7 +1493,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,
 bail:
        brelse(bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1540,7 +1529,10 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,
         * another tree level */
        if (shift) {
                BUG_ON(bh);
-               mlog(0, "need to shift tree depth (current = %d)\n", depth);
+               trace_ocfs2_grow_tree(
+                       (unsigned long long)
+                       ocfs2_metadata_cache_owner(et->et_ci),
+                       depth);
 
                /* ocfs2_shift_tree_depth will return us a buffer with
                 * the new extent block (so we can pass that to
@@ -1570,7 +1562,6 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,
 
        /* call ocfs2_add_branch to add the final part of the tree with
         * the new data. */
-       mlog(0, "add branch. bh = %p\n", bh);
        ret = ocfs2_add_branch(handle, et, bh, last_eb_bh,
                               meta_ac);
        if (ret < 0) {
@@ -1645,8 +1636,9 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
        }
        insert_index = i;
 
-       mlog(0, "ins %u: index %d, has_empty %d, next_free %d, count %d\n",
-            insert_cpos, insert_index, has_empty, next_free, le16_to_cpu(el->l_count));
+       trace_ocfs2_rotate_leaf(insert_cpos, insert_index,
+                               has_empty, next_free,
+                               le16_to_cpu(el->l_count));
 
        BUG_ON(insert_index < 0);
        BUG_ON(insert_index >= le16_to_cpu(el->l_count));
@@ -2059,7 +2051,7 @@ static void ocfs2_complete_edge_insert(handle_t *handle,
        left_el = path_leaf_el(left_path);
        right_el = path_leaf_el(right_path);
        for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) {
-               mlog(0, "Adjust records at index %u\n", i);
+               trace_ocfs2_complete_edge_insert(i);
 
                /*
                 * One nice property of knowing that all of these
@@ -2389,7 +2381,9 @@ static int ocfs2_rotate_tree_right(handle_t *handle,
                goto out;
        }
 
-       mlog(0, "Insert: %u, first left path cpos: %u\n", insert_cpos, cpos);
+       trace_ocfs2_rotate_tree_right(
+               (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+               insert_cpos, cpos);
 
        /*
         * What we want to do here is:
@@ -2418,8 +2412,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle,
         * rotating subtrees.
         */
        while (cpos && insert_cpos <= cpos) {
-               mlog(0, "Rotating a tree: ins. cpos: %u, left path cpos: %u\n",
-                    insert_cpos, cpos);
+               trace_ocfs2_rotate_tree_right(
+                       (unsigned long long)
+                       ocfs2_metadata_cache_owner(et->et_ci),
+                       insert_cpos, cpos);
 
                ret = ocfs2_find_path(et->et_ci, left_path, cpos);
                if (ret) {
@@ -2461,10 +2457,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle,
 
                start = ocfs2_find_subtree_root(et, left_path, right_path);
 
-               mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
-                    start,
-                    (unsigned long long) right_path->p_node[start].bh->b_blocknr,
-                    right_path->p_tree_depth);
+               trace_ocfs2_rotate_subtree(start,
+                       (unsigned long long)
+                       right_path->p_node[start].bh->b_blocknr,
+                       right_path->p_tree_depth);
 
                ret = ocfs2_extend_rotate_transaction(handle, start,
                                                      orig_credits, right_path);
@@ -2964,8 +2960,7 @@ static int __ocfs2_rotate_tree_left(handle_t *handle,
                subtree_root = ocfs2_find_subtree_root(et, left_path,
                                                       right_path);
 
-               mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
-                    subtree_root,
+               trace_ocfs2_rotate_subtree(subtree_root,
                     (unsigned long long)
                     right_path->p_node[subtree_root].bh->b_blocknr,
                     right_path->p_tree_depth);
@@ -3989,9 +3984,11 @@ static int ocfs2_append_rec_to_path(handle_t *handle,
                        goto out;
                }
 
-               mlog(0, "Append may need a left path update. cpos: %u, "
-                    "left_cpos: %u\n", le32_to_cpu(insert_rec->e_cpos),
-                    left_cpos);
+               trace_ocfs2_append_rec_to_path(
+                       (unsigned long long)
+                       ocfs2_metadata_cache_owner(et->et_ci),
+                       le32_to_cpu(insert_rec->e_cpos),
+                       left_cpos);
 
                /*
                 * No need to worry if the append is already in the
@@ -4562,7 +4559,7 @@ static int ocfs2_figure_insert_type(struct ocfs2_extent_tree *et,
                                              ocfs2_et_get_last_eb_blk(et),
                                              &bh);
                if (ret) {
-                       mlog_exit(ret);
+                       mlog_errno(ret);
                        goto out;
                }
                eb = (struct ocfs2_extent_block *) bh->b_data;
@@ -4678,9 +4675,9 @@ int ocfs2_insert_extent(handle_t *handle,
        struct ocfs2_insert_type insert = {0, };
        struct ocfs2_extent_rec rec;
 
-       mlog(0, "add %u clusters at position %u to owner %llu\n",
-            new_clusters, cpos,
-            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
+       trace_ocfs2_insert_extent_start(
+               (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+               cpos, new_clusters);
 
        memset(&rec, 0, sizeof(rec));
        rec.e_cpos = cpu_to_le32(cpos);
@@ -4700,11 +4697,9 @@ int ocfs2_insert_extent(handle_t *handle,
                goto bail;
        }
 
-       mlog(0, "Insert.appending: %u, Insert.Contig: %u, "
-            "Insert.contig_index: %d, Insert.free_records: %d, "
-            "Insert.tree_depth: %d\n",
-            insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
-            free_records, insert.ins_tree_depth);
+       trace_ocfs2_insert_extent(insert.ins_appending, insert.ins_contig,
+                                 insert.ins_contig_index, free_records,
+                                 insert.ins_tree_depth);
 
        if (insert.ins_contig == CONTIG_NONE && free_records == 0) {
                status = ocfs2_grow_tree(handle, et,
@@ -4726,7 +4721,6 @@ int ocfs2_insert_extent(handle_t *handle,
 bail:
        brelse(last_eb_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -4746,7 +4740,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
                                struct ocfs2_alloc_context *meta_ac,
                                enum ocfs2_alloc_restarted *reason_ret)
 {
-       int status = 0;
+       int status = 0, err = 0;
        int free_extents;
        enum ocfs2_alloc_restarted reason = RESTART_NONE;
        u32 bit_off, num_bits;
@@ -4773,14 +4767,14 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
         * 2) we are so fragmented, we've needed to add metadata too
         *    many times. */
        if (!free_extents && !meta_ac) {
-               mlog(0, "we haven't reserved any metadata!\n");
+               err = -1;
                status = -EAGAIN;
                reason = RESTART_META;
                goto leave;
        } else if ((!free_extents)
                   && (ocfs2_alloc_context_bits_left(meta_ac)
                       < ocfs2_extend_meta_needed(et->et_root_el))) {
-               mlog(0, "filesystem is really fragmented...\n");
+               err = -2;
                status = -EAGAIN;
                reason = RESTART_META;
                goto leave;
@@ -4805,9 +4799,9 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
        }
 
        block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "Allocating %u clusters at block %u for owner %llu\n",
-            num_bits, bit_off,
-            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
+       trace_ocfs2_add_clusters_in_btree(
+            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+            bit_off, num_bits);
        status = ocfs2_insert_extent(handle, et, *logical_offset, block,
                                     num_bits, flags, meta_ac);
        if (status < 0) {
@@ -4821,16 +4815,15 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
        *logical_offset += num_bits;
 
        if (clusters_to_add) {
-               mlog(0, "need to alloc once more, wanted = %u\n",
-                    clusters_to_add);
+               err = clusters_to_add;
                status = -EAGAIN;
                reason = RESTART_TRANS;
        }
 
 leave:
-       mlog_exit(status);
        if (reason_ret)
                *reason_ret = reason;
+       trace_ocfs2_add_clusters_in_btree_ret(status, reason, err);
        return status;
 }
 
@@ -5039,7 +5032,7 @@ int ocfs2_split_extent(handle_t *handle,
                                              ocfs2_et_get_last_eb_blk(et),
                                              &last_eb_bh);
                if (ret) {
-                       mlog_exit(ret);
+                       mlog_errno(ret);
                        goto out;
                }
 
@@ -5056,9 +5049,9 @@ int ocfs2_split_extent(handle_t *handle,
 
        ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
 
-       mlog(0, "index: %d, contig: %u, has_empty: %u, split_covers: %u\n",
-            split_index, ctxt.c_contig_type, ctxt.c_has_empty_extent,
-            ctxt.c_split_covers_rec);
+       trace_ocfs2_split_extent(split_index, ctxt.c_contig_type,
+                                ctxt.c_has_empty_extent,
+                                ctxt.c_split_covers_rec);
 
        if (ctxt.c_contig_type == CONTIG_NONE) {
                if (ctxt.c_split_covers_rec)
@@ -5192,8 +5185,9 @@ int ocfs2_mark_extent_written(struct inode *inode,
 {
        int ret;
 
-       mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n",
-            inode->i_ino, cpos, len, phys);
+       trace_ocfs2_mark_extent_written(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               cpos, len, phys);
 
        if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
                ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
@@ -5512,11 +5506,10 @@ int ocfs2_remove_extent(handle_t *handle,
 
        BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range);
 
-       mlog(0, "Owner %llu, remove (cpos %u, len %u). Existing index %d "
-            "(cpos %u, len %u)\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
-            cpos, len, index,
-            le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec));
+       trace_ocfs2_remove_extent(
+               (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+               cpos, len, index, le32_to_cpu(rec->e_cpos),
+               ocfs2_rec_clusters(el, rec));
 
        if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
                ret = ocfs2_truncate_rec(handle, et, path, index, dealloc,
@@ -5795,9 +5788,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
        struct ocfs2_dinode *di;
        struct ocfs2_truncate_log *tl;
 
-       mlog_entry("start_blk = %llu, num_clusters = %u\n",
-                  (unsigned long long)start_blk, num_clusters);
-
        BUG_ON(mutex_trylock(&tl_inode->i_mutex));
 
        start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk);
@@ -5834,10 +5824,9 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
                goto bail;
        }
 
-       mlog(0, "Log truncate of %u clusters starting at cluster %u to "
-            "%llu (index = %d)\n", num_clusters, start_cluster,
-            (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index);
-
+       trace_ocfs2_truncate_log_append(
+               (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index,
+               start_cluster, num_clusters);
        if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) {
                /*
                 * Move index back to the record we are coalescing with.
@@ -5846,9 +5835,10 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
                index--;
 
                num_clusters += le32_to_cpu(tl->tl_recs[index].t_clusters);
-               mlog(0, "Coalesce with index %u (start = %u, clusters = %u)\n",
-                    index, le32_to_cpu(tl->tl_recs[index].t_start),
-                    num_clusters);
+               trace_ocfs2_truncate_log_append(
+                       (unsigned long long)OCFS2_I(tl_inode)->ip_blkno,
+                       index, le32_to_cpu(tl->tl_recs[index].t_start),
+                       num_clusters);
        } else {
                tl->tl_recs[index].t_start = cpu_to_le32(start_cluster);
                tl->tl_used = cpu_to_le16(index + 1);
@@ -5859,7 +5849,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
 
        osb->truncated_clusters += num_clusters;
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -5878,8 +5867,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
        struct inode *tl_inode = osb->osb_tl_inode;
        struct buffer_head *tl_bh = osb->osb_tl_bh;
 
-       mlog_entry_void();
-
        di = (struct ocfs2_dinode *) tl_bh->b_data;
        tl = &di->id2.i_dealloc;
        i = le16_to_cpu(tl->tl_used) - 1;
@@ -5915,8 +5902,9 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
                /* if start_blk is not set, we ignore the record as
                 * invalid. */
                if (start_blk) {
-                       mlog(0, "free record %d, start = %u, clusters = %u\n",
-                            i, le32_to_cpu(rec.t_start), num_clusters);
+                       trace_ocfs2_replay_truncate_records(
+                               (unsigned long long)OCFS2_I(tl_inode)->ip_blkno,
+                               i, le32_to_cpu(rec.t_start), num_clusters);
 
                        status = ocfs2_free_clusters(handle, data_alloc_inode,
                                                     data_alloc_bh, start_blk,
@@ -5932,7 +5920,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
        osb->truncated_clusters = 0;
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -5949,8 +5936,6 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        struct ocfs2_dinode *di;
        struct ocfs2_truncate_log *tl;
 
-       mlog_entry_void();
-
        BUG_ON(mutex_trylock(&tl_inode->i_mutex));
 
        di = (struct ocfs2_dinode *) tl_bh->b_data;
@@ -5962,8 +5947,9 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
 
        tl = &di->id2.i_dealloc;
        num_to_flush = le16_to_cpu(tl->tl_used);
-       mlog(0, "Flush %u records from truncate log #%llu\n",
-            num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno);
+       trace_ocfs2_flush_truncate_log(
+               (unsigned long long)OCFS2_I(tl_inode)->ip_blkno,
+               num_to_flush);
        if (!num_to_flush) {
                status = 0;
                goto out;
@@ -6009,7 +5995,6 @@ out_mutex:
        iput(data_alloc_inode);
 
 out:
-       mlog_exit(status);
        return status;
 }
 
@@ -6032,15 +6017,11 @@ static void ocfs2_truncate_log_worker(struct work_struct *work)
                container_of(work, struct ocfs2_super,
                             osb_truncate_log_wq.work);
 
-       mlog_entry_void();
-
        status = ocfs2_flush_truncate_log(osb);
        if (status < 0)
                mlog_errno(status);
        else
                ocfs2_init_steal_slots(osb);
-
-       mlog_exit(status);
 }
 
 #define OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL (2 * HZ)
@@ -6086,7 +6067,6 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
        *tl_inode = inode;
        *tl_bh    = bh;
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -6106,7 +6086,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
 
        *tl_copy = NULL;
 
-       mlog(0, "recover truncate log from slot %d\n", slot_num);
+       trace_ocfs2_begin_truncate_log_recovery(slot_num);
 
        status = ocfs2_get_truncate_log_info(osb, slot_num, &tl_inode, &tl_bh);
        if (status < 0) {
@@ -6123,8 +6103,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
 
        tl = &di->id2.i_dealloc;
        if (le16_to_cpu(tl->tl_used)) {
-               mlog(0, "We'll have %u logs to recover\n",
-                    le16_to_cpu(tl->tl_used));
+               trace_ocfs2_truncate_log_recovery_num(le16_to_cpu(tl->tl_used));
 
                *tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL);
                if (!(*tl_copy)) {
@@ -6157,9 +6136,9 @@ bail:
        if (status < 0 && (*tl_copy)) {
                kfree(*tl_copy);
                *tl_copy = NULL;
+               mlog_errno(status);
        }
 
-       mlog_exit(status);
        return status;
 }
 
@@ -6174,8 +6153,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
        struct inode *tl_inode = osb->osb_tl_inode;
        struct ocfs2_truncate_log *tl;
 
-       mlog_entry_void();
-
        if (OCFS2_I(tl_inode)->ip_blkno == le64_to_cpu(tl_copy->i_blkno)) {
                mlog(ML_ERROR, "Asked to recover my own truncate log!\n");
                return -EINVAL;
@@ -6183,8 +6160,9 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
 
        tl = &tl_copy->id2.i_dealloc;
        num_recs = le16_to_cpu(tl->tl_used);
-       mlog(0, "cleanup %u records from %llu\n", num_recs,
-            (unsigned long long)le64_to_cpu(tl_copy->i_blkno));
+       trace_ocfs2_complete_truncate_log_recovery(
+               (unsigned long long)le64_to_cpu(tl_copy->i_blkno),
+               num_recs);
 
        mutex_lock(&tl_inode->i_mutex);
        for(i = 0; i < num_recs; i++) {
@@ -6219,7 +6197,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
 bail_up:
        mutex_unlock(&tl_inode->i_mutex);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -6228,8 +6205,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)
        int status;
        struct inode *tl_inode = osb->osb_tl_inode;
 
-       mlog_entry_void();
-
        if (tl_inode) {
                cancel_delayed_work(&osb->osb_truncate_log_wq);
                flush_workqueue(ocfs2_wq);
@@ -6241,8 +6216,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)
                brelse(osb->osb_tl_bh);
                iput(osb->osb_tl_inode);
        }
-
-       mlog_exit_void();
 }
 
 int ocfs2_truncate_log_init(struct ocfs2_super *osb)
@@ -6251,8 +6224,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
        struct inode *tl_inode = NULL;
        struct buffer_head *tl_bh = NULL;
 
-       mlog_entry_void();
-
        status = ocfs2_get_truncate_log_info(osb,
                                             osb->slot_num,
                                             &tl_inode,
@@ -6268,7 +6239,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
        osb->osb_tl_bh    = tl_bh;
        osb->osb_tl_inode = tl_inode;
 
-       mlog_exit(status);
        return status;
 }
 
@@ -6350,8 +6320,8 @@ static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,
                else
                        bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
                                                              head->free_bit);
-               mlog(0, "Free bit: (bit %u, blkno %llu)\n",
-                    head->free_bit, (unsigned long long)head->free_blk);
+               trace_ocfs2_free_cached_blocks(
+                    (unsigned long long)head->free_blk, head->free_bit);
 
                ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
                                               head->free_bit, bg_blkno, 1);
@@ -6404,8 +6374,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
                return ret;
        }
 
-       mlog(0, "Insert clusters: (bit %u, blk %llu)\n",
-            bit, (unsigned long long)blkno);
+       trace_ocfs2_cache_cluster_dealloc((unsigned long long)blkno, bit);
 
        item->free_blk = blkno;
        item->free_bit = bit;
@@ -6480,8 +6449,8 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
                fl = ctxt->c_first_suballocator;
 
                if (fl->f_first) {
-                       mlog(0, "Free items: (type %u, slot %d)\n",
-                            fl->f_inode_type, fl->f_slot);
+                       trace_ocfs2_run_deallocs(fl->f_inode_type,
+                                                fl->f_slot);
                        ret2 = ocfs2_free_cached_blocks(osb,
                                                        fl->f_inode_type,
                                                        fl->f_slot,
@@ -6558,8 +6527,9 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
                goto out;
        }
 
-       mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
-            type, slot, bit, (unsigned long long)blkno);
+       trace_ocfs2_cache_block_dealloc(type, slot,
+                                       (unsigned long long)suballoc,
+                                       (unsigned long long)blkno, bit);
 
        item->free_bg = suballoc;
        item->free_blk = blkno;
@@ -7005,8 +6975,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
        struct ocfs2_extent_tree et;
        struct ocfs2_cached_dealloc_ctxt dealloc;
 
-       mlog_entry_void();
-
        ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
        ocfs2_init_dealloc_ctxt(&dealloc);
 
@@ -7041,8 +7009,11 @@ start:
                goto bail;
        }
 
-       mlog(0, "inode->ip_clusters = %u, tree_depth = %u\n",
-            OCFS2_I(inode)->ip_clusters, path->p_tree_depth);
+       trace_ocfs2_commit_truncate(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               new_highest_cpos,
+               OCFS2_I(inode)->ip_clusters,
+               path->p_tree_depth);
 
        /*
         * By now, el will point to the extent list on the bottom most
@@ -7136,7 +7107,6 @@ bail:
 
        ocfs2_free_path(path);
 
-       mlog_exit(status);
        return status;
 }
 
index daea0359e9740263a525cec5c7f645e456d9a909..ac97bca282d25ebb5943c41ac05fef385d93abf1 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mpage.h>
 #include <linux/quotaops.h>
 
-#define MLOG_MASK_PREFIX ML_FILE_IO
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -45,6 +44,7 @@
 #include "super.h"
 #include "symlink.h"
 #include "refcounttree.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -59,8 +59,9 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        void *kaddr;
 
-       mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode,
-                  (unsigned long long)iblock, bh_result, create);
+       trace_ocfs2_symlink_get_block(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)iblock, bh_result, create);
 
        BUG_ON(ocfs2_inode_is_fast_symlink(inode));
 
@@ -123,7 +124,6 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
 bail:
        brelse(bh);
 
-       mlog_exit(err);
        return err;
 }
 
@@ -136,8 +136,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock,
        u64 p_blkno, count, past_eof;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode,
-                  (unsigned long long)iblock, bh_result, create);
+       trace_ocfs2_get_block((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                             (unsigned long long)iblock, bh_result, create);
 
        if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE)
                mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n",
@@ -199,8 +199,9 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock,
        }
 
        past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
-       mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino,
-            (unsigned long long)past_eof);
+
+       trace_ocfs2_get_block_end((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                 (unsigned long long)past_eof);
        if (create && (iblock >= past_eof))
                set_buffer_new(bh_result);
 
@@ -208,7 +209,6 @@ bail:
        if (err < 0)
                err = -EIO;
 
-       mlog_exit(err);
        return err;
 }
 
@@ -278,7 +278,8 @@ static int ocfs2_readpage(struct file *file, struct page *page)
        loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT;
        int ret, unlock = 1;
 
-       mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0));
+       trace_ocfs2_readpage((unsigned long long)oi->ip_blkno,
+                            (page ? page->index : 0));
 
        ret = ocfs2_inode_lock_with_page(inode, NULL, 0, page);
        if (ret != 0) {
@@ -323,7 +324,6 @@ out_inode_unlock:
 out:
        if (unlock)
                unlock_page(page);
-       mlog_exit(ret);
        return ret;
 }
 
@@ -396,15 +396,11 @@ out_unlock:
  */
 static int ocfs2_writepage(struct page *page, struct writeback_control *wbc)
 {
-       int ret;
-
-       mlog_entry("(0x%p)\n", page);
-
-       ret = block_write_full_page(page, ocfs2_get_block, wbc);
+       trace_ocfs2_writepage(
+               (unsigned long long)OCFS2_I(page->mapping->host)->ip_blkno,
+               page->index);
 
-       mlog_exit(ret);
-
-       return ret;
+       return block_write_full_page(page, ocfs2_get_block, wbc);
 }
 
 /* Taken from ext3. We don't necessarily need the full blown
@@ -450,7 +446,8 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
        int err = 0;
        struct inode *inode = mapping->host;
 
-       mlog_entry("(block = %llu)\n", (unsigned long long)block);
+       trace_ocfs2_bmap((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                        (unsigned long long)block);
 
        /* We don't need to lock journal system files, since they aren't
         * accessed concurrently from multiple nodes.
@@ -484,8 +481,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
 bail:
        status = err ? 0 : p_blkno;
 
-       mlog_exit((int)status);
-
        return status;
 }
 
@@ -616,9 +611,6 @@ static ssize_t ocfs2_direct_IO(int rw,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
-       int ret;
-
-       mlog_entry_void();
 
        /*
         * Fallback to buffered I/O if we see an inode without
@@ -631,13 +623,10 @@ static ssize_t ocfs2_direct_IO(int rw,
        if (i_size_read(inode) <= offset)
                return 0;
 
-       ret = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
-                                  iov, offset, nr_segs,
-                                  ocfs2_direct_IO_get_blocks,
-                                  ocfs2_dio_end_io, NULL, 0);
-
-       mlog_exit(ret);
-       return ret;
+       return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
+                                   iov, offset, nr_segs,
+                                   ocfs2_direct_IO_get_blocks,
+                                   ocfs2_dio_end_io, NULL, 0);
 }
 
 static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb,
@@ -1026,6 +1015,12 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
        ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
                                        &cluster_start, &cluster_end);
 
+       /* treat the write as new if the a hole/lseek spanned across
+        * the page boundary.
+        */
+       new = new | ((i_size_read(inode) <= page_offset(page)) &&
+                       (page_offset(page) <= user_pos));
+
        if (page == wc->w_target_page) {
                map_from = user_pos & (PAGE_CACHE_SIZE - 1);
                map_to = map_from + user_len;
@@ -1534,9 +1529,9 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping,
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_dinode *di = NULL;
 
-       mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n",
-            (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos,
-            oi->ip_dyn_features);
+       trace_ocfs2_try_to_write_inline_data((unsigned long long)oi->ip_blkno,
+                                            len, (unsigned long long)pos,
+                                            oi->ip_dyn_features);
 
        /*
         * Handle inodes which already have inline data 1st.
@@ -1739,6 +1734,13 @@ try_again:
 
        di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
 
+       trace_ocfs2_write_begin_nolock(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (long long)i_size_read(inode),
+                       le32_to_cpu(di->i_clusters),
+                       pos, len, flags, mmap_page,
+                       clusters_to_alloc, extents_to_split);
+
        /*
         * We set w_target_from, w_target_to here so that
         * ocfs2_write_end() knows which range in the target page to
@@ -1751,12 +1753,6 @@ try_again:
                 * ocfs2_lock_allocators(). It greatly over-estimates
                 * the work to be done.
                 */
-               mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u,"
-                    " clusters_to_add = %u, extents_to_split = %u\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                    (long long)i_size_read(inode), le32_to_cpu(di->i_clusters),
-                    clusters_to_alloc, extents_to_split);
-
                ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode),
                                              wc->w_di_bh);
                ret = ocfs2_lock_allocators(inode, &et,
@@ -1938,8 +1934,8 @@ static void ocfs2_write_end_inline(struct inode *inode, loff_t pos,
        memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied);
        kunmap_atomic(kaddr, KM_USER0);
 
-       mlog(0, "Data written to inode at offset %llu. "
-            "id_count = %u, copied = %u, i_dyn_features = 0x%x\n",
+       trace_ocfs2_write_end_inline(
+            (unsigned long long)OCFS2_I(inode)->ip_blkno,
             (unsigned long long)pos, *copied,
             le16_to_cpu(di->id2.i_data.id_count),
             le16_to_cpu(di->i_dyn_features));
index f9d5d3ffc75a9011b0a63a76a97184853ee7f063..5d18ad10c27fc044ae240a5c147c8f3e0b146ae5 100644 (file)
@@ -35,8 +35,8 @@
 #include "inode.h"
 #include "journal.h"
 #include "uptodate.h"
-
 #include "buffer_head_io.h"
+#include "ocfs2_trace.h"
 
 /*
  * Bits on bh->b_state used by ocfs2.
@@ -55,8 +55,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
 {
        int ret = 0;
 
-       mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n",
-                  (unsigned long long)bh->b_blocknr, ci);
+       trace_ocfs2_write_block((unsigned long long)bh->b_blocknr, ci);
 
        BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO);
        BUG_ON(buffer_jbd(bh));
@@ -66,6 +65,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
         * can get modified during recovery even if read-only. */
        if (ocfs2_is_hard_readonly(osb)) {
                ret = -EROFS;
+               mlog_errno(ret);
                goto out;
        }
 
@@ -91,11 +91,11 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
                 * uptodate. */
                ret = -EIO;
                put_bh(bh);
+               mlog_errno(ret);
        }
 
        ocfs2_metadata_cache_io_unlock(ci);
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -106,10 +106,10 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
        unsigned int i;
        struct buffer_head *bh;
 
-       if (!nr) {
-               mlog(ML_BH_IO, "No buffers will be read!\n");
+       trace_ocfs2_read_blocks_sync((unsigned long long)block, nr);
+
+       if (!nr)
                goto bail;
-       }
 
        for (i = 0 ; i < nr ; i++) {
                if (bhs[i] == NULL) {
@@ -123,10 +123,8 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
                bh = bhs[i];
 
                if (buffer_jbd(bh)) {
-                       mlog(ML_BH_IO,
-                            "trying to sync read a jbd "
-                            "managed bh (blocknr = %llu), skipping\n",
-                            (unsigned long long)bh->b_blocknr);
+                       trace_ocfs2_read_blocks_sync_jbd(
+                                       (unsigned long long)bh->b_blocknr);
                        continue;
                }
 
@@ -186,8 +184,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
        struct buffer_head *bh;
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
 
-       mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n",
-                  ci, (unsigned long long)block, nr, flags);
+       trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags);
 
        BUG_ON(!ci);
        BUG_ON((flags & OCFS2_BH_READAHEAD) &&
@@ -207,7 +204,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
        }
 
        if (nr == 0) {
-               mlog(ML_BH_IO, "No buffers will be read!\n");
                status = 0;
                goto bail;
        }
@@ -251,8 +247,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                 */
 
                if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) {
-                       mlog(ML_UPTODATE,
-                            "bh (%llu), owner %llu not uptodate\n",
+                       trace_ocfs2_read_blocks_from_disk(
                             (unsigned long long)bh->b_blocknr,
                             (unsigned long long)ocfs2_metadata_cache_owner(ci));
                        /* We're using ignore_cache here to say
@@ -260,11 +255,10 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                        ignore_cache = 1;
                }
 
+               trace_ocfs2_read_blocks_bh((unsigned long long)bh->b_blocknr,
+                       ignore_cache, buffer_jbd(bh), buffer_dirty(bh));
+
                if (buffer_jbd(bh)) {
-                       if (ignore_cache)
-                               mlog(ML_BH_IO, "trying to sync read a jbd "
-                                              "managed bh (blocknr = %llu)\n",
-                                    (unsigned long long)bh->b_blocknr);
                        continue;
                }
 
@@ -272,9 +266,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                        if (buffer_dirty(bh)) {
                                /* This should probably be a BUG, or
                                 * at least return an error. */
-                               mlog(ML_BH_IO, "asking me to sync read a dirty "
-                                              "buffer! (blocknr = %llu)\n",
-                                    (unsigned long long)bh->b_blocknr);
                                continue;
                        }
 
@@ -367,14 +358,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
        }
        ocfs2_metadata_cache_io_unlock(ci);
 
-       mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n",
-            (unsigned long long)block, nr,
-            ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes",
-            flags);
+       trace_ocfs2_read_blocks_end((unsigned long long)block, nr,
+                                   flags, ignore_cache);
 
 bail:
 
-       mlog_exit(status);
        return status;
 }
 
@@ -408,13 +396,12 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
        int ret = 0;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
 
-       mlog_entry_void();
-
        BUG_ON(buffer_jbd(bh));
        ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr);
 
        if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) {
                ret = -EROFS;
+               mlog_errno(ret);
                goto out;
        }
 
@@ -434,9 +421,9 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
        if (!buffer_uptodate(bh)) {
                ret = -EIO;
                put_bh(bh);
+               mlog_errno(ret);
        }
 
 out:
-       mlog_exit(ret);
        return ret;
 }
index 1adab287bd24c814ceb042be381744b3c3fc3e7c..2461eb3272edfab9c6c4949cb435252181938b72 100644 (file)
@@ -1654,8 +1654,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg)
        struct o2hb_disk_slot *slot;
        struct o2hb_disk_heartbeat_block *hb_block;
 
-       mlog_entry_void();
-
        ret = o2hb_read_slots(reg, reg->hr_blocks);
        if (ret) {
                mlog_errno(ret);
@@ -1677,7 +1675,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg)
        }
 
 out:
-       mlog_exit(ret);
        return ret;
 }
 
index 6c61771469af24ef9e2610e93e65092768b59691..07ac24fd92520f604f6d3cfeff4cd4bd2c6ad85c 100644 (file)
@@ -30,7 +30,7 @@
 
 struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK);
 EXPORT_SYMBOL_GPL(mlog_and_bits);
-struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(MLOG_INITIAL_NOT_MASK);
+struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0);
 EXPORT_SYMBOL_GPL(mlog_not_bits);
 
 static ssize_t mlog_mask_show(u64 mask, char *buf)
@@ -80,8 +80,6 @@ struct mlog_attribute {
 }
 
 static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
-       define_mask(ENTRY),
-       define_mask(EXIT),
        define_mask(TCP),
        define_mask(MSG),
        define_mask(SOCKET),
@@ -93,27 +91,11 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
        define_mask(DLM_THREAD),
        define_mask(DLM_MASTER),
        define_mask(DLM_RECOVERY),
-       define_mask(AIO),
-       define_mask(JOURNAL),
-       define_mask(DISK_ALLOC),
-       define_mask(SUPER),
-       define_mask(FILE_IO),
-       define_mask(EXTENT_MAP),
        define_mask(DLM_GLUE),
-       define_mask(BH_IO),
-       define_mask(UPTODATE),
-       define_mask(NAMEI),
-       define_mask(INODE),
        define_mask(VOTE),
-       define_mask(DCACHE),
        define_mask(CONN),
        define_mask(QUORUM),
-       define_mask(EXPORT),
-       define_mask(XATTR),
-       define_mask(QUOTA),
-       define_mask(REFCOUNT),
        define_mask(BASTS),
-       define_mask(RESERVATIONS),
        define_mask(CLUSTER),
        define_mask(ERROR),
        define_mask(NOTICE),
index 34d6544357d9718699af25e25aecc48a1f26c9c0..baa2b9ef7eef90094dbd3ef8d76f6a6e1df64224 100644 (file)
 
 /* bits that are frequently given and infrequently matched in the low word */
 /* NOTE: If you add a flag, you need to also update masklog.c! */
-#define ML_ENTRY       0x0000000000000001ULL /* func call entry */
-#define ML_EXIT                0x0000000000000002ULL /* func call exit */
-#define ML_TCP         0x0000000000000004ULL /* net cluster/tcp.c */
-#define ML_MSG         0x0000000000000008ULL /* net network messages */
-#define ML_SOCKET      0x0000000000000010ULL /* net socket lifetime */
-#define ML_HEARTBEAT   0x0000000000000020ULL /* hb all heartbeat tracking */
-#define ML_HB_BIO      0x0000000000000040ULL /* hb io tracing */
-#define ML_DLMFS       0x0000000000000080ULL /* dlm user dlmfs */
-#define ML_DLM         0x0000000000000100ULL /* dlm general debugging */
-#define ML_DLM_DOMAIN  0x0000000000000200ULL /* dlm domain debugging */
-#define ML_DLM_THREAD  0x0000000000000400ULL /* dlm domain thread */
-#define ML_DLM_MASTER  0x0000000000000800ULL /* dlm master functions */
-#define ML_DLM_RECOVERY        0x0000000000001000ULL /* dlm master functions */
-#define ML_AIO         0x0000000000002000ULL /* ocfs2 aio read and write */
-#define ML_JOURNAL     0x0000000000004000ULL /* ocfs2 journalling functions */
-#define ML_DISK_ALLOC  0x0000000000008000ULL /* ocfs2 disk allocation */
-#define ML_SUPER       0x0000000000010000ULL /* ocfs2 mount / umount */
-#define ML_FILE_IO     0x0000000000020000ULL /* ocfs2 file I/O */
-#define ML_EXTENT_MAP  0x0000000000040000ULL /* ocfs2 extent map caching */
-#define ML_DLM_GLUE    0x0000000000080000ULL /* ocfs2 dlm glue layer */
-#define ML_BH_IO       0x0000000000100000ULL /* ocfs2 buffer I/O */
-#define ML_UPTODATE    0x0000000000200000ULL /* ocfs2 caching sequence #'s */
-#define ML_NAMEI       0x0000000000400000ULL /* ocfs2 directory / namespace */
-#define ML_INODE       0x0000000000800000ULL /* ocfs2 inode manipulation */
-#define ML_VOTE                0x0000000001000000ULL /* ocfs2 node messaging  */
-#define ML_DCACHE      0x0000000002000000ULL /* ocfs2 dcache operations */
-#define ML_CONN                0x0000000004000000ULL /* net connection management */
-#define ML_QUORUM      0x0000000008000000ULL /* net connection quorum */
-#define ML_EXPORT      0x0000000010000000ULL /* ocfs2 export operations */
-#define ML_XATTR       0x0000000020000000ULL /* ocfs2 extended attributes */
-#define ML_QUOTA       0x0000000040000000ULL /* ocfs2 quota operations */
-#define ML_REFCOUNT    0x0000000080000000ULL /* refcount tree operations */
-#define ML_BASTS       0x0000000100000000ULL /* dlmglue asts and basts */
-#define ML_RESERVATIONS        0x0000000200000000ULL /* ocfs2 alloc reservations */
-#define ML_CLUSTER     0x0000000400000000ULL /* cluster stack */
+#define ML_TCP         0x0000000000000001ULL /* net cluster/tcp.c */
+#define ML_MSG         0x0000000000000002ULL /* net network messages */
+#define ML_SOCKET      0x0000000000000004ULL /* net socket lifetime */
+#define ML_HEARTBEAT   0x0000000000000008ULL /* hb all heartbeat tracking */
+#define ML_HB_BIO      0x0000000000000010ULL /* hb io tracing */
+#define ML_DLMFS       0x0000000000000020ULL /* dlm user dlmfs */
+#define ML_DLM         0x0000000000000040ULL /* dlm general debugging */
+#define ML_DLM_DOMAIN  0x0000000000000080ULL /* dlm domain debugging */
+#define ML_DLM_THREAD  0x0000000000000100ULL /* dlm domain thread */
+#define ML_DLM_MASTER  0x0000000000000200ULL /* dlm master functions */
+#define ML_DLM_RECOVERY        0x0000000000000400ULL /* dlm master functions */
+#define ML_DLM_GLUE    0x0000000000000800ULL /* ocfs2 dlm glue layer */
+#define ML_VOTE                0x0000000000001000ULL /* ocfs2 node messaging  */
+#define ML_CONN                0x0000000000002000ULL /* net connection management */
+#define ML_QUORUM      0x0000000000004000ULL /* net connection quorum */
+#define ML_BASTS       0x0000000000008000ULL /* dlmglue asts and basts */
+#define ML_CLUSTER     0x0000000000010000ULL /* cluster stack */
 
 /* bits that are infrequently given and frequently matched in the high word */
 #define ML_ERROR       0x1000000000000000ULL /* sent to KERN_ERR */
 #define ML_KTHREAD     0x4000000000000000ULL /* kernel thread activity */
 
 #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
-#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
 #ifndef MLOG_MASK_PREFIX
 #define MLOG_MASK_PREFIX 0
 #endif
@@ -222,58 +203,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
                mlog(ML_ERROR, "status = %lld\n", (long long)_st);      \
 } while (0)
 
-#if defined(CONFIG_OCFS2_DEBUG_MASKLOG)
-#define mlog_entry(fmt, args...) do {                                  \
-       mlog(ML_ENTRY, "ENTRY:" fmt , ##args);                          \
-} while (0)
-
-#define mlog_entry_void() do {                                         \
-       mlog(ML_ENTRY, "ENTRY:\n");                                     \
-} while (0)
-
-/*
- * We disable this for sparse.
- */
-#if !defined(__CHECKER__)
-#define mlog_exit(st) do {                                                  \
-       if (__builtin_types_compatible_p(typeof(st), unsigned long))         \
-               mlog(ML_EXIT, "EXIT: %lu\n", (unsigned long) (st));          \
-       else if (__builtin_types_compatible_p(typeof(st), signed long))      \
-               mlog(ML_EXIT, "EXIT: %ld\n", (signed long) (st));            \
-       else if (__builtin_types_compatible_p(typeof(st), unsigned int)      \
-                || __builtin_types_compatible_p(typeof(st), unsigned short) \
-                || __builtin_types_compatible_p(typeof(st), unsigned char)) \
-               mlog(ML_EXIT, "EXIT: %u\n", (unsigned int) (st));            \
-       else if (__builtin_types_compatible_p(typeof(st), signed int)        \
-                || __builtin_types_compatible_p(typeof(st), signed short)   \
-                || __builtin_types_compatible_p(typeof(st), signed char))   \
-               mlog(ML_EXIT, "EXIT: %d\n", (signed int) (st));              \
-       else if (__builtin_types_compatible_p(typeof(st), long long))        \
-               mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st));             \
-       else                                                                 \
-               mlog(ML_EXIT, "EXIT: %llu\n", (unsigned long long) (st));    \
-} while (0)
-#else
-#define mlog_exit(st) do {                                                  \
-       mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st));                     \
-} while (0)
-#endif
-
-#define mlog_exit_ptr(ptr) do {                                                \
-       mlog(ML_EXIT, "EXIT: %p\n", ptr);                               \
-} while (0)
-
-#define mlog_exit_void() do {                                          \
-       mlog(ML_EXIT, "EXIT\n");                                        \
-} while (0)
-#else
-#define mlog_entry(...)  do { } while (0)
-#define mlog_entry_void(...)  do { } while (0)
-#define mlog_exit(...)  do { } while (0)
-#define mlog_exit_ptr(...)  do { } while (0)
-#define mlog_exit_void(...)  do { } while (0)
-#endif  /* defined(CONFIG_OCFS2_DEBUG_MASKLOG) */
-
 #define mlog_bug_on_msg(cond, fmt, args...) do {                       \
        if (cond) {                                                     \
                mlog(ML_ERROR, "bug expression: " #cond "\n");          \
index 3b11cb1e38fce990a5e2042fd75ebd0f7a3fbbaf..ee04ff5ee60334106fca7ce4c94bd23f86b05f31 100644 (file)
@@ -210,10 +210,6 @@ static inline void o2net_set_func_stop_time(struct o2net_sock_container *sc)
        sc->sc_tv_func_stop = ktime_get();
 }
 
-static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc)
-{
-       return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start);
-}
 #else  /* CONFIG_DEBUG_FS */
 # define o2net_init_nst(a, b, c, d, e)
 # define o2net_set_nst_sock_time(a)
@@ -227,10 +223,14 @@ static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc)
 # define o2net_set_advance_stop_time(a)
 # define o2net_set_func_start_time(a)
 # define o2net_set_func_stop_time(a)
-# define o2net_get_func_run_time(a)            (ktime_t)0
 #endif /* CONFIG_DEBUG_FS */
 
 #ifdef CONFIG_OCFS2_FS_STATS
+static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc)
+{
+       return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start);
+}
+
 static void o2net_update_send_stats(struct o2net_send_tracking *nst,
                                    struct o2net_sock_container *sc)
 {
index 7eb90403fc8af0521b7d3df89d37956ccad054a4..e5ba348183321d133ab7f75c715b305dbed28a07 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <linux/namei.h>
 
-#define MLOG_MASK_PREFIX ML_DCACHE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -39,6 +38,7 @@
 #include "file.h"
 #include "inode.h"
 #include "super.h"
+#include "ocfs2_trace.h"
 
 void ocfs2_dentry_attach_gen(struct dentry *dentry)
 {
@@ -62,8 +62,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
        inode = dentry->d_inode;
        osb = OCFS2_SB(dentry->d_sb);
 
-       mlog_entry("(0x%p, '%.*s')\n", dentry,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len,
+                                     dentry->d_name.name);
 
        /* For a negative dentry -
         * check the generation number of the parent and compare with the
@@ -73,9 +73,10 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
                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);
+
+               trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
+                                                      dentry->d_name.name,
+                                                      pgen, gen);
                if (gen != pgen)
                        goto bail;
                goto valid;
@@ -90,8 +91,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
        /* did we or someone else delete this inode? */
        if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
                spin_unlock(&OCFS2_I(inode)->ip_lock);
-               mlog(0, "inode (%llu) deleted, returning false\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+               trace_ocfs2_dentry_revalidate_delete(
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
                goto bail;
        }
        spin_unlock(&OCFS2_I(inode)->ip_lock);
@@ -101,10 +102,9 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
         * inode nlink hits zero, it never goes back.
         */
        if (inode->i_nlink == 0) {
-               mlog(0, "Inode %llu orphaned, returning false "
-                    "dir = %d\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                    S_ISDIR(inode->i_mode));
+               trace_ocfs2_dentry_revalidate_orphaned(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       S_ISDIR(inode->i_mode));
                goto bail;
        }
 
@@ -113,9 +113,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
         * redo it.
         */
        if (!dentry->d_fsdata) {
-               mlog(0, "Inode %llu doesn't have dentry lock, "
-                    "returning false\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+               trace_ocfs2_dentry_revalidate_nofsdata(
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
                goto bail;
        }
 
@@ -123,8 +122,7 @@ valid:
        ret = 1;
 
 bail:
-       mlog_exit(ret);
-
+       trace_ocfs2_dentry_revalidate_ret(ret);
        return ret;
 }
 
@@ -181,8 +179,8 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
 
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
-                       mlog(0, "dentry found: %.*s\n",
-                            dentry->d_name.len, dentry->d_name.name);
+                       trace_ocfs2_find_local_alias(dentry->d_name.len,
+                                                    dentry->d_name.name);
 
                        dget_dlock(dentry);
                        spin_unlock(&dentry->d_lock);
@@ -240,9 +238,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
        struct dentry *alias;
        struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
 
-       mlog(0, "Attach \"%.*s\", parent %llu, fsdata: %p\n",
-            dentry->d_name.len, dentry->d_name.name,
-            (unsigned long long)parent_blkno, dl);
+       trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name,
+                                      (unsigned long long)parent_blkno, dl);
 
        /*
         * Negative dentry. We ignore these for now.
@@ -292,7 +289,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
                                (unsigned long long)parent_blkno,
                                (unsigned long long)dl->dl_parent_blkno);
 
-               mlog(0, "Found: %s\n", dl->dl_lockres.l_name);
+               trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name,
+                               (unsigned long long)parent_blkno,
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
                goto out_attach;
        }
index f97b6f1c61dd47392d0052acb64d218b1d9cdd76..9fe5b8fd658f0a3db09f1919512a0479a241ecca 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/quotaops.h>
 #include <linux/sort.h>
 
-#define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -61,6 +60,7 @@
 #include "super.h"
 #include "sysfile.h"
 #include "uptodate.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -322,21 +322,23 @@ static int ocfs2_check_dir_entry(struct inode * dir,
        const char *error_msg = NULL;
        const int rlen = le16_to_cpu(de->rec_len);
 
-       if (rlen < OCFS2_DIR_REC_LEN(1))
+       if (unlikely(rlen < OCFS2_DIR_REC_LEN(1)))
                error_msg = "rec_len is smaller than minimal";
-       else if (rlen % 4 != 0)
+       else if (unlikely(rlen % 4 != 0))
                error_msg = "rec_len % 4 != 0";
-       else if (rlen < OCFS2_DIR_REC_LEN(de->name_len))
+       else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len)))
                error_msg = "rec_len is too small for name_len";
-       else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+       else if (unlikely(
+                ((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize))
                error_msg = "directory entry across blocks";
 
-       if (error_msg != NULL)
+       if (unlikely(error_msg != NULL))
                mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
                     "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
                     (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
                     offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
                     de->name_len);
+
        return error_msg == NULL ? 1 : 0;
 }
 
@@ -367,8 +369,6 @@ static inline int ocfs2_search_dirblock(struct buffer_head *bh,
        int de_len;
        int ret = 0;
 
-       mlog_entry_void();
-
        de_buf = first_de;
        dlimit = de_buf + bytes;
 
@@ -402,7 +402,7 @@ static inline int ocfs2_search_dirblock(struct buffer_head *bh,
        }
 
 bail:
-       mlog_exit(ret);
+       trace_ocfs2_search_dirblock(ret);
        return ret;
 }
 
@@ -447,8 +447,7 @@ static int ocfs2_validate_dir_block(struct super_block *sb,
         * We don't validate dirents here, that's handled
         * in-place when the code walks them.
         */
-       mlog(0, "Validating dirblock %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_dir_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -706,8 +705,6 @@ static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
        int num = 0;
        int nblocks, i, err;
 
-       mlog_entry_void();
-
        sb = dir->i_sb;
 
        nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
@@ -788,7 +785,7 @@ cleanup_and_exit:
        for (; ra_ptr < ra_max; ra_ptr++)
                brelse(bh_use[ra_ptr]);
 
-       mlog_exit_ptr(ret);
+       trace_ocfs2_find_entry_el(ret);
        return ret;
 }
 
@@ -950,11 +947,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen,
                goto out;
        }
 
-       mlog(0, "Dir %llu: name: \"%.*s\", lookup of hash: %u.0x%x "
-            "returns: %llu\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno,
-            namelen, name, hinfo->major_hash, hinfo->minor_hash,
-            (unsigned long long)phys);
+       trace_ocfs2_dx_dir_search((unsigned long long)OCFS2_I(dir)->ip_blkno,
+                                 namelen, name, hinfo->major_hash,
+                                 hinfo->minor_hash, (unsigned long long)phys);
 
        ret = ocfs2_read_dx_leaf(dir, phys, &dx_leaf_bh);
        if (ret) {
@@ -964,9 +959,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen,
 
        dx_leaf = (struct ocfs2_dx_leaf *) dx_leaf_bh->b_data;
 
-       mlog(0, "leaf info: num_used: %d, count: %d\n",
-            le16_to_cpu(dx_leaf->dl_list.de_num_used),
-            le16_to_cpu(dx_leaf->dl_list.de_count));
+       trace_ocfs2_dx_dir_search_leaf_info(
+                       le16_to_cpu(dx_leaf->dl_list.de_num_used),
+                       le16_to_cpu(dx_leaf->dl_list.de_count));
 
        entry_list = &dx_leaf->dl_list;
 
@@ -1166,8 +1161,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
        int i, status = -ENOENT;
        ocfs2_journal_access_func access = ocfs2_journal_access_db;
 
-       mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
-
        if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                access = ocfs2_journal_access_di;
 
@@ -1202,7 +1195,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
                de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
        }
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -1348,8 +1340,8 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
                }
        }
 
-       mlog(0, "Dir %llu: delete entry at index: %d\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno, index);
+       trace_ocfs2_delete_entry_dx((unsigned long long)OCFS2_I(dir)->ip_blkno,
+                                   index);
 
        ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry,
                                   leaf_bh, leaf_bh->b_data, leaf_bh->b_size);
@@ -1632,8 +1624,6 @@ int __ocfs2_add_entry(handle_t *handle,
        struct buffer_head *insert_bh = lookup->dl_leaf_bh;
        char *data_start = insert_bh->b_data;
 
-       mlog_entry_void();
-
        if (!namelen)
                return -EINVAL;
 
@@ -1765,8 +1755,9 @@ int __ocfs2_add_entry(handle_t *handle,
         * from ever getting here. */
        retval = -ENOSPC;
 bail:
+       if (retval)
+               mlog_errno(retval);
 
-       mlog_exit(retval);
        return retval;
 }
 
@@ -2028,8 +2019,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
        struct inode *inode = filp->f_path.dentry->d_inode;
        int lock_level = 0;
 
-       mlog_entry("dirino=%llu\n",
-                  (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        error = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level);
        if (lock_level && error >= 0) {
@@ -2051,9 +2041,10 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                      dirent, filldir, NULL);
 
        ocfs2_inode_unlock(inode, lock_level);
+       if (error)
+               mlog_errno(error);
 
 bail_nolock:
-       mlog_exit(error);
 
        return error;
 }
@@ -2069,8 +2060,8 @@ int ocfs2_find_files_on_disk(const char *name,
 {
        int status = -ENOENT;
 
-       mlog(0, "name=%.*s, blkno=%p, inode=%llu\n", namelen, name, blkno,
-            (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       trace_ocfs2_find_files_on_disk(namelen, name, blkno,
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        status = ocfs2_find_entry(name, namelen, inode, lookup);
        if (status)
@@ -2114,8 +2105,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
        int ret;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 
-       mlog_entry("dir %llu, name '%.*s'\n",
-                  (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
+       trace_ocfs2_check_dir_for_entry(
+               (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
 
        ret = -EEXIST;
        if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0)
@@ -2125,7 +2116,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
 bail:
        ocfs2_free_dir_lookup_result(&lookup);
 
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
        return ret;
 }
 
@@ -2324,8 +2316,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
        struct buffer_head *new_bh = NULL;
        struct ocfs2_dir_entry *de;
 
-       mlog_entry_void();
-
        if (ocfs2_new_dir_wants_trailer(inode))
                size = ocfs2_dir_trailer_blk_off(parent->i_sb);
 
@@ -2380,7 +2370,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
 bail:
        brelse(new_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -2409,9 +2398,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
                goto out;
        }
 
-       mlog(0, "Dir %llu, attach new index block: %llu\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno,
-            (unsigned long long)dr_blkno);
+       trace_ocfs2_dx_dir_attach_index(
+                               (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                               (unsigned long long)dr_blkno);
 
        dx_root_bh = sb_getblk(osb->sb, dr_blkno);
        if (dx_root_bh == NULL) {
@@ -2511,11 +2500,10 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
                dx_leaf->dl_list.de_count =
                        cpu_to_le16(ocfs2_dx_entries_per_leaf(osb->sb));
 
-               mlog(0,
-                    "Dir %llu, format dx_leaf: %llu, entry count: %u\n",
-                    (unsigned long long)OCFS2_I(dir)->ip_blkno,
-                    (unsigned long long)bh->b_blocknr,
-                    le16_to_cpu(dx_leaf->dl_list.de_count));
+               trace_ocfs2_dx_dir_format_cluster(
+                               (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                               (unsigned long long)bh->b_blocknr,
+                               le16_to_cpu(dx_leaf->dl_list.de_count));
 
                ocfs2_journal_dirty(handle, bh);
        }
@@ -2759,12 +2747,11 @@ static void ocfs2_dx_dir_index_root_block(struct inode *dir,
 
                ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo);
 
-               mlog(0,
-                    "dir: %llu, major: 0x%x minor: 0x%x, index: %u, name: %.*s\n",
-                    (unsigned long long)dir->i_ino, hinfo.major_hash,
-                    hinfo.minor_hash,
-                    le16_to_cpu(dx_root->dr_entries.de_num_used),
-                    de->name_len, de->name);
+               trace_ocfs2_dx_dir_index_root_block(
+                               (unsigned long long)dir->i_ino,
+                               hinfo.major_hash, hinfo.minor_hash,
+                               de->name_len, de->name,
+                               le16_to_cpu(dx_root->dr_entries.de_num_used));
 
                ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo,
                                           dirent_blk);
@@ -3235,7 +3222,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
 bail:
        if (did_quota && status < 0)
                dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
-       mlog_exit(status);
        return status;
 }
 
@@ -3270,8 +3256,6 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        struct ocfs2_extent_tree et;
        struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
 
-       mlog_entry_void();
-
        if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
                /*
                 * This would be a code error as an inline directory should
@@ -3320,8 +3304,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        down_write(&OCFS2_I(dir)->ip_alloc_sem);
        drop_alloc_sem = 1;
        dir_i_size = i_size_read(dir);
-       mlog(0, "extending dir %llu (i_size = %lld)\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size);
+       trace_ocfs2_extend_dir((unsigned long long)OCFS2_I(dir)->ip_blkno,
+                              dir_i_size);
 
        /* dir->i_size is always block aligned. */
        spin_lock(&OCFS2_I(dir)->ip_lock);
@@ -3436,7 +3420,6 @@ bail:
 
        brelse(new_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -3583,8 +3566,9 @@ next:
        status = 0;
 bail:
        brelse(bh);
+       if (status)
+               mlog_errno(status);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -3815,9 +3799,9 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
        struct ocfs2_dx_root_block *dx_root;
        struct ocfs2_dx_leaf *tmp_dx_leaf = NULL;
 
-       mlog(0, "DX Dir: %llu, rebalance leaf leaf_blkno: %llu insert: %u\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno,
-            (unsigned long long)leaf_blkno, insert_hash);
+       trace_ocfs2_dx_dir_rebalance((unsigned long long)OCFS2_I(dir)->ip_blkno,
+                                    (unsigned long long)leaf_blkno,
+                                    insert_hash);
 
        ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
 
@@ -3897,8 +3881,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
                goto  out_commit;
        }
 
-       mlog(0, "Split leaf (%u) at %u, insert major hash is %u\n",
-            leaf_cpos, split_hash, insert_hash);
+       trace_ocfs2_dx_dir_rebalance_split(leaf_cpos, split_hash, insert_hash);
 
        /*
         * We have to carefully order operations here. There are items
@@ -4355,8 +4338,8 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
        unsigned int blocks_wanted = 1;
        struct buffer_head *bh = NULL;
 
-       mlog(0, "getting ready to insert namelen %d into dir %llu\n",
-            namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno);
+       trace_ocfs2_prepare_dir_for_insert(
+               (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen);
 
        if (!namelen) {
                ret = -EINVAL;
index 9f30491e5e88a36ff3ec9a07f0869e7d9d88592d..29a886d1e82c84dd7338380b0ed65a0becd1e3bb 100644 (file)
@@ -128,8 +128,8 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm,
 
        assert_spin_locked(&res->spinlock);
 
-       mlog_entry("type=%d, convert_type=%d, new convert_type=%d\n",
-                  lock->ml.type, lock->ml.convert_type, type);
+       mlog(0, "type=%d, convert_type=%d, new convert_type=%d\n",
+            lock->ml.type, lock->ml.convert_type, type);
 
        spin_lock(&lock->spinlock);
 
@@ -353,7 +353,7 @@ static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm,
        struct kvec vec[2];
        size_t veclen = 1;
 
-       mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+       mlog(0, "%.*s\n", res->lockname.len, res->lockname.name);
 
        memset(&convert, 0, sizeof(struct dlm_convert_lock));
        convert.node_idx = dlm->node_num;
index 7e38a072d720275ecd6b89a5f5113d9bde11c308..7540a492eaba0188d624a08f73688eee04838288 100644 (file)
@@ -188,7 +188,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
        struct hlist_head *bucket;
        struct hlist_node *list;
 
-       mlog_entry("%.*s\n", len, name);
+       mlog(0, "%.*s\n", len, name);
 
        assert_spin_locked(&dlm->spinlock);
 
@@ -222,7 +222,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
 {
        struct dlm_lock_resource *res = NULL;
 
-       mlog_entry("%.*s\n", len, name);
+       mlog(0, "%.*s\n", len, name);
 
        assert_spin_locked(&dlm->spinlock);
 
@@ -531,7 +531,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
        unsigned int node;
        struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf;
 
-       mlog_entry("%p %u %p", msg, len, data);
+       mlog(0, "%p %u %p", msg, len, data);
 
        if (!dlm_grab(dlm))
                return 0;
@@ -926,9 +926,10 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
 }
 
 static int dlm_match_regions(struct dlm_ctxt *dlm,
-                            struct dlm_query_region *qr)
+                            struct dlm_query_region *qr,
+                            char *local, int locallen)
 {
-       char *local = NULL, *remote = qr->qr_regions;
+       char *remote = qr->qr_regions;
        char *l, *r;
        int localnr, i, j, foundit;
        int status = 0;
@@ -957,13 +958,8 @@ static int dlm_match_regions(struct dlm_ctxt *dlm,
                r += O2HB_MAX_REGION_NAME_LEN;
        }
 
-       local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC);
-       if (!local) {
-               status = -ENOMEM;
-               goto bail;
-       }
-
-       localnr = o2hb_get_all_regions(local, O2NM_MAX_REGIONS);
+       localnr = min(O2NM_MAX_REGIONS, locallen/O2HB_MAX_REGION_NAME_LEN);
+       localnr = o2hb_get_all_regions(local, (u8)localnr);
 
        /* compare local regions with remote */
        l = local;
@@ -1012,8 +1008,6 @@ static int dlm_match_regions(struct dlm_ctxt *dlm,
        }
 
 bail:
-       kfree(local);
-
        return status;
 }
 
@@ -1075,6 +1069,7 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
 {
        struct dlm_query_region *qr;
        struct dlm_ctxt *dlm = NULL;
+       char *local = NULL;
        int status = 0;
        int locked = 0;
 
@@ -1083,6 +1078,13 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
        mlog(0, "Node %u queries hb regions on domain %s\n", qr->qr_node,
             qr->qr_domain);
 
+       /* buffer used in dlm_mast_regions() */
+       local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL);
+       if (!local) {
+               status = -ENOMEM;
+               goto bail;
+       }
+
        status = -EINVAL;
 
        spin_lock(&dlm_domain_lock);
@@ -1112,13 +1114,15 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
                goto bail;
        }
 
-       status = dlm_match_regions(dlm, qr);
+       status = dlm_match_regions(dlm, qr, local, sizeof(qr->qr_regions));
 
 bail:
        if (locked)
                spin_unlock(&dlm->spinlock);
        spin_unlock(&dlm_domain_lock);
 
+       kfree(local);
+
        return status;
 }
 
@@ -1553,7 +1557,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
        struct domain_join_ctxt *ctxt;
        enum dlm_query_join_response_code response = JOIN_DISALLOW;
 
-       mlog_entry("%p", dlm);
+       mlog(0, "%p", dlm);
 
        ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
        if (!ctxt) {
index 7009292aac5ad4dd2ddd6f0511af0820e64c4b22..8d39e0fd66f7379b8fb08ac40502efa0d4a51cc6 100644 (file)
@@ -128,7 +128,7 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
        int call_ast = 0, kick_thread = 0;
        enum dlm_status status = DLM_NORMAL;
 
-       mlog_entry("type=%d\n", lock->ml.type);
+       mlog(0, "type=%d\n", lock->ml.type);
 
        spin_lock(&res->spinlock);
        /* if called from dlm_create_lock_handler, need to
@@ -227,8 +227,8 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
        enum dlm_status status = DLM_DENIED;
        int lockres_changed = 1;
 
-       mlog_entry("type=%d\n", lock->ml.type);
-       mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len,
+       mlog(0, "type=%d, lockres %.*s, flags = 0x%x\n",
+            lock->ml.type, res->lockname.len,
             res->lockname.name, flags);
 
        spin_lock(&res->spinlock);
@@ -308,8 +308,6 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
        int tmpret, status = 0;
        enum dlm_status ret;
 
-       mlog_entry_void();
-
        memset(&create, 0, sizeof(create));
        create.node_idx = dlm->node_num;
        create.requested_type = lock->ml.type;
@@ -477,8 +475,6 @@ int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 
        BUG_ON(!dlm);
 
-       mlog_entry_void();
-
        if (!dlm_grab(dlm))
                return DLM_REJECTED;
 
index 59f0f6bdfc62110141ca7ad413dc51abadd4b3c8..9d67610dfc74fc77854e668fef72baa72034d684 100644 (file)
@@ -426,8 +426,6 @@ static void dlm_mle_release(struct kref *kref)
        struct dlm_master_list_entry *mle;
        struct dlm_ctxt *dlm;
 
-       mlog_entry_void();
-
        mle = container_of(kref, struct dlm_master_list_entry, mle_refs);
        dlm = mle->dlm;
 
@@ -3120,8 +3118,6 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm,
 
        *oldmle = NULL;
 
-       mlog_entry_void();
-
        assert_spin_locked(&dlm->spinlock);
        assert_spin_locked(&dlm->master_lock);
 
@@ -3261,7 +3257,7 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
        struct hlist_node *list;
        unsigned int i;
 
-       mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node);
+       mlog(0, "dlm=%s, dead node=%u\n", dlm->name, dead_node);
 top:
        assert_spin_locked(&dlm->spinlock);
 
index aaaffbcbe9163f0ea7376301bc854d85a0bd5b66..f1beb6fc254d1720ae10b10a0a7ea904703c7d0d 100644 (file)
@@ -727,7 +727,6 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
        if (destroy)
                dlm_destroy_recovery_area(dlm, dead_node);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1496,9 +1495,9 @@ leave:
                        kfree(buf);
                if (item)
                        kfree(item);
+               mlog_errno(ret);
        }
 
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1567,7 +1566,6 @@ leave:
                dlm_lockres_put(res);
        }
        kfree(data);
-       mlog_exit(ret);
 }
 
 
@@ -1986,7 +1984,6 @@ leave:
                        dlm_lock_put(newlock);
        }
 
-       mlog_exit(ret);
        return ret;
 }
 
@@ -2083,8 +2080,6 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
        struct hlist_head *bucket;
        struct dlm_lock_resource *res, *next;
 
-       mlog_entry_void();
-
        assert_spin_locked(&dlm->spinlock);
 
        list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
@@ -2607,8 +2602,6 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node)
        int nodenum;
        int status;
 
-       mlog_entry("%u\n", dead_node);
-
        mlog(0, "%s: dead node is %u\n", dlm->name, dead_node);
 
        spin_lock(&dlm->spinlock);
index 817287c6a6db65fe412062ecfaba3c379312791d..850aa7e875377b76eaae054b675367aea157c13c 100644 (file)
@@ -317,7 +317,7 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm,
        struct kvec vec[2];
        size_t veclen = 1;
 
-       mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+       mlog(0, "%.*s\n", res->lockname.len, res->lockname.name);
 
        if (owner == dlm->node_num) {
                /* ended up trying to contact ourself.  this means
@@ -588,8 +588,6 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb,
        struct dlm_lock *lock = NULL;
        int call_ast, is_master;
 
-       mlog_entry_void();
-
        if (!lksb) {
                dlm_error(DLM_BADARGS);
                return DLM_BADARGS;
index e8d94d722ecb8b6dc7aad1ceaa749c99d51cf8a6..7642d7ca73e523f3bc29b7b8a5d767e8f7c7cb83 100644 (file)
@@ -64,7 +64,7 @@ struct ocfs2_mask_waiter {
        unsigned long           mw_mask;
        unsigned long           mw_goal;
 #ifdef CONFIG_OCFS2_FS_STATS
-       unsigned long long      mw_lock_start;
+       ktime_t                 mw_lock_start;
 #endif
 };
 
@@ -397,8 +397,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
 {
        int len;
 
-       mlog_entry_void();
-
        BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
 
        len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x",
@@ -408,8 +406,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
        BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1));
 
        mlog(0, "built lock resource with name: %s\n", name);
-
-       mlog_exit_void();
 }
 
 static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock);
@@ -435,44 +431,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
 #ifdef CONFIG_OCFS2_FS_STATS
 static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
 {
-       res->l_lock_num_prmode = 0;
-       res->l_lock_num_prmode_failed = 0;
-       res->l_lock_total_prmode = 0;
-       res->l_lock_max_prmode = 0;
-       res->l_lock_num_exmode = 0;
-       res->l_lock_num_exmode_failed = 0;
-       res->l_lock_total_exmode = 0;
-       res->l_lock_max_exmode = 0;
        res->l_lock_refresh = 0;
+       memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats));
+       memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats));
 }
 
 static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level,
                                    struct ocfs2_mask_waiter *mw, int ret)
 {
-       unsigned long long *num, *sum;
-       unsigned int *max, *failed;
-       struct timespec ts = current_kernel_time();
-       unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start;
-
-       if (level == LKM_PRMODE) {
-               num = &res->l_lock_num_prmode;
-               sum = &res->l_lock_total_prmode;
-               max = &res->l_lock_max_prmode;
-               failed = &res->l_lock_num_prmode_failed;
-       } else if (level == LKM_EXMODE) {
-               num = &res->l_lock_num_exmode;
-               sum = &res->l_lock_total_exmode;
-               max = &res->l_lock_max_exmode;
-               failed = &res->l_lock_num_exmode_failed;
-       } else
+       u32 usec;
+       ktime_t kt;
+       struct ocfs2_lock_stats *stats;
+
+       if (level == LKM_PRMODE)
+               stats = &res->l_lock_prmode;
+       else if (level == LKM_EXMODE)
+               stats = &res->l_lock_exmode;
+       else
                return;
 
-       (*num)++;
-       (*sum) += time;
-       if (time > *max)
-               *max = time;
+       kt = ktime_sub(ktime_get(), mw->mw_lock_start);
+       usec = ktime_to_us(kt);
+
+       stats->ls_gets++;
+       stats->ls_total += ktime_to_ns(kt);
+       /* overflow */
+       if (unlikely(stats->ls_gets) == 0) {
+               stats->ls_gets++;
+               stats->ls_total = ktime_to_ns(kt);
+       }
+
+       if (stats->ls_max < usec)
+               stats->ls_max = usec;
+
        if (ret)
-               (*failed)++;
+               stats->ls_fail++;
 }
 
 static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
@@ -482,8 +475,7 @@ static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
 
 static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
 {
-       struct timespec ts = current_kernel_time();
-       mw->mw_lock_start = timespec_to_ns(&ts);
+       mw->mw_lock_start = ktime_get();
 }
 #else
 static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
@@ -729,8 +721,6 @@ void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
 
 void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
 {
-       mlog_entry_void();
-
        if (!(res->l_flags & OCFS2_LOCK_INITIALIZED))
                return;
 
@@ -756,14 +746,11 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
        memset(&res->l_lksb, 0, sizeof(res->l_lksb));
 
        res->l_flags = 0UL;
-       mlog_exit_void();
 }
 
 static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
                                     int level)
 {
-       mlog_entry_void();
-
        BUG_ON(!lockres);
 
        switch(level) {
@@ -776,15 +763,11 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
        default:
                BUG();
        }
-
-       mlog_exit_void();
 }
 
 static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
                                     int level)
 {
-       mlog_entry_void();
-
        BUG_ON(!lockres);
 
        switch(level) {
@@ -799,7 +782,6 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
        default:
                BUG();
        }
-       mlog_exit_void();
 }
 
 /* WARNING: This function lives in a world where the only three lock
@@ -846,8 +828,6 @@ static void lockres_clear_flags(struct ocfs2_lock_res *lockres,
 
 static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres)
 {
-       mlog_entry_void();
-
        BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
        BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
        BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
@@ -860,14 +840,10 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res
                lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
        }
        lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
-
-       mlog_exit_void();
 }
 
 static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres)
 {
-       mlog_entry_void();
-
        BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
        BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
 
@@ -889,14 +865,10 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo
        lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
 
        lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
-
-       mlog_exit_void();
 }
 
 static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres)
 {
-       mlog_entry_void();
-
        BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
        BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
 
@@ -908,15 +880,12 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc
        lockres->l_level = lockres->l_requested;
        lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED);
        lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
-
-       mlog_exit_void();
 }
 
 static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
                                     int level)
 {
        int needs_downconvert = 0;
-       mlog_entry_void();
 
        assert_spin_locked(&lockres->l_lock);
 
@@ -938,8 +907,7 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
 
        if (needs_downconvert)
                lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
-
-       mlog_exit(needs_downconvert);
+       mlog(0, "needs_downconvert = %d\n", needs_downconvert);
        return needs_downconvert;
 }
 
@@ -1151,8 +1119,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error)
        struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
        unsigned long flags;
 
-       mlog_entry_void();
-
        mlog(ML_BASTS, "UNLOCK AST fired for lockres %s, action = %d\n",
             lockres->l_name, lockres->l_unlock_action);
 
@@ -1162,7 +1128,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error)
                     "unlock_action %d\n", error, lockres->l_name,
                     lockres->l_unlock_action);
                spin_unlock_irqrestore(&lockres->l_lock, flags);
-               mlog_exit_void();
                return;
        }
 
@@ -1186,8 +1151,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error)
        lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
        wake_up(&lockres->l_event);
        spin_unlock_irqrestore(&lockres->l_lock, flags);
-
-       mlog_exit_void();
 }
 
 /*
@@ -1233,7 +1196,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
 {
        unsigned long flags;
 
-       mlog_entry_void();
        spin_lock_irqsave(&lockres->l_lock, flags);
        lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
        lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
@@ -1244,7 +1206,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
        spin_unlock_irqrestore(&lockres->l_lock, flags);
 
        wake_up(&lockres->l_event);
-       mlog_exit_void();
 }
 
 /* Note: If we detect another process working on the lock (i.e.,
@@ -1260,8 +1221,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
        unsigned long flags;
        unsigned int gen;
 
-       mlog_entry_void();
-
        mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level,
             dlm_flags);
 
@@ -1293,7 +1252,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
        mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name);
 
 bail:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1416,8 +1374,6 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
        unsigned int gen;
        int noqueue_attempted = 0;
 
-       mlog_entry_void();
-
        ocfs2_init_mask_waiter(&mw);
 
        if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
@@ -1583,7 +1539,6 @@ out:
                                caller_ip);
        }
 #endif
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1605,7 +1560,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
 {
        unsigned long flags;
 
-       mlog_entry_void();
        spin_lock_irqsave(&lockres->l_lock, flags);
        ocfs2_dec_holders(lockres, level);
        ocfs2_downconvert_on_unlock(osb, lockres);
@@ -1614,7 +1568,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
        if (lockres->l_lockdep_map.key != NULL)
                rwsem_release(&lockres->l_lockdep_map, 1, caller_ip);
 #endif
-       mlog_exit_void();
 }
 
 static int ocfs2_create_new_lock(struct ocfs2_super *osb,
@@ -1648,8 +1601,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
        BUG_ON(!inode);
        BUG_ON(!ocfs2_inode_is_new(inode));
 
-       mlog_entry_void();
-
        mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        /* NOTE: That we don't increment any of the holder counts, nor
@@ -1683,7 +1634,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
        }
 
 bail:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1695,16 +1645,12 @@ int ocfs2_rw_lock(struct inode *inode, int write)
 
        BUG_ON(!inode);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu take %s RW lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
-       if (ocfs2_mount_local(osb)) {
-               mlog_exit(0);
+       if (ocfs2_mount_local(osb))
                return 0;
-       }
 
        lockres = &OCFS2_I(inode)->ip_rw_lockres;
 
@@ -1715,7 +1661,6 @@ int ocfs2_rw_lock(struct inode *inode, int write)
        if (status < 0)
                mlog_errno(status);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1725,16 +1670,12 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu drop %s RW lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
        if (!ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
-
-       mlog_exit_void();
 }
 
 /*
@@ -1748,8 +1689,6 @@ int ocfs2_open_lock(struct inode *inode)
 
        BUG_ON(!inode);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu take PRMODE open lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
@@ -1764,7 +1703,6 @@ int ocfs2_open_lock(struct inode *inode)
                mlog_errno(status);
 
 out:
-       mlog_exit(status);
        return status;
 }
 
@@ -1776,8 +1714,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
 
        BUG_ON(!inode);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu try to take %s open lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
@@ -1799,7 +1735,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
                                    level, DLM_LKF_NOQUEUE, 0);
 
 out:
-       mlog_exit(status);
        return status;
 }
 
@@ -1811,8 +1746,6 @@ void ocfs2_open_unlock(struct inode *inode)
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu drop open lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
@@ -1827,7 +1760,7 @@ void ocfs2_open_unlock(struct inode *inode)
                                     DLM_LOCK_EX);
 
 out:
-       mlog_exit_void();
+       return;
 }
 
 static int ocfs2_flock_handle_signal(struct ocfs2_lock_res *lockres,
@@ -2043,8 +1976,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
 {
        int kick = 0;
 
-       mlog_entry_void();
-
        /* If we know that another node is waiting on our lock, kick
         * the downconvert thread * pre-emptively when we reach a release
         * condition. */
@@ -2065,8 +1996,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
 
        if (kick)
                ocfs2_wake_downconvert_thread(osb);
-
-       mlog_exit_void();
 }
 
 #define OCFS2_SEC_BITS   34
@@ -2095,8 +2024,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
        struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
        struct ocfs2_meta_lvb *lvb;
 
-       mlog_entry_void();
-
        lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
 
        /*
@@ -2128,8 +2055,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
 
 out:
        mlog_meta_lvb(0, lockres);
-
-       mlog_exit_void();
 }
 
 static void ocfs2_unpack_timespec(struct timespec *spec,
@@ -2145,8 +2070,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
        struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
        struct ocfs2_meta_lvb *lvb;
 
-       mlog_entry_void();
-
        mlog_meta_lvb(0, lockres);
 
        lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
@@ -2177,8 +2100,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
        ocfs2_unpack_timespec(&inode->i_ctime,
                              be64_to_cpu(lvb->lvb_ictime_packed));
        spin_unlock(&oi->ip_lock);
-
-       mlog_exit_void();
 }
 
 static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
@@ -2205,8 +2126,6 @@ static int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres)
        unsigned long flags;
        int status = 0;
 
-       mlog_entry_void();
-
 refresh_check:
        spin_lock_irqsave(&lockres->l_lock, flags);
        if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) {
@@ -2227,7 +2146,7 @@ refresh_check:
 
        status = 1;
 bail:
-       mlog_exit(status);
+       mlog(0, "status %d\n", status);
        return status;
 }
 
@@ -2237,7 +2156,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre
                                                   int status)
 {
        unsigned long flags;
-       mlog_entry_void();
 
        spin_lock_irqsave(&lockres->l_lock, flags);
        lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING);
@@ -2246,8 +2164,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre
        spin_unlock_irqrestore(&lockres->l_lock, flags);
 
        wake_up(&lockres->l_event);
-
-       mlog_exit_void();
 }
 
 /* may or may not return a bh if it went to disk. */
@@ -2260,8 +2176,6 @@ static int ocfs2_inode_lock_update(struct inode *inode,
        struct ocfs2_dinode *fe;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry_void();
-
        if (ocfs2_mount_local(osb))
                goto bail;
 
@@ -2330,7 +2244,6 @@ static int ocfs2_inode_lock_update(struct inode *inode,
 bail_refresh:
        ocfs2_complete_lock_res_refresh(lockres, status);
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -2374,8 +2287,6 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
 
        BUG_ON(!inode);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu, take %s META lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             ex ? "EXMODE" : "PRMODE");
@@ -2467,7 +2378,6 @@ bail:
        if (local_bh)
                brelse(local_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -2517,7 +2427,6 @@ int ocfs2_inode_lock_atime(struct inode *inode,
 {
        int ret;
 
-       mlog_entry_void();
        ret = ocfs2_inode_lock(inode, NULL, 0);
        if (ret < 0) {
                mlog_errno(ret);
@@ -2545,7 +2454,6 @@ int ocfs2_inode_lock_atime(struct inode *inode,
        } else
                *level = 0;
 
-       mlog_exit(ret);
        return ret;
 }
 
@@ -2556,8 +2464,6 @@ void ocfs2_inode_unlock(struct inode *inode,
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry_void();
-
        mlog(0, "inode %llu drop %s META lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             ex ? "EXMODE" : "PRMODE");
@@ -2565,8 +2471,6 @@ void ocfs2_inode_unlock(struct inode *inode,
        if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
            !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
-
-       mlog_exit_void();
 }
 
 int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno)
@@ -2617,8 +2521,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
        int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
        struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
 
-       mlog_entry_void();
-
        if (ocfs2_is_hard_readonly(osb))
                return -EROFS;
 
@@ -2650,7 +2552,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
                ocfs2_track_lock_refresh(lockres);
        }
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -2869,8 +2770,15 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
        return iter;
 }
 
-/* So that debugfs.ocfs2 can determine which format is being used */
-#define OCFS2_DLM_DEBUG_STR_VERSION 2
+/*
+ * Version is used by debugfs.ocfs2 to determine the format being used
+ *
+ * New in version 2
+ *     - Lock stats printed
+ * New in version 3
+ *     - Max time in lock stats is in usecs (instead of nsecs)
+ */
+#define OCFS2_DLM_DEBUG_STR_VERSION 3
 static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
 {
        int i;
@@ -2912,18 +2820,18 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
                seq_printf(m, "0x%x\t", lvb[i]);
 
 #ifdef CONFIG_OCFS2_FS_STATS
-# define lock_num_prmode(_l)           (_l)->l_lock_num_prmode
-# define lock_num_exmode(_l)           (_l)->l_lock_num_exmode
-# define lock_num_prmode_failed(_l)    (_l)->l_lock_num_prmode_failed
-# define lock_num_exmode_failed(_l)    (_l)->l_lock_num_exmode_failed
-# define lock_total_prmode(_l)         (_l)->l_lock_total_prmode
-# define lock_total_exmode(_l)         (_l)->l_lock_total_exmode
-# define lock_max_prmode(_l)           (_l)->l_lock_max_prmode
-# define lock_max_exmode(_l)           (_l)->l_lock_max_exmode
-# define lock_refresh(_l)              (_l)->l_lock_refresh
+# define lock_num_prmode(_l)           ((_l)->l_lock_prmode.ls_gets)
+# define lock_num_exmode(_l)           ((_l)->l_lock_exmode.ls_gets)
+# define lock_num_prmode_failed(_l)    ((_l)->l_lock_prmode.ls_fail)
+# define lock_num_exmode_failed(_l)    ((_l)->l_lock_exmode.ls_fail)
+# define lock_total_prmode(_l)         ((_l)->l_lock_prmode.ls_total)
+# define lock_total_exmode(_l)         ((_l)->l_lock_exmode.ls_total)
+# define lock_max_prmode(_l)           ((_l)->l_lock_prmode.ls_max)
+# define lock_max_exmode(_l)           ((_l)->l_lock_exmode.ls_max)
+# define lock_refresh(_l)              ((_l)->l_lock_refresh)
 #else
-# define lock_num_prmode(_l)           (0ULL)
-# define lock_num_exmode(_l)           (0ULL)
+# define lock_num_prmode(_l)           (0)
+# define lock_num_exmode(_l)           (0)
 # define lock_num_prmode_failed(_l)    (0)
 # define lock_num_exmode_failed(_l)    (0)
 # define lock_total_prmode(_l)         (0ULL)
@@ -2933,8 +2841,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
 # define lock_refresh(_l)              (0)
 #endif
        /* The following seq_print was added in version 2 of this output */
-       seq_printf(m, "%llu\t"
-                  "%llu\t"
+       seq_printf(m, "%u\t"
+                  "%u\t"
                   "%u\t"
                   "%u\t"
                   "%llu\t"
@@ -3054,8 +2962,6 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
        int status = 0;
        struct ocfs2_cluster_connection *conn = NULL;
 
-       mlog_entry_void();
-
        if (ocfs2_mount_local(osb)) {
                osb->node_num = 0;
                goto local;
@@ -3112,15 +3018,12 @@ bail:
                        kthread_stop(osb->dc_task);
        }
 
-       mlog_exit(status);
        return status;
 }
 
 void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
                        int hangup_pending)
 {
-       mlog_entry_void();
-
        ocfs2_drop_osb_locks(osb);
 
        /*
@@ -3143,8 +3046,6 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
        osb->cconn = NULL;
 
        ocfs2_dlm_shutdown_debug(osb);
-
-       mlog_exit_void();
 }
 
 static int ocfs2_drop_lock(struct ocfs2_super *osb,
@@ -3226,7 +3127,6 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
 
        ocfs2_wait_on_busy_lock(lockres);
 out:
-       mlog_exit(0);
        return 0;
 }
 
@@ -3284,8 +3184,6 @@ int ocfs2_drop_inode_locks(struct inode *inode)
 {
        int status, err;
 
-       mlog_entry_void();
-
        /* No need to call ocfs2_mark_lockres_freeing here -
         * ocfs2_clear_inode has done it for us. */
 
@@ -3310,7 +3208,6 @@ int ocfs2_drop_inode_locks(struct inode *inode)
        if (err < 0 && !status)
                status = err;
 
-       mlog_exit(status);
        return status;
 }
 
@@ -3352,8 +3249,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
        int ret;
        u32 dlm_flags = DLM_LKF_CONVERT;
 
-       mlog_entry_void();
-
        mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
             lockres->l_level, new_level);
 
@@ -3375,7 +3270,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
 
        ret = 0;
 bail:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -3385,8 +3279,6 @@ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
 {
        assert_spin_locked(&lockres->l_lock);
 
-       mlog_entry_void();
-
        if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
                /* If we're already trying to cancel a lock conversion
                 * then just drop the spinlock and allow the caller to
@@ -3416,8 +3308,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
 {
        int ret;
 
-       mlog_entry_void();
-
        ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb,
                               DLM_LKF_CANCEL);
        if (ret) {
@@ -3427,7 +3317,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
 
        mlog(ML_BASTS, "lockres %s\n", lockres->l_name);
 
-       mlog_exit(ret);
        return ret;
 }
 
@@ -3443,8 +3332,6 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
        int set_lvb = 0;
        unsigned int gen;
 
-       mlog_entry_void();
-
        spin_lock_irqsave(&lockres->l_lock, flags);
 
 recheck:
@@ -3619,14 +3506,14 @@ downconvert:
                                     gen);
 
 leave:
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
        return ret;
 
 leave_requeue:
        spin_unlock_irqrestore(&lockres->l_lock, flags);
        ctl->requeue = 1;
 
-       mlog_exit(0);
        return 0;
 }
 
@@ -3859,8 +3746,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
        struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
                                            oinfo->dqi_gi.dqi_type);
 
-       mlog_entry_void();
-
        lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
        lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
        lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
@@ -3869,8 +3754,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
        lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
        lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
        lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
-
-       mlog_exit_void();
 }
 
 void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
@@ -3879,10 +3762,8 @@ void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
        struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
        int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
 
-       mlog_entry_void();
        if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(osb, lockres, level);
-       mlog_exit_void();
 }
 
 static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
@@ -3937,8 +3818,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
        int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
        int status = 0;
 
-       mlog_entry_void();
-
        /* On RO devices, locking really isn't needed... */
        if (ocfs2_is_hard_readonly(osb)) {
                if (ex)
@@ -3961,7 +3840,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
                ocfs2_qinfo_unlock(oinfo, ex);
        ocfs2_complete_lock_res_refresh(lockres, status);
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -4007,8 +3885,6 @@ static void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
         * considered valid until we remove the OCFS2_LOCK_QUEUED
         * flag. */
 
-       mlog_entry_void();
-
        BUG_ON(!lockres);
        BUG_ON(!lockres->l_ops);
 
@@ -4042,15 +3918,11 @@ unqueue:
        if (ctl.unblock_action != UNBLOCK_CONTINUE
            && lockres->l_ops->post_unlock)
                lockres->l_ops->post_unlock(osb, lockres);
-
-       mlog_exit_void();
 }
 
 static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
                                        struct ocfs2_lock_res *lockres)
 {
-       mlog_entry_void();
-
        assert_spin_locked(&lockres->l_lock);
 
        if (lockres->l_flags & OCFS2_LOCK_FREEING) {
@@ -4071,8 +3943,6 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
                osb->blocked_lock_count++;
        }
        spin_unlock(&osb->dc_task_lock);
-
-       mlog_exit_void();
 }
 
 static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
@@ -4080,8 +3950,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
        unsigned long processed;
        struct ocfs2_lock_res *lockres;
 
-       mlog_entry_void();
-
        spin_lock(&osb->dc_task_lock);
        /* grab this early so we know to try again if a state change and
         * wake happens part-way through our work  */
@@ -4105,8 +3973,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
                spin_lock(&osb->dc_task_lock);
        }
        spin_unlock(&osb->dc_task_lock);
-
-       mlog_exit_void();
 }
 
 static int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb)
index 254652a9b542687e1a08e0e52d7b28db20ed6ba3..745db42528d5fd2f875a099177158f347fd361e7 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 
-#define MLOG_MASK_PREFIX ML_EXPORT
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -40,6 +39,7 @@
 
 #include "buffer_head_io.h"
 #include "suballoc.h"
+#include "ocfs2_trace.h"
 
 struct ocfs2_inode_handle
 {
@@ -56,10 +56,9 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
        int status, set;
        struct dentry *result;
 
-       mlog_entry("(0x%p, 0x%p)\n", sb, handle);
+       trace_ocfs2_get_dentry_begin(sb, handle, (unsigned long long)blkno);
 
        if (blkno == 0) {
-               mlog(0, "nfs wants inode with blkno: 0\n");
                result = ERR_PTR(-ESTALE);
                goto bail;
        }
@@ -83,6 +82,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
        }
 
        status = ocfs2_test_inode_bit(osb, blkno, &set);
+       trace_ocfs2_get_dentry_test_bit(status, set);
        if (status < 0) {
                if (status == -EINVAL) {
                        /*
@@ -90,18 +90,14 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
                         * as an inode, we return -ESTALE to be
                         * nice
                         */
-                       mlog(0, "test inode bit failed %d\n", status);
                        status = -ESTALE;
-               } else {
+               } else
                        mlog(ML_ERROR, "test inode bit failed %d\n", status);
-               }
                goto unlock_nfs_sync;
        }
 
        /* If the inode allocator bit is clear, this inode must be stale */
        if (!set) {
-               mlog(0, "inode %llu suballoc bit is clear\n",
-                    (unsigned long long)blkno);
                status = -ESTALE;
                goto unlock_nfs_sync;
        }
@@ -114,8 +110,8 @@ unlock_nfs_sync:
 check_err:
        if (status < 0) {
                if (status == -ESTALE) {
-                       mlog(0, "stale inode ino: %llu generation: %u\n",
-                            (unsigned long long)blkno, handle->ih_generation);
+                       trace_ocfs2_get_dentry_stale((unsigned long long)blkno,
+                                                    handle->ih_generation);
                }
                result = ERR_PTR(status);
                goto bail;
@@ -130,8 +126,9 @@ check_err:
 check_gen:
        if (handle->ih_generation != inode->i_generation) {
                iput(inode);
-               mlog(0, "stale inode ino: %llu generation: %u\n",
-                    (unsigned long long)blkno, handle->ih_generation);
+               trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
+                                                 handle->ih_generation,
+                                                 inode->i_generation);
                result = ERR_PTR(-ESTALE);
                goto bail;
        }
@@ -141,7 +138,7 @@ check_gen:
                mlog_errno(PTR_ERR(result));
 
 bail:
-       mlog_exit_ptr(result);
+       trace_ocfs2_get_dentry_end(result);
        return result;
 }
 
@@ -152,11 +149,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
        struct dentry *parent;
        struct inode *dir = child->d_inode;
 
-       mlog_entry("(0x%p, '%.*s')\n", child,
-                  child->d_name.len, child->d_name.name);
-
-       mlog(0, "find parent of directory %llu\n",
-            (unsigned long long)OCFS2_I(dir)->ip_blkno);
+       trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
+                              (unsigned long long)OCFS2_I(dir)->ip_blkno);
 
        status = ocfs2_inode_lock(dir, NULL, 0);
        if (status < 0) {
@@ -178,7 +172,7 @@ bail_unlock:
        ocfs2_inode_unlock(dir, 0);
 
 bail:
-       mlog_exit_ptr(parent);
+       trace_ocfs2_get_parent_end(parent);
 
        return parent;
 }
@@ -193,9 +187,9 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
        u32 generation;
        __le32 *fh = (__force __le32 *) fh_in;
 
-       mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry,
-                  dentry->d_name.len, dentry->d_name.name,
-                  fh, len, connectable);
+       trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len,
+                                   dentry->d_name.name,
+                                   fh, len, connectable);
 
        if (connectable && (len < 6)) {
                *max_len = 6;
@@ -210,8 +204,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
        blkno = OCFS2_I(inode)->ip_blkno;
        generation = inode->i_generation;
 
-       mlog(0, "Encoding fh: blkno: %llu, generation: %u\n",
-            (unsigned long long)blkno, generation);
+       trace_ocfs2_encode_fh_self((unsigned long long)blkno, generation);
 
        len = 3;
        fh[0] = cpu_to_le32((u32)(blkno >> 32));
@@ -236,14 +229,14 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
                len = 6;
                type = 2;
 
-               mlog(0, "Encoding parent: blkno: %llu, generation: %u\n",
-                    (unsigned long long)blkno, generation);
+               trace_ocfs2_encode_fh_parent((unsigned long long)blkno,
+                                            generation);
        }
 
        *max_len = len;
 
 bail:
-       mlog_exit(type);
+       trace_ocfs2_encode_fh_type(type);
        return type;
 }
 
index 09e3fdfa6d33f603f6fe2a9bcdade3f979565e61..23457b491e8ce53ac5b71d9cd5fc2a5e1400a07f 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/types.h>
 #include <linux/fiemap.h>
 
-#define MLOG_MASK_PREFIX ML_EXTENT_MAP
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -39,6 +38,7 @@
 #include "inode.h"
 #include "super.h"
 #include "symlink.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -841,10 +841,9 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
        u64 p_block, p_count;
        int i, count, done = 0;
 
-       mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, "
-                  "flags = %x, validate = %p)\n",
-                  inode, (unsigned long long)v_block, nr, bhs, flags,
-                  validate);
+       trace_ocfs2_read_virt_blocks(
+            inode, (unsigned long long)v_block, nr, bhs, flags,
+            validate);
 
        if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >=
            i_size_read(inode)) {
@@ -897,7 +896,6 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
        }
 
 out:
-       mlog_exit(rc);
        return rc;
 }
 
index a6651956482e121b460ccadb5446892efee220a7..41565ae528566b3a5bfca14092aad21bba721812 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/quotaops.h>
 #include <linux/blkdev.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -61,6 +60,7 @@
 #include "acl.h"
 #include "quota.h"
 #include "refcounttree.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -99,8 +99,10 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
        int mode = file->f_flags;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
-       mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
-                  file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name);
+       trace_ocfs2_file_open(inode, file, file->f_path.dentry,
+                             (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                             file->f_path.dentry->d_name.len,
+                             file->f_path.dentry->d_name.name, mode);
 
        if (file->f_mode & FMODE_WRITE)
                dquot_initialize(inode);
@@ -135,7 +137,6 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
        }
 
 leave:
-       mlog_exit(status);
        return status;
 }
 
@@ -143,19 +144,19 @@ static int ocfs2_file_release(struct inode *inode, struct file *file)
 {
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
-       mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
-                      file->f_path.dentry->d_name.len,
-                      file->f_path.dentry->d_name.name);
-
        spin_lock(&oi->ip_lock);
        if (!--oi->ip_open_count)
                oi->ip_flags &= ~OCFS2_INODE_OPEN_DIRECT;
+
+       trace_ocfs2_file_release(inode, file, file->f_path.dentry,
+                                oi->ip_blkno,
+                                file->f_path.dentry->d_name.len,
+                                file->f_path.dentry->d_name.name,
+                                oi->ip_open_count);
        spin_unlock(&oi->ip_lock);
 
        ocfs2_free_file_private(inode, file);
 
-       mlog_exit(0);
-
        return 0;
 }
 
@@ -177,9 +178,11 @@ static int ocfs2_sync_file(struct file *file, int datasync)
        struct inode *inode = file->f_mapping->host;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       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);
+       trace_ocfs2_sync_file(inode, file, file->f_path.dentry,
+                             OCFS2_I(inode)->ip_blkno,
+                             file->f_path.dentry->d_name.len,
+                             file->f_path.dentry->d_name.name,
+                             (unsigned long long)datasync);
 
        if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
                /*
@@ -195,7 +198,8 @@ static int ocfs2_sync_file(struct file *file, int datasync)
        err = jbd2_journal_force_commit(journal);
 
 bail:
-       mlog_exit(err);
+       if (err)
+               mlog_errno(err);
 
        return (err < 0) ? -EIO : 0;
 }
@@ -251,8 +255,6 @@ int ocfs2_update_inode_atime(struct inode *inode,
        handle_t *handle;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *) bh->b_data;
 
-       mlog_entry_void();
-
        handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
@@ -280,7 +282,6 @@ int ocfs2_update_inode_atime(struct inode *inode,
 out_commit:
        ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -291,7 +292,6 @@ static int ocfs2_set_inode_size(handle_t *handle,
 {
        int status;
 
-       mlog_entry_void();
        i_size_write(inode, new_i_size);
        inode->i_blocks = ocfs2_inode_sector_count(inode);
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
@@ -303,7 +303,6 @@ static int ocfs2_set_inode_size(handle_t *handle,
        }
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -375,8 +374,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
        struct ocfs2_dinode *di;
        u64 cluster_bytes;
 
-       mlog_entry_void();
-
        /*
         * We need to CoW the cluster contains the offset if it is reflinked
         * since we will call ocfs2_zero_range_for_truncate later which will
@@ -429,8 +426,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
 out_commit:
        ocfs2_commit_trans(osb, handle);
 out:
-
-       mlog_exit(status);
        return status;
 }
 
@@ -442,14 +437,14 @@ static int ocfs2_truncate_file(struct inode *inode,
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry("(inode = %llu, new_i_size = %llu\n",
-                  (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                  (unsigned long long)new_i_size);
-
        /* We trust di_bh because it comes from ocfs2_inode_lock(), which
         * already validated it */
        fe = (struct ocfs2_dinode *) di_bh->b_data;
 
+       trace_ocfs2_truncate_file((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                 (unsigned long long)le64_to_cpu(fe->i_size),
+                                 (unsigned long long)new_i_size);
+
        mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode),
                        "Inode %llu, inode i_size = %lld != di "
                        "i_size = %llu, i_flags = 0x%x\n",
@@ -459,19 +454,14 @@ static int ocfs2_truncate_file(struct inode *inode,
                        le32_to_cpu(fe->i_flags));
 
        if (new_i_size > le64_to_cpu(fe->i_size)) {
-               mlog(0, "asked to truncate file with size (%llu) to size (%llu)!\n",
-                    (unsigned long long)le64_to_cpu(fe->i_size),
-                    (unsigned long long)new_i_size);
+               trace_ocfs2_truncate_file_error(
+                       (unsigned long long)le64_to_cpu(fe->i_size),
+                       (unsigned long long)new_i_size);
                status = -EINVAL;
                mlog_errno(status);
                goto bail;
        }
 
-       mlog(0, "inode %llu, i_size = %llu, new_i_size = %llu\n",
-            (unsigned long long)le64_to_cpu(fe->i_blkno),
-            (unsigned long long)le64_to_cpu(fe->i_size),
-            (unsigned long long)new_i_size);
-
        /* lets handle the simple truncate cases before doing any more
         * cluster locking. */
        if (new_i_size == le64_to_cpu(fe->i_size))
@@ -525,7 +515,6 @@ bail:
        if (!status && OCFS2_I(inode)->ip_clusters == 0)
                status = ocfs2_try_remove_refcount_tree(inode, di_bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -578,8 +567,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
        struct ocfs2_extent_tree et;
        int did_quota = 0;
 
-       mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
-
        /*
         * This function only exists for file systems which don't
         * support holes.
@@ -596,11 +583,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
 restart_all:
        BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
 
-       mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
-            "clusters_to_add = %u\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno,
-            (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
-            clusters_to_add);
        ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh);
        status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
                                       &data_ac, &meta_ac);
@@ -620,6 +602,12 @@ restart_all:
        }
 
 restarted_transaction:
+       trace_ocfs2_extend_allocation(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               (unsigned long long)i_size_read(inode),
+               le32_to_cpu(fe->i_clusters), clusters_to_add,
+               why, restart_func);
+
        status = dquot_alloc_space_nodirty(inode,
                        ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
        if (status)
@@ -666,13 +654,11 @@ restarted_transaction:
 
        if (why != RESTART_NONE && clusters_to_add) {
                if (why == RESTART_META) {
-                       mlog(0, "restarting function.\n");
                        restart_func = 1;
                        status = 0;
                } else {
                        BUG_ON(why != RESTART_TRANS);
 
-                       mlog(0, "restarting transaction.\n");
                        /* TODO: This can be more intelligent. */
                        credits = ocfs2_calc_extend_credits(osb->sb,
                                                            &fe->id2.i_list,
@@ -689,11 +675,11 @@ restarted_transaction:
                }
        }
 
-       mlog(0, "fe: i_clusters = %u, i_size=%llu\n",
+       trace_ocfs2_extend_allocation_end(OCFS2_I(inode)->ip_blkno,
             le32_to_cpu(fe->i_clusters),
-            (unsigned long long)le64_to_cpu(fe->i_size));
-       mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",
-            OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode));
+            (unsigned long long)le64_to_cpu(fe->i_size),
+            OCFS2_I(inode)->ip_clusters,
+            (unsigned long long)i_size_read(inode));
 
 leave:
        if (status < 0 && did_quota)
@@ -718,7 +704,6 @@ leave:
        brelse(bh);
        bh = NULL;
 
-       mlog_exit(status);
        return status;
 }
 
@@ -785,10 +770,11 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
        if (!zero_to)
                zero_to = PAGE_CACHE_SIZE;
 
-       mlog(0,
-            "abs_from = %llu, abs_to = %llu, index = %lu, zero_from = %u, zero_to = %u\n",
-            (unsigned long long)abs_from, (unsigned long long)abs_to,
-            index, zero_from, zero_to);
+       trace_ocfs2_write_zero_page(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)abs_from,
+                       (unsigned long long)abs_to,
+                       index, zero_from, zero_to);
 
        /* We know that zero_from is block aligned */
        for (block_start = zero_from; block_start < zero_to;
@@ -928,9 +914,10 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start,
        u64 next_pos;
        u64 zero_pos = range_start;
 
-       mlog(0, "range_start = %llu, range_end = %llu\n",
-            (unsigned long long)range_start,
-            (unsigned long long)range_end);
+       trace_ocfs2_zero_extend_range(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)range_start,
+                       (unsigned long long)range_end);
        BUG_ON(range_start >= range_end);
 
        while (zero_pos < range_end) {
@@ -962,9 +949,9 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh,
        struct super_block *sb = inode->i_sb;
 
        zero_start = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode));
-       mlog(0, "zero_start %llu for i_size %llu\n",
-            (unsigned long long)zero_start,
-            (unsigned long long)i_size_read(inode));
+       trace_ocfs2_zero_extend((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                               (unsigned long long)zero_start,
+                               (unsigned long long)i_size_read(inode));
        while (zero_start < zero_to_size) {
                ret = ocfs2_zero_extend_get_range(inode, di_bh, zero_start,
                                                  zero_to_size,
@@ -1113,30 +1100,20 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
        struct dquot *transfer_to[MAXQUOTAS] = { };
        int qtype;
 
-       mlog_entry("(0x%p, '%.*s')\n", dentry,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_setattr(inode, dentry,
+                           (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                           dentry->d_name.len, dentry->d_name.name,
+                           attr->ia_valid, attr->ia_mode,
+                           attr->ia_uid, attr->ia_gid);
 
        /* ensuring we don't even attempt to truncate a symlink */
        if (S_ISLNK(inode->i_mode))
                attr->ia_valid &= ~ATTR_SIZE;
 
-       if (attr->ia_valid & ATTR_MODE)
-               mlog(0, "mode change: %d\n", attr->ia_mode);
-       if (attr->ia_valid & ATTR_UID)
-               mlog(0, "uid change: %d\n", attr->ia_uid);
-       if (attr->ia_valid & ATTR_GID)
-               mlog(0, "gid change: %d\n", attr->ia_gid);
-       if (attr->ia_valid & ATTR_SIZE)
-               mlog(0, "size change...\n");
-       if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME))
-               mlog(0, "time change...\n");
-
 #define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \
                           | ATTR_GID | ATTR_UID | ATTR_MODE)
-       if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) {
-               mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid);
+       if (!(attr->ia_valid & OCFS2_VALID_ATTRS))
                return 0;
-       }
 
        status = inode_change_ok(inode, attr);
        if (status)
@@ -1274,7 +1251,6 @@ bail:
                        mlog_errno(status);
        }
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1287,8 +1263,6 @@ int ocfs2_getattr(struct vfsmount *mnt,
        struct ocfs2_super *osb = sb->s_fs_info;
        int err;
 
-       mlog_entry_void();
-
        err = ocfs2_inode_revalidate(dentry);
        if (err) {
                if (err != -ENOENT)
@@ -1302,8 +1276,6 @@ int ocfs2_getattr(struct vfsmount *mnt,
        stat->blksize = osb->s_clustersize;
 
 bail:
-       mlog_exit(err);
-
        return err;
 }
 
@@ -1314,8 +1286,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags)
        if (flags & IPERM_FLAG_RCU)
                return -ECHILD;
 
-       mlog_entry_void();
-
        ret = ocfs2_inode_lock(inode, NULL, 0);
        if (ret) {
                if (ret != -ENOENT)
@@ -1327,7 +1297,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags)
 
        ocfs2_inode_unlock(inode, 0);
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1339,8 +1308,9 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_dinode *di;
 
-       mlog_entry("(Inode %llu, mode 0%o)\n",
-                  (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
+       trace_ocfs2_write_remove_suid(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       inode->i_mode);
 
        handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
@@ -1368,7 +1338,6 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
 out_trans:
        ocfs2_commit_trans(osb, handle);
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -1547,8 +1516,9 @@ static int ocfs2_zero_partial_clusters(struct inode *inode,
         * partial clusters here. There's no need to worry about
         * physical allocation - the zeroing code knows to skip holes.
         */
-       mlog(0, "byte start: %llu, end: %llu\n",
-            (unsigned long long)start, (unsigned long long)end);
+       trace_ocfs2_zero_partial_clusters(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               (unsigned long long)start, (unsigned long long)end);
 
        /*
         * If both edges are on a cluster boundary then there's no
@@ -1572,8 +1542,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode,
        if (tmpend > end)
                tmpend = end;
 
-       mlog(0, "1st range: start: %llu, tmpend: %llu\n",
-            (unsigned long long)start, (unsigned long long)tmpend);
+       trace_ocfs2_zero_partial_clusters_range1((unsigned long long)start,
+                                                (unsigned long long)tmpend);
 
        ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
        if (ret)
@@ -1587,8 +1557,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode,
                 */
                start = end & ~(osb->s_clustersize - 1);
 
-               mlog(0, "2nd range: start: %llu, end: %llu\n",
-                    (unsigned long long)start, (unsigned long long)end);
+               trace_ocfs2_zero_partial_clusters_range2(
+                       (unsigned long long)start, (unsigned long long)end);
 
                ret = ocfs2_zero_range_for_truncate(inode, handle, start, end);
                if (ret)
@@ -1688,6 +1658,11 @@ static int ocfs2_remove_inode_range(struct inode *inode,
        ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
        ocfs2_init_dealloc_ctxt(&dealloc);
 
+       trace_ocfs2_remove_inode_range(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)byte_start,
+                       (unsigned long long)byte_len);
+
        if (byte_len == 0)
                return 0;
 
@@ -1734,11 +1709,6 @@ static int ocfs2_remove_inode_range(struct inode *inode,
        trunc_end = (byte_start + byte_len) >> osb->s_clustersize_bits;
        cluster_in_el = trunc_end;
 
-       mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, cend: %u\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno,
-            (unsigned long long)byte_start,
-            (unsigned long long)byte_len, trunc_start, trunc_end);
-
        ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len);
        if (ret) {
                mlog_errno(ret);
@@ -2093,7 +2063,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
        int ret = 0, meta_level = 0;
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
-       loff_t saved_pos, end;
+       loff_t saved_pos = 0, end;
 
        /*
         * We start with a read level meta lock and only jump to an ex
@@ -2132,12 +2102,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
 
                /* work on a copy of ppos until we're sure that we won't have
                 * to recalculate it due to relocking. */
-               if (appending) {
+               if (appending)
                        saved_pos = i_size_read(inode);
-                       mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos);
-               } else {
+               else
                        saved_pos = *ppos;
-               }
 
                end = saved_pos + count;
 
@@ -2208,6 +2176,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
                *ppos = saved_pos;
 
 out_unlock:
+       trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno,
+                                           saved_pos, appending, count,
+                                           direct_io, has_refcount);
+
        if (meta_level >= 0)
                ocfs2_inode_unlock(inode, meta_level);
 
@@ -2233,10 +2205,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
        int full_coherency = !(osb->s_mount_opt &
                               OCFS2_MOUNT_COHERENCY_BUFFERED);
 
-       mlog_entry("(0x%p, %u, '%.*s')\n", file,
-                  (unsigned int)nr_segs,
-                  file->f_path.dentry->d_name.len,
-                  file->f_path.dentry->d_name.name);
+       trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               file->f_path.dentry->d_name.len,
+               file->f_path.dentry->d_name.name,
+               (unsigned int)nr_segs);
 
        if (iocb->ki_left == 0)
                return 0;
@@ -2402,7 +2375,6 @@ out_sems:
 
        if (written)
                ret = written;
-       mlog_exit(ret);
        return ret;
 }
 
@@ -2438,10 +2410,11 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
                .u.file = out,
        };
 
-       mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
-                  (unsigned int)len,
-                  out->f_path.dentry->d_name.len,
-                  out->f_path.dentry->d_name.name);
+
+       trace_ocfs2_file_splice_write(inode, out, out->f_path.dentry,
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       out->f_path.dentry->d_name.len,
+                       out->f_path.dentry->d_name.name, len);
 
        if (pipe->inode)
                mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
@@ -2485,7 +2458,6 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
                balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
        }
 
-       mlog_exit(ret);
        return ret;
 }
 
@@ -2498,10 +2470,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
        int ret = 0, lock_level = 0;
        struct inode *inode = in->f_path.dentry->d_inode;
 
-       mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe,
-                  (unsigned int)len,
-                  in->f_path.dentry->d_name.len,
-                  in->f_path.dentry->d_name.name);
+       trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry,
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       in->f_path.dentry->d_name.len,
+                       in->f_path.dentry->d_name.name, len);
 
        /*
         * See the comment in ocfs2_file_aio_read()
@@ -2516,7 +2488,6 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
        ret = generic_file_splice_read(in, ppos, pipe, len, flags);
 
 bail:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -2529,10 +2500,11 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
        struct file *filp = iocb->ki_filp;
        struct inode *inode = filp->f_path.dentry->d_inode;
 
-       mlog_entry("(0x%p, %u, '%.*s')\n", filp,
-                  (unsigned int)nr_segs,
-                  filp->f_path.dentry->d_name.len,
-                  filp->f_path.dentry->d_name.name);
+       trace_ocfs2_file_aio_read(inode, filp, filp->f_path.dentry,
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       filp->f_path.dentry->d_name.len,
+                       filp->f_path.dentry->d_name.name, nr_segs);
+
 
        if (!inode) {
                ret = -EINVAL;
@@ -2578,8 +2550,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
        ocfs2_inode_unlock(inode, lock_level);
 
        ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
-       if (ret == -EINVAL)
-               mlog(0, "generic_file_aio_read returned -EINVAL\n");
+       trace_generic_file_aio_read_ret(ret);
 
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
@@ -2597,7 +2568,6 @@ bail:
        }
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);
-       mlog_exit(ret);
 
        return ret;
 }
index 1aa863dd901f783d71e54f19b37e78440fe46693..d8208b20dc532ea80a2f807d6b7ee39ee5c22306 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 
-#define MLOG_MASK_PREFIX ML_SUPER
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -37,6 +36,7 @@
 #include "heartbeat.h"
 #include "inode.h"
 #include "journal.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -66,7 +66,7 @@ void ocfs2_do_node_down(int node_num, void *data)
 
        BUG_ON(osb->node_num == node_num);
 
-       mlog(0, "ocfs2: node down event for %d\n", node_num);
+       trace_ocfs2_do_node_down(node_num);
 
        if (!osb->cconn) {
                /*
index 4068c6c4c6f64c56c6c2a675b82c5a4cf1934f83..177d3a6c2a5f4fdfc301ed3c9bb626a84594b93b 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/byteorder.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -53,6 +52,7 @@
 #include "uptodate.h"
 #include "xattr.h"
 #include "refcounttree.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -131,7 +131,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
        struct super_block *sb = osb->sb;
        struct ocfs2_find_inode_args args;
 
-       mlog_entry("(blkno = %llu)\n", (unsigned long long)blkno);
+       trace_ocfs2_iget_begin((unsigned long long)blkno, flags,
+                              sysfile_type);
 
        /* Ok. By now we've either got the offsets passed to us by the
         * caller, or we just pulled them off the bh. Lets do some
@@ -152,16 +153,16 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
        /* inode was *not* in the inode cache. 2.6.x requires
         * us to do our own read_inode call and unlock it
         * afterwards. */
-       if (inode && inode->i_state & I_NEW) {
-               mlog(0, "Inode was not in inode cache, reading it.\n");
-               ocfs2_read_locked_inode(inode, &args);
-               unlock_new_inode(inode);
-       }
        if (inode == NULL) {
                inode = ERR_PTR(-ENOMEM);
                mlog_errno(PTR_ERR(inode));
                goto bail;
        }
+       trace_ocfs2_iget5_locked(inode->i_state);
+       if (inode->i_state & I_NEW) {
+               ocfs2_read_locked_inode(inode, &args);
+               unlock_new_inode(inode);
+       }
        if (is_bad_inode(inode)) {
                iput(inode);
                inode = ERR_PTR(-ESTALE);
@@ -170,9 +171,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
 
 bail:
        if (!IS_ERR(inode)) {
-               mlog(0, "returning inode with number %llu\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno);
-               mlog_exit_ptr(inode);
+               trace_ocfs2_iget_end(inode, 
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno);
        }
 
        return inode;
@@ -192,18 +192,17 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque)
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        int ret = 0;
 
-       mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque);
-
        args = opaque;
 
        mlog_bug_on_msg(!inode, "No inode in find actor!\n");
 
+       trace_ocfs2_find_actor(inode, inode->i_ino, opaque, args->fi_blkno);
+
        if (oi->ip_blkno != args->fi_blkno)
                goto bail;
 
        ret = 1;
 bail:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -218,8 +217,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque)
        static struct lock_class_key ocfs2_quota_ip_alloc_sem_key,
                                     ocfs2_file_ip_alloc_sem_key;
 
-       mlog_entry("inode = %p, opaque = %p\n", inode, opaque);
-
        inode->i_ino = args->fi_ino;
        OCFS2_I(inode)->ip_blkno = args->fi_blkno;
        if (args->fi_sysfile_type != 0)
@@ -235,7 +232,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque)
                lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem,
                                  &ocfs2_file_ip_alloc_sem_key);
 
-       mlog_exit(0);
        return 0;
 }
 
@@ -246,9 +242,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        struct ocfs2_super *osb;
        int use_plocks = 1;
 
-       mlog_entry("(0x%p, size:%llu)\n", inode,
-                  (unsigned long long)le64_to_cpu(fe->i_size));
-
        sb = inode->i_sb;
        osb = OCFS2_SB(sb);
 
@@ -300,20 +293,20 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
 
        inode->i_nlink = ocfs2_read_links_count(fe);
 
+       trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno,
+                                  le32_to_cpu(fe->i_flags));
        if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
                inode->i_flags |= S_NOQUOTA;
        }
-
+  
        if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
-               mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino);
        } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
        } else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) {
                inode->i_flags |= S_NOQUOTA;
        } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) {
-               mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino);
                /* we can't actually hit this as read_inode can't
                 * handle superblocks today ;-) */
                BUG();
@@ -381,7 +374,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        if (S_ISDIR(inode->i_mode))
                ocfs2_resv_set_type(&OCFS2_I(inode)->ip_la_data_resv,
                                    OCFS2_RESV_FLAG_DIR);
-       mlog_exit_void();
 }
 
 static int ocfs2_read_locked_inode(struct inode *inode,
@@ -394,8 +386,6 @@ static int ocfs2_read_locked_inode(struct inode *inode,
        int status, can_lock;
        u32 generation = 0;
 
-       mlog_entry("(0x%p, 0x%p)\n", inode, args);
-
        status = -EINVAL;
        if (inode == NULL || inode->i_sb == NULL) {
                mlog(ML_ERROR, "bad inode\n");
@@ -443,6 +433,9 @@ static int ocfs2_read_locked_inode(struct inode *inode,
                && !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)
                && !ocfs2_mount_local(osb);
 
+       trace_ocfs2_read_locked_inode(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock);
+
        /*
         * To maintain backwards compatibility with older versions of
         * ocfs2-tools, we still store the generation value for system
@@ -534,7 +527,6 @@ bail:
        if (args && bh)
                brelse(bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -551,8 +543,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
        struct ocfs2_dinode *fe;
        handle_t *handle = NULL;
 
-       mlog_entry_void();
-
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        /*
@@ -600,7 +590,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
 out:
        if (handle)
                ocfs2_commit_trans(osb, handle);
-       mlog_exit(status);
        return status;
 }
 
@@ -696,8 +685,6 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb,
 
        spin_lock(&osb->osb_lock);
        if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) {
-               mlog(0, "Recovery is happening on orphan dir %d, will skip "
-                    "this inode\n", slot);
                ret = -EDEADLK;
                goto out;
        }
@@ -706,6 +693,7 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb,
        osb->osb_orphan_wipes[slot]++;
 out:
        spin_unlock(&osb->osb_lock);
+       trace_ocfs2_check_orphan_recovery_state(slot, ret);
        return ret;
 }
 
@@ -816,6 +804,10 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
+       trace_ocfs2_inode_is_valid_to_delete(current, osb->dc_task,
+                                            (unsigned long long)oi->ip_blkno,
+                                            oi->ip_flags);
+
        /* We shouldn't be getting here for the root directory
         * inode.. */
        if (inode == osb->root_inode) {
@@ -828,11 +820,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
         * have to skip deleting this guy. That's OK though because
         * the node who's doing the actual deleting should handle it
         * anyway. */
-       if (current == osb->dc_task) {
-               mlog(0, "Skipping delete of %lu because we're currently "
-                    "in downconvert\n", inode->i_ino);
+       if (current == osb->dc_task)
                goto bail;
-       }
 
        spin_lock(&oi->ip_lock);
        /* OCFS2 *never* deletes system files. This should technically
@@ -847,11 +836,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
        /* If we have allowd wipe of this inode for another node, it
         * will be marked here so we can safely skip it. Recovery will
         * cleanup any inodes we might inadvertantly skip here. */
-       if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) {
-               mlog(0, "Skipping delete of %lu because another node "
-                    "has done this for us.\n", inode->i_ino);
+       if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE)
                goto bail_unlock;
-       }
 
        ret = 1;
 bail_unlock:
@@ -868,28 +854,27 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
                                  struct buffer_head *di_bh,
                                  int *wipe)
 {
-       int status = 0;
+       int status = 0, reason = 0;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_dinode *di;
 
        *wipe = 0;
 
+       trace_ocfs2_query_inode_wipe_begin((unsigned long long)oi->ip_blkno,
+                                          inode->i_nlink);
+
        /* While we were waiting for the cluster lock in
         * ocfs2_delete_inode, another node might have asked to delete
         * the inode. Recheck our flags to catch this. */
        if (!ocfs2_inode_is_valid_to_delete(inode)) {
-               mlog(0, "Skipping delete of %llu because flags changed\n",
-                    (unsigned long long)oi->ip_blkno);
+               reason = 1;
                goto bail;
        }
 
        /* Now that we have an up to date inode, we can double check
         * the link count. */
-       if (inode->i_nlink) {
-               mlog(0, "Skipping delete of %llu because nlink = %u\n",
-                    (unsigned long long)oi->ip_blkno, inode->i_nlink);
+       if (inode->i_nlink)
                goto bail;
-       }
 
        /* Do some basic inode verification... */
        di = (struct ocfs2_dinode *) di_bh->b_data;
@@ -904,9 +889,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
                 * ORPHANED_FL not.
                 */
                if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) {
-                       mlog(0, "Reflinked inode %llu is no longer orphaned.  "
-                            "it shouldn't be deleted\n",
-                            (unsigned long long)oi->ip_blkno);
+                       reason = 2;
                        goto bail;
                }
 
@@ -943,8 +926,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
        status = ocfs2_try_open_lock(inode, 1);
        if (status == -EAGAIN) {
                status = 0;
-               mlog(0, "Skipping delete of %llu because it is in use on "
-                    "other nodes\n", (unsigned long long)oi->ip_blkno);
+               reason = 3;
                goto bail;
        }
        if (status < 0) {
@@ -953,11 +935,10 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
        }
 
        *wipe = 1;
-       mlog(0, "Inode %llu is ok to wipe from orphan dir %u\n",
-            (unsigned long long)oi->ip_blkno,
-            le16_to_cpu(di->i_orphaned_slot));
+       trace_ocfs2_query_inode_wipe_succ(le16_to_cpu(di->i_orphaned_slot));
 
 bail:
+       trace_ocfs2_query_inode_wipe_end(status, reason);
        return status;
 }
 
@@ -967,8 +948,8 @@ bail:
 static void ocfs2_cleanup_delete_inode(struct inode *inode,
                                       int sync_data)
 {
-       mlog(0, "Cleanup inode %llu, sync = %d\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
+       trace_ocfs2_cleanup_delete_inode(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
        if (sync_data)
                write_inode_now(inode, 1);
        truncate_inode_pages(&inode->i_data, 0);
@@ -980,15 +961,15 @@ static void ocfs2_delete_inode(struct inode *inode)
        sigset_t oldset;
        struct buffer_head *di_bh = NULL;
 
-       mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
+       trace_ocfs2_delete_inode(inode->i_ino,
+                                (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                is_bad_inode(inode));
 
        /* When we fail in read_inode() we mark inode as bad. The second test
         * catches the case when inode allocation fails before allocating
         * a block for inode. */
-       if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) {
-               mlog(0, "Skipping delete of bad inode\n");
+       if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno)
                goto bail;
-       }
 
        dquot_initialize(inode);
 
@@ -1080,7 +1061,7 @@ bail_unlock_nfs_sync:
 bail_unblock:
        ocfs2_unblock_signals(&oldset);
 bail:
-       mlog_exit_void();
+       return;
 }
 
 static void ocfs2_clear_inode(struct inode *inode)
@@ -1088,11 +1069,9 @@ static void ocfs2_clear_inode(struct inode *inode)
        int status;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
-       mlog_entry_void();
-
        end_writeback(inode);
-       mlog(0, "Clearing inode: %llu, nlink = %u\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink);
+       trace_ocfs2_clear_inode((unsigned long long)oi->ip_blkno,
+                               inode->i_nlink);
 
        mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL,
                        "Inode=%lu\n", inode->i_ino);
@@ -1181,8 +1160,6 @@ static void ocfs2_clear_inode(struct inode *inode)
         */
        jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal,
                                       &oi->ip_jinode);
-
-       mlog_exit_void();
 }
 
 void ocfs2_evict_inode(struct inode *inode)
@@ -1204,17 +1181,14 @@ int ocfs2_drop_inode(struct inode *inode)
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        int res;
 
-       mlog_entry_void();
-
-       mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n",
-            (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);
+       trace_ocfs2_drop_inode((unsigned long long)oi->ip_blkno,
+                               inode->i_nlink, oi->ip_flags);
 
        if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
                res = 1;
        else
                res = generic_drop_inode(inode);
 
-       mlog_exit_void();
        return res;
 }
 
@@ -1226,11 +1200,11 @@ int ocfs2_inode_revalidate(struct dentry *dentry)
        struct inode *inode = dentry->d_inode;
        int status = 0;
 
-       mlog_entry("(inode = 0x%p, ino = %llu)\n", inode,
-                  inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL);
+       trace_ocfs2_inode_revalidate(inode,
+               inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL,
+               inode ? (unsigned long long)OCFS2_I(inode)->ip_flags : 0);
 
        if (!inode) {
-               mlog(0, "eep, no inode!\n");
                status = -ENOENT;
                goto bail;
        }
@@ -1238,7 +1212,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry)
        spin_lock(&OCFS2_I(inode)->ip_lock);
        if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
                spin_unlock(&OCFS2_I(inode)->ip_lock);
-               mlog(0, "inode deleted!\n");
                status = -ENOENT;
                goto bail;
        }
@@ -1254,8 +1227,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry)
        }
        ocfs2_inode_unlock(inode, 0);
 bail:
-       mlog_exit(status);
-
        return status;
 }
 
@@ -1271,8 +1242,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
        int status;
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
 
-       mlog_entry("(inode %llu)\n",
-                  (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       trace_ocfs2_mark_inode_dirty((unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
@@ -1302,7 +1272,6 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
 
        ocfs2_journal_dirty(handle, bh);
 leave:
-       mlog_exit(status);
        return status;
 }
 
@@ -1345,8 +1314,7 @@ int ocfs2_validate_inode_block(struct super_block *sb,
        int rc;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
 
-       mlog(0, "Validating dinode %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_inode_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
index 09de77ce002ab0f68e9e0783521f5eba3f6ae056..8f13c5989eaeeecd543be983cec37176c1c54ece 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/mount.h>
 #include <linux/compat.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -46,6 +45,22 @@ static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq,
 #define o2info_set_request_error(a, b) \
                __o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
 
+static inline void __o2info_set_request_filled(struct ocfs2_info_request *req)
+{
+       req->ir_flags |= OCFS2_INFO_FL_FILLED;
+}
+
+#define o2info_set_request_filled(a) \
+               __o2info_set_request_filled((struct ocfs2_info_request *)&(a))
+
+static inline void __o2info_clear_request_filled(struct ocfs2_info_request *req)
+{
+       req->ir_flags &= ~OCFS2_INFO_FL_FILLED;
+}
+
+#define o2info_clear_request_filled(a) \
+               __o2info_clear_request_filled((struct ocfs2_info_request *)&(a))
+
 static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
 {
        int status;
@@ -59,7 +74,6 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
        *flags = OCFS2_I(inode)->ip_attr;
        ocfs2_inode_unlock(inode, 0);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -125,7 +139,6 @@ bail:
 
        brelse(bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -139,7 +152,8 @@ int ocfs2_info_handle_blocksize(struct inode *inode,
                goto bail;
 
        oib.ib_blocksize = inode->i_sb->s_blocksize;
-       oib.ib_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       o2info_set_request_filled(oib);
 
        if (o2info_to_user(oib, req))
                goto bail;
@@ -163,7 +177,8 @@ int ocfs2_info_handle_clustersize(struct inode *inode,
                goto bail;
 
        oic.ic_clustersize = osb->s_clustersize;
-       oic.ic_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       o2info_set_request_filled(oic);
 
        if (o2info_to_user(oic, req))
                goto bail;
@@ -187,7 +202,8 @@ int ocfs2_info_handle_maxslots(struct inode *inode,
                goto bail;
 
        oim.im_max_slots = osb->max_slots;
-       oim.im_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       o2info_set_request_filled(oim);
 
        if (o2info_to_user(oim, req))
                goto bail;
@@ -211,7 +227,8 @@ int ocfs2_info_handle_label(struct inode *inode,
                goto bail;
 
        memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
-       oil.il_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       o2info_set_request_filled(oil);
 
        if (o2info_to_user(oil, req))
                goto bail;
@@ -235,7 +252,8 @@ int ocfs2_info_handle_uuid(struct inode *inode,
                goto bail;
 
        memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
-       oiu.iu_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       o2info_set_request_filled(oiu);
 
        if (o2info_to_user(oiu, req))
                goto bail;
@@ -261,7 +279,8 @@ int ocfs2_info_handle_fs_features(struct inode *inode,
        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;
+
+       o2info_set_request_filled(oif);
 
        if (o2info_to_user(oif, req))
                goto bail;
@@ -286,7 +305,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode,
 
        oij.ij_journal_size = osb->journal->j_inode->i_size;
 
-       oij.ij_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+       o2info_set_request_filled(oij);
 
        if (o2info_to_user(oij, req))
                goto bail;
@@ -308,7 +327,7 @@ int ocfs2_info_handle_unknown(struct inode *inode,
        if (o2info_from_user(oir, req))
                goto bail;
 
-       oir.ir_flags &= ~OCFS2_INFO_FL_FILLED;
+       o2info_clear_request_filled(oir);
 
        if (o2info_to_user(oir, req))
                goto bail;
index faa2303dbf0a4b5bd0b21a013abee4af82dda47f..dcc2d9327150a7285af56b4bf9645a1bd46bf9a3 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/time.h>
 #include <linux/random.h>
 
-#define MLOG_MASK_PREFIX ML_JOURNAL
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -52,6 +51,7 @@
 #include "quota.h"
 
 #include "buffer_head_io.h"
+#include "ocfs2_trace.h"
 
 DEFINE_SPINLOCK(trans_inc_lock);
 
@@ -303,16 +303,15 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
        unsigned int flushed;
        struct ocfs2_journal *journal = NULL;
 
-       mlog_entry_void();
-
        journal = osb->journal;
 
        /* Flush all pending commits and checkpoint the journal. */
        down_write(&journal->j_trans_barrier);
 
-       if (atomic_read(&journal->j_num_trans) == 0) {
+       flushed = atomic_read(&journal->j_num_trans);
+       trace_ocfs2_commit_cache_begin(flushed);
+       if (flushed == 0) {
                up_write(&journal->j_trans_barrier);
-               mlog(0, "No transactions for me to flush!\n");
                goto finally;
        }
 
@@ -331,13 +330,11 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
        atomic_set(&journal->j_num_trans, 0);
        up_write(&journal->j_trans_barrier);
 
-       mlog(0, "commit_thread: flushed transaction %lu (%u handles)\n",
-            journal->j_trans_id, flushed);
+       trace_ocfs2_commit_cache_end(journal->j_trans_id, flushed);
 
        ocfs2_wake_downconvert_thread(osb);
        wake_up(&journal->j_checkpointed);
 finally:
-       mlog_exit(status);
        return status;
 }
 
@@ -425,9 +422,8 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
                return 0;
 
        old_nblocks = handle->h_buffer_credits;
-       mlog_entry_void();
 
-       mlog(0, "Trying to extend transaction by %d blocks\n", nblocks);
+       trace_ocfs2_extend_trans(old_nblocks, nblocks);
 
 #ifdef CONFIG_OCFS2_DEBUG_FS
        status = 1;
@@ -440,9 +436,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
 #endif
 
        if (status > 0) {
-               mlog(0,
-                    "jbd2_journal_extend failed, trying "
-                    "jbd2_journal_restart\n");
+               trace_ocfs2_extend_trans_restart(old_nblocks + nblocks);
                status = jbd2_journal_restart(handle,
                                              old_nblocks + nblocks);
                if (status < 0) {
@@ -453,8 +447,6 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
 
        status = 0;
 bail:
-
-       mlog_exit(status);
        return status;
 }
 
@@ -622,12 +614,9 @@ static int __ocfs2_journal_access(handle_t *handle,
        BUG_ON(!handle);
        BUG_ON(!bh);
 
-       mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n",
-                  (unsigned long long)bh->b_blocknr, type,
-                  (type == OCFS2_JOURNAL_ACCESS_CREATE) ?
-                  "OCFS2_JOURNAL_ACCESS_CREATE" :
-                  "OCFS2_JOURNAL_ACCESS_WRITE",
-                  bh->b_size);
+       trace_ocfs2_journal_access(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)bh->b_blocknr, type, bh->b_size);
 
        /* we can safely remove this assertion after testing. */
        if (!buffer_uptodate(bh)) {
@@ -668,7 +657,6 @@ static int __ocfs2_journal_access(handle_t *handle,
                mlog(ML_ERROR, "Error %d getting %d access to buffer!\n",
                     status, type);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -737,13 +725,10 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh)
 {
        int status;
 
-       mlog_entry("(bh->b_blocknr=%llu)\n",
-                  (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_journal_dirty((unsigned long long)bh->b_blocknr);
 
        status = jbd2_journal_dirty_metadata(handle, bh);
        BUG_ON(status);
-
-       mlog_exit_void();
 }
 
 #define OCFS2_DEFAULT_COMMIT_INTERVAL  (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE)
@@ -775,8 +760,6 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
        struct ocfs2_super *osb;
        int inode_lock = 0;
 
-       mlog_entry_void();
-
        BUG_ON(!journal);
 
        osb = journal->j_osb;
@@ -820,10 +803,9 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
                goto done;
        }
 
-       mlog(0, "inode->i_size = %lld\n", inode->i_size);
-       mlog(0, "inode->i_blocks = %llu\n",
-                       (unsigned long long)inode->i_blocks);
-       mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters);
+       trace_ocfs2_journal_init(inode->i_size,
+                                (unsigned long long)inode->i_blocks,
+                                OCFS2_I(inode)->ip_clusters);
 
        /* call the kernels journal init function now */
        j_journal = jbd2_journal_init_inode(inode);
@@ -833,8 +815,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
                goto done;
        }
 
-       mlog(0, "Returned from jbd2_journal_init_inode\n");
-       mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen);
+       trace_ocfs2_journal_init_maxlen(j_journal->j_maxlen);
 
        *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) &
                  OCFS2_JOURNAL_DIRTY_FL);
@@ -859,7 +840,6 @@ done:
                }
        }
 
-       mlog_exit(status);
        return status;
 }
 
@@ -882,8 +862,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
        struct buffer_head *bh = journal->j_bh;
        struct ocfs2_dinode *fe;
 
-       mlog_entry_void();
-
        fe = (struct ocfs2_dinode *)bh->b_data;
 
        /* The journal bh on the osb always comes from ocfs2_journal_init()
@@ -906,7 +884,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
        if (status < 0)
                mlog_errno(status);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -921,8 +898,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
        struct inode *inode = NULL;
        int num_running_trans = 0;
 
-       mlog_entry_void();
-
        BUG_ON(!osb);
 
        journal = osb->journal;
@@ -939,10 +914,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
                BUG();
 
        num_running_trans = atomic_read(&(osb->journal->j_num_trans));
-       if (num_running_trans > 0)
-               mlog(0, "Shutting down journal: must wait on %d "
-                    "running transactions!\n",
-                    num_running_trans);
+       trace_ocfs2_journal_shutdown(num_running_trans);
 
        /* Do a commit_cache here. It will flush our journal, *and*
         * release any locks that are still held.
@@ -955,7 +927,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
         * completely destroy the journal. */
        if (osb->commit_task) {
                /* Wait for the commit thread */
-               mlog(0, "Waiting for ocfs2commit to exit....\n");
+               trace_ocfs2_journal_shutdown_wait(osb->commit_task);
                kthread_stop(osb->commit_task);
                osb->commit_task = NULL;
        }
@@ -998,7 +970,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
 done:
        if (inode)
                iput(inode);
-       mlog_exit_void();
 }
 
 static void ocfs2_clear_journal_error(struct super_block *sb,
@@ -1024,8 +995,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed)
        int status = 0;
        struct ocfs2_super *osb;
 
-       mlog_entry_void();
-
        BUG_ON(!journal);
 
        osb = journal->j_osb;
@@ -1059,7 +1028,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed)
                osb->commit_task = NULL;
 
 done:
-       mlog_exit(status);
        return status;
 }
 
@@ -1070,8 +1038,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full)
 {
        int status;
 
-       mlog_entry_void();
-
        BUG_ON(!journal);
 
        status = jbd2_journal_wipe(journal->j_journal, full);
@@ -1085,7 +1051,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full)
                mlog_errno(status);
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -1124,8 +1089,6 @@ static int ocfs2_force_read_journal(struct inode *inode)
 #define CONCURRENT_JOURNAL_FILL 32ULL
        struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL];
 
-       mlog_entry_void();
-
        memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL);
 
        num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size);
@@ -1161,7 +1124,6 @@ static int ocfs2_force_read_journal(struct inode *inode)
 bail:
        for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++)
                brelse(bhs[i]);
-       mlog_exit(status);
        return status;
 }
 
@@ -1185,7 +1147,7 @@ struct ocfs2_la_recovery_item {
  */
 void ocfs2_complete_recovery(struct work_struct *work)
 {
-       int ret;
+       int ret = 0;
        struct ocfs2_journal *journal =
                container_of(work, struct ocfs2_journal, j_recovery_work);
        struct ocfs2_super *osb = journal->j_osb;
@@ -1194,9 +1156,8 @@ void ocfs2_complete_recovery(struct work_struct *work)
        struct ocfs2_quota_recovery *qrec;
        LIST_HEAD(tmp_la_list);
 
-       mlog_entry_void();
-
-       mlog(0, "completing recovery from keventd\n");
+       trace_ocfs2_complete_recovery(
+               (unsigned long long)OCFS2_I(journal->j_inode)->ip_blkno);
 
        spin_lock(&journal->j_lock);
        list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
@@ -1205,15 +1166,18 @@ void ocfs2_complete_recovery(struct work_struct *work)
        list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
                list_del_init(&item->lri_list);
 
-               mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
-
                ocfs2_wait_on_quotas(osb);
 
                la_dinode = item->lri_la_dinode;
-               if (la_dinode) {
-                       mlog(0, "Clean up local alloc %llu\n",
-                            (unsigned long long)le64_to_cpu(la_dinode->i_blkno));
+               tl_dinode = item->lri_tl_dinode;
+               qrec = item->lri_qrec;
+
+               trace_ocfs2_complete_recovery_slot(item->lri_slot,
+                       la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0,
+                       tl_dinode ? le64_to_cpu(tl_dinode->i_blkno) : 0,
+                       qrec);
 
+               if (la_dinode) {
                        ret = ocfs2_complete_local_alloc_recovery(osb,
                                                                  la_dinode);
                        if (ret < 0)
@@ -1222,11 +1186,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
                        kfree(la_dinode);
                }
 
-               tl_dinode = item->lri_tl_dinode;
                if (tl_dinode) {
-                       mlog(0, "Clean up truncate log %llu\n",
-                            (unsigned long long)le64_to_cpu(tl_dinode->i_blkno));
-
                        ret = ocfs2_complete_truncate_log_recovery(osb,
                                                                   tl_dinode);
                        if (ret < 0)
@@ -1239,9 +1199,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
                if (ret < 0)
                        mlog_errno(ret);
 
-               qrec = item->lri_qrec;
                if (qrec) {
-                       mlog(0, "Recovering quota files");
                        ret = ocfs2_finish_quota_recovery(osb, qrec,
                                                          item->lri_slot);
                        if (ret < 0)
@@ -1252,8 +1210,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
                kfree(item);
        }
 
-       mlog(0, "Recovery completion\n");
-       mlog_exit_void();
+       trace_ocfs2_complete_recovery_end(ret);
 }
 
 /* NOTE: This function always eats your references to la_dinode and
@@ -1339,8 +1296,6 @@ static int __ocfs2_recovery_thread(void *arg)
        int rm_quota_used = 0, i;
        struct ocfs2_quota_recovery *qrec;
 
-       mlog_entry_void();
-
        status = ocfs2_wait_on_mount(osb);
        if (status < 0) {
                goto bail;
@@ -1372,15 +1327,12 @@ restart:
                 * clear it until ocfs2_recover_node() has succeeded. */
                node_num = rm->rm_entries[0];
                spin_unlock(&osb->osb_lock);
-               mlog(0, "checking node %d\n", node_num);
                slot_num = ocfs2_node_num_to_slot(osb, node_num);
+               trace_ocfs2_recovery_thread_node(node_num, slot_num);
                if (slot_num == -ENOENT) {
                        status = 0;
-                       mlog(0, "no slot for this node, so no recovery"
-                            "required.\n");
                        goto skip_recovery;
                }
-               mlog(0, "node %d was using slot %d\n", node_num, slot_num);
 
                /* It is a bit subtle with quota recovery. We cannot do it
                 * immediately because we have to obtain cluster locks from
@@ -1407,7 +1359,7 @@ skip_recovery:
                spin_lock(&osb->osb_lock);
        }
        spin_unlock(&osb->osb_lock);
-       mlog(0, "All nodes recovered\n");
+       trace_ocfs2_recovery_thread_end(status);
 
        /* Refresh all journal recovery generations from disk */
        status = ocfs2_check_journals_nolocks(osb);
@@ -1451,7 +1403,6 @@ bail:
        if (rm_quota)
                kfree(rm_quota);
 
-       mlog_exit(status);
        /* no one is callint kthread_stop() for us so the kthread() api
         * requires that we call do_exit().  And it isn't exported, but
         * complete_and_exit() seems to be a minimal wrapper around it. */
@@ -1461,19 +1412,15 @@ bail:
 
 void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
 {
-       mlog_entry("(node_num=%d, osb->node_num = %d)\n",
-                  node_num, osb->node_num);
-
        mutex_lock(&osb->recovery_lock);
-       if (osb->disable_recovery)
-               goto out;
 
-       /* People waiting on recovery will wait on
-        * the recovery map to empty. */
-       if (ocfs2_recovery_map_set(osb, node_num))
-               mlog(0, "node %d already in recovery map.\n", node_num);
+       trace_ocfs2_recovery_thread(node_num, osb->node_num,
+               osb->disable_recovery, osb->recovery_thread_task,
+               osb->disable_recovery ?
+               -1 : ocfs2_recovery_map_set(osb, node_num));
 
-       mlog(0, "starting recovery thread...\n");
+       if (osb->disable_recovery)
+               goto out;
 
        if (osb->recovery_thread_task)
                goto out;
@@ -1488,8 +1435,6 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
 out:
        mutex_unlock(&osb->recovery_lock);
        wake_up(&osb->recovery_event);
-
-       mlog_exit_void();
 }
 
 static int ocfs2_read_journal_inode(struct ocfs2_super *osb,
@@ -1563,7 +1508,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
         * If not, it needs recovery.
         */
        if (osb->slot_recovery_generations[slot_num] != slot_reco_gen) {
-               mlog(0, "Slot %u already recovered (old/new=%u/%u)\n", slot_num,
+               trace_ocfs2_replay_journal_recovered(slot_num,
                     osb->slot_recovery_generations[slot_num], slot_reco_gen);
                osb->slot_recovery_generations[slot_num] = slot_reco_gen;
                status = -EBUSY;
@@ -1574,7 +1519,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
 
        status = ocfs2_inode_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY);
        if (status < 0) {
-               mlog(0, "status returned from ocfs2_inode_lock=%d\n", status);
+               trace_ocfs2_replay_journal_lock_err(status);
                if (status != -ERESTARTSYS)
                        mlog(ML_ERROR, "Could not lock journal!\n");
                goto done;
@@ -1587,7 +1532,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        slot_reco_gen = ocfs2_get_recovery_generation(fe);
 
        if (!(flags & OCFS2_JOURNAL_DIRTY_FL)) {
-               mlog(0, "No recovery required for node %d\n", node_num);
+               trace_ocfs2_replay_journal_skip(node_num);
                /* Refresh recovery generation for the slot */
                osb->slot_recovery_generations[slot_num] = slot_reco_gen;
                goto done;
@@ -1608,7 +1553,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
                goto done;
        }
 
-       mlog(0, "calling journal_init_inode\n");
        journal = jbd2_journal_init_inode(inode);
        if (journal == NULL) {
                mlog(ML_ERROR, "Linux journal layer error\n");
@@ -1628,7 +1572,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        ocfs2_clear_journal_error(osb->sb, journal, slot_num);
 
        /* wipe the journal */
-       mlog(0, "flushing the journal.\n");
        jbd2_journal_lock_updates(journal);
        status = jbd2_journal_flush(journal);
        jbd2_journal_unlock_updates(journal);
@@ -1665,7 +1608,6 @@ done:
 
        brelse(bh);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1688,8 +1630,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
        struct ocfs2_dinode *la_copy = NULL;
        struct ocfs2_dinode *tl_copy = NULL;
 
-       mlog_entry("(node_num=%d, slot_num=%d, osb->node_num = %d)\n",
-                  node_num, slot_num, osb->node_num);
+       trace_ocfs2_recover_node(node_num, slot_num, osb->node_num);
 
        /* Should not ever be called to recover ourselves -- in that
         * case we should've called ocfs2_journal_load instead. */
@@ -1698,9 +1639,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
        status = ocfs2_replay_journal(osb, node_num, slot_num);
        if (status < 0) {
                if (status == -EBUSY) {
-                       mlog(0, "Skipping recovery for slot %u (node %u) "
-                            "as another node has recovered it\n", slot_num,
-                            node_num);
+                       trace_ocfs2_recover_node_skip(slot_num, node_num);
                        status = 0;
                        goto done;
                }
@@ -1735,7 +1674,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
        status = 0;
 done:
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1808,8 +1746,8 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
                spin_lock(&osb->osb_lock);
                osb->slot_recovery_generations[i] = gen;
 
-               mlog(0, "Slot %u recovery generation is %u\n", i,
-                    osb->slot_recovery_generations[i]);
+               trace_ocfs2_mark_dead_nodes(i,
+                                           osb->slot_recovery_generations[i]);
 
                if (i == osb->slot_num) {
                        spin_unlock(&osb->osb_lock);
@@ -1845,7 +1783,6 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
 
        status = 0;
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -1884,11 +1821,12 @@ 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;
 
+       trace_ocfs2_queue_orphan_scan_begin(os->os_count, os->os_seqno,
+                                           atomic_read(&os->os_state));
+
        status = ocfs2_orphan_scan_lock(osb, &seqno);
        if (status < 0) {
                if (status != -EAGAIN)
@@ -1918,7 +1856,8 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb)
 unlock:
        ocfs2_orphan_scan_unlock(osb, seqno);
 out:
-       mlog(0, "Orphan scan completed\n");
+       trace_ocfs2_queue_orphan_scan_end(os->os_count, os->os_seqno,
+                                         atomic_read(&os->os_state));
        return;
 }
 
@@ -2002,8 +1941,7 @@ static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len,
        if (IS_ERR(iter))
                return 0;
 
-       mlog(0, "queue orphan %llu\n",
-            (unsigned long long)OCFS2_I(iter)->ip_blkno);
+       trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno);
        /* No locking is required for the next_orphan queue as there
         * is only ever a single process doing orphan recovery. */
        OCFS2_I(iter)->ip_next_orphan = p->head;
@@ -2119,7 +2057,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
        struct inode *iter;
        struct ocfs2_inode_info *oi;
 
-       mlog(0, "Recover inodes from orphan dir in slot %d\n", slot);
+       trace_ocfs2_recover_orphans(slot);
 
        ocfs2_mark_recovering_orphan_dir(osb, slot);
        ret = ocfs2_queue_orphans(osb, slot, &inode);
@@ -2132,7 +2070,8 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
 
        while (inode) {
                oi = OCFS2_I(inode);
-               mlog(0, "iput orphan %llu\n", (unsigned long long)oi->ip_blkno);
+               trace_ocfs2_recover_orphans_iput(
+                                       (unsigned long long)oi->ip_blkno);
 
                iter = oi->ip_next_orphan;
 
@@ -2170,6 +2109,7 @@ static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota)
         * MOUNTED flag, but this is set right before
         * dismount_volume() so we can trust it. */
        if (atomic_read(&osb->vol_state) == VOLUME_DISABLED) {
+               trace_ocfs2_wait_on_mount(VOLUME_DISABLED);
                mlog(0, "mount error, exiting!\n");
                return -EBUSY;
        }
index ec6adbf8f5515afbaa7e8ffcb8a32b6a3c4e1ea8..210c35237548be82f9d99966beb166cdd2ffc87d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/highmem.h>
 #include <linux/bitops.h>
 
-#define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -43,6 +42,7 @@
 #include "suballoc.h"
 #include "super.h"
 #include "sysfile.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -201,8 +201,7 @@ void ocfs2_la_set_sizes(struct ocfs2_super *osb, int requested_mb)
        la_max_mb = ocfs2_clusters_to_megabytes(sb,
                                                ocfs2_local_alloc_size(sb) * 8);
 
-       mlog(0, "requested: %dM, max: %uM, default: %uM\n",
-            requested_mb, la_max_mb, la_default_mb);
+       trace_ocfs2_la_set_sizes(requested_mb, la_max_mb, la_default_mb);
 
        if (requested_mb == -1) {
                /* No user request - use defaults */
@@ -276,8 +275,8 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
 
        ret = 1;
 bail:
-       mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n",
-            osb->local_alloc_state, (unsigned long long)bits, la_bits, ret);
+       trace_ocfs2_alloc_should_use_local(
+            (unsigned long long)bits, osb->local_alloc_state, la_bits, ret);
        spin_unlock(&osb->osb_lock);
        return ret;
 }
@@ -291,8 +290,6 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
        struct inode *inode = NULL;
        struct ocfs2_local_alloc *la;
 
-       mlog_entry_void();
-
        if (osb->local_alloc_bits == 0)
                goto bail;
 
@@ -364,9 +361,10 @@ bail:
        if (inode)
                iput(inode);
 
-       mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits);
+       trace_ocfs2_load_local_alloc(osb->local_alloc_bits);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -388,8 +386,6 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
        struct ocfs2_dinode *alloc_copy = NULL;
        struct ocfs2_dinode *alloc = NULL;
 
-       mlog_entry_void();
-
        cancel_delayed_work(&osb->la_enable_wq);
        flush_workqueue(ocfs2_wq);
 
@@ -482,8 +478,6 @@ out:
 
        if (alloc_copy)
                kfree(alloc_copy);
-
-       mlog_exit_void();
 }
 
 /*
@@ -502,7 +496,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
        struct inode *inode = NULL;
        struct ocfs2_dinode *alloc;
 
-       mlog_entry("(slot_num = %d)\n", slot_num);
+       trace_ocfs2_begin_local_alloc_recovery(slot_num);
 
        *alloc_copy = NULL;
 
@@ -552,7 +546,8 @@ bail:
                iput(inode);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -570,8 +565,6 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
        struct buffer_head *main_bm_bh = NULL;
        struct inode *main_bm_inode;
 
-       mlog_entry_void();
-
        main_bm_inode = ocfs2_get_system_file_inode(osb,
                                                    GLOBAL_BITMAP_SYSTEM_INODE,
                                                    OCFS2_INVALID_SLOT);
@@ -620,7 +613,8 @@ out_mutex:
 out:
        if (!status)
                ocfs2_init_steal_slots(osb);
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -640,8 +634,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
        struct inode *local_alloc_inode;
        unsigned int free_bits;
 
-       mlog_entry_void();
-
        BUG_ON(!ac);
 
        local_alloc_inode =
@@ -712,10 +704,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
                        goto bail;
        }
 
-       if (ac->ac_max_block)
-               mlog(0, "Calling in_range for max block %llu\n",
-                    (unsigned long long)ac->ac_max_block);
-
        ac->ac_inode = local_alloc_inode;
        /* We should never use localalloc from another slot */
        ac->ac_alloc_slot = osb->slot_num;
@@ -729,10 +717,12 @@ bail:
                iput(local_alloc_inode);
        }
 
-       mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num,
-            status);
+       trace_ocfs2_reserve_local_alloc_bits(
+               (unsigned long long)ac->ac_max_block,
+               bits_wanted, osb->slot_num, status);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -749,7 +739,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
        struct ocfs2_dinode *alloc;
        struct ocfs2_local_alloc *la;
 
-       mlog_entry_void();
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
 
        local_alloc_inode = ac->ac_inode;
@@ -788,7 +777,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
        ocfs2_journal_dirty(handle, osb->local_alloc_bh);
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -799,13 +789,11 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
        u32 count = 0;
        struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
 
-       mlog_entry_void();
-
        buffer = la->la_bitmap;
        for (i = 0; i < le16_to_cpu(la->la_size); i++)
                count += hweight8(buffer[i]);
 
-       mlog_exit(count);
+       trace_ocfs2_local_alloc_count_bits(count);
        return count;
 }
 
@@ -820,10 +808,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
        void *bitmap = NULL;
        struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap;
 
-       mlog_entry("(numbits wanted = %u)\n", *numbits);
-
        if (!alloc->id1.bitmap1.i_total) {
-               mlog(0, "No bits in my window!\n");
                bitoff = -1;
                goto bail;
        }
@@ -883,8 +868,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
                }
        }
 
-       mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff,
-            numfound);
+       trace_ocfs2_local_alloc_find_clear_bits_search_bitmap(bitoff, numfound);
 
        if (numfound == *numbits)
                bitoff = startoff - numfound;
@@ -895,7 +879,10 @@ bail:
        if (local_resv)
                ocfs2_resv_discard(resmap, resv);
 
-       mlog_exit(bitoff);
+       trace_ocfs2_local_alloc_find_clear_bits(*numbits,
+               le32_to_cpu(alloc->id1.bitmap1.i_total),
+               bitoff, numfound);
+
        return bitoff;
 }
 
@@ -903,15 +890,12 @@ static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc)
 {
        struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
        int i;
-       mlog_entry_void();
 
        alloc->id1.bitmap1.i_total = 0;
        alloc->id1.bitmap1.i_used = 0;
        la->la_bm_off = 0;
        for(i = 0; i < le16_to_cpu(la->la_size); i++)
                la->la_bitmap[i] = 0;
-
-       mlog_exit_void();
 }
 
 #if 0
@@ -952,18 +936,16 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
        void *bitmap;
        struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
 
-       mlog_entry("total = %u, used = %u\n",
-                  le32_to_cpu(alloc->id1.bitmap1.i_total),
-                  le32_to_cpu(alloc->id1.bitmap1.i_used));
+       trace_ocfs2_sync_local_to_main(
+            le32_to_cpu(alloc->id1.bitmap1.i_total),
+            le32_to_cpu(alloc->id1.bitmap1.i_used));
 
        if (!alloc->id1.bitmap1.i_total) {
-               mlog(0, "nothing to sync!\n");
                goto bail;
        }
 
        if (le32_to_cpu(alloc->id1.bitmap1.i_used) ==
            le32_to_cpu(alloc->id1.bitmap1.i_total)) {
-               mlog(0, "all bits were taken!\n");
                goto bail;
        }
 
@@ -985,8 +967,7 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
                                ocfs2_clusters_to_blocks(osb->sb,
                                                         start - count);
 
-                       mlog(0, "freeing %u bits starting at local alloc bit "
-                            "%u (la_start_blk = %llu, blkno = %llu)\n",
+                       trace_ocfs2_sync_local_to_main_free(
                             count, start - count,
                             (unsigned long long)la_start_blk,
                             (unsigned long long)blkno);
@@ -1007,7 +988,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
        }
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1132,7 +1114,8 @@ bail:
                *ac = NULL;
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1148,17 +1131,12 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
        struct ocfs2_dinode *alloc = NULL;
        struct ocfs2_local_alloc *la;
 
-       mlog_entry_void();
-
        alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
        la = OCFS2_LOCAL_ALLOC(alloc);
 
-       if (alloc->id1.bitmap1.i_total)
-               mlog(0, "asking me to alloc a new window over a non-empty "
-                    "one\n");
-
-       mlog(0, "Allocating %u clusters for a new window.\n",
-            osb->local_alloc_bits);
+       trace_ocfs2_local_alloc_new_window(
+               le32_to_cpu(alloc->id1.bitmap1.i_total),
+               osb->local_alloc_bits);
 
        /* Instruct the allocation code to try the most recently used
         * cluster group. We'll re-record the group used this pass
@@ -1220,13 +1198,13 @@ retry_enospc:
        ocfs2_resmap_restart(&osb->osb_la_resmap, cluster_count,
                             OCFS2_LOCAL_ALLOC(alloc)->la_bitmap);
 
-       mlog(0, "New window allocated:\n");
-       mlog(0, "window la_bm_off = %u\n",
-            OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
-       mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total));
+       trace_ocfs2_local_alloc_new_window_result(
+               OCFS2_LOCAL_ALLOC(alloc)->la_bm_off,
+               le32_to_cpu(alloc->id1.bitmap1.i_total));
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1243,8 +1221,6 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
        struct ocfs2_dinode *alloc_copy = NULL;
        struct ocfs2_alloc_context *ac = NULL;
 
-       mlog_entry_void();
-
        ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_SLIDE);
 
        /* This will lock the main bitmap for us. */
@@ -1324,7 +1300,8 @@ bail:
        if (ac)
                ocfs2_free_alloc_context(ac);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
index b5cb3ede9408944d99abc7c7c3b28c01b1ddadeb..e57c804069ea6487c0a8eba6d203f88ccd8dd39a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/fs.h>
 #include <linux/fcntl.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
index 7e32db9c2c993b38e67f5d1282525f0a089b54b0..3e9393ca39ebd823772ae910cda1b4516d46fa62 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/signal.h>
 #include <linux/rbtree.h>
 
-#define MLOG_MASK_PREFIX ML_FILE_IO
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -42,6 +41,7 @@
 #include "inode.h"
 #include "mmap.h"
 #include "super.h"
+#include "ocfs2_trace.h"
 
 
 static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
@@ -49,13 +49,12 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
        sigset_t oldset;
        int ret;
 
-       mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff);
-
        ocfs2_block_signals(&oldset);
        ret = filemap_fault(area, vmf);
        ocfs2_unblock_signals(&oldset);
 
-       mlog_exit_ptr(vmf->page);
+       trace_ocfs2_fault(OCFS2_I(area->vm_file->f_mapping->host)->ip_blkno,
+                         area, vmf->page, vmf->pgoff);
        return ret;
 }
 
index d6c25d76b537df58a92796b4258ccb2d83c523e2..28f2cc1080d8b16da36e4dee718d44f3690943c0 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/highmem.h>
 #include <linux/quotaops.h>
 
-#define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -63,6 +62,7 @@
 #include "uptodate.h"
 #include "xattr.h"
 #include "acl.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -106,17 +106,15 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *ret;
        struct ocfs2_inode_info *oi;
 
-       mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_lookup(dir, dentry, dentry->d_name.len,
+                          dentry->d_name.name,
+                          (unsigned long long)OCFS2_I(dir)->ip_blkno, 0);
 
        if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) {
                ret = ERR_PTR(-ENAMETOOLONG);
                goto bail;
        }
 
-       mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
-            dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
-
        status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT);
        if (status < 0) {
                if (status != -ENOENT)
@@ -182,7 +180,7 @@ bail_unlock:
 
 bail:
 
-       mlog_exit_ptr(ret);
+       trace_ocfs2_lookup_ret(ret);
 
        return ret;
 }
@@ -235,9 +233,9 @@ static int ocfs2_mknod(struct inode *dir,
        sigset_t oldset;
        int did_block_signals = 0;
 
-       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
-                  (unsigned long)dev, dentry->d_name.len,
-                  dentry->d_name.name);
+       trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
+                         (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                         (unsigned long)dev, mode);
 
        dquot_initialize(dir);
 
@@ -354,10 +352,6 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        did_quota_inode = 1;
 
-       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
-                  inode->i_mode, (unsigned long)dev, dentry->d_name.len,
-                  dentry->d_name.name);
-
        /* do the real work now. */
        status = ocfs2_mknod_locked(osb, dir, inode, dev,
                                    &new_fe_bh, parent_fe_bh, handle,
@@ -436,9 +430,6 @@ leave:
        if (did_block_signals)
                ocfs2_unblock_signals(&oldset);
 
-       if (status == -ENOSPC)
-               mlog(0, "Disk is full\n");
-
        brelse(new_fe_bh);
        brelse(parent_fe_bh);
        kfree(si.name);
@@ -466,7 +457,8 @@ leave:
                iput(inode);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
@@ -577,7 +569,8 @@ leave:
                }
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -615,10 +608,11 @@ static int ocfs2_mkdir(struct inode *dir,
 {
        int ret;
 
-       mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_mkdir(dir, dentry, dentry->d_name.len, dentry->d_name.name,
+                         OCFS2_I(dir)->ip_blkno, mode);
        ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0);
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
 
        return ret;
 }
@@ -630,10 +624,11 @@ static int ocfs2_create(struct inode *dir,
 {
        int ret;
 
-       mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_create(dir, dentry, dentry->d_name.len, dentry->d_name.name,
+                          (unsigned long long)OCFS2_I(dir)->ip_blkno, mode);
        ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0);
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
 
        return ret;
 }
@@ -652,9 +647,9 @@ static int ocfs2_link(struct dentry *old_dentry,
        struct ocfs2_dir_lookup_result lookup = { NULL, };
        sigset_t oldset;
 
-       mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino,
-                  old_dentry->d_name.len, old_dentry->d_name.name,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                        old_dentry->d_name.len, old_dentry->d_name.name,
+                        dentry->d_name.len, dentry->d_name.name);
 
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
@@ -757,7 +752,8 @@ out:
 
        ocfs2_free_dir_lookup_result(&lookup);
 
-       mlog_exit(err);
+       if (err)
+               mlog_errno(err);
 
        return err;
 }
@@ -809,19 +805,17 @@ static int ocfs2_unlink(struct inode *dir,
        struct ocfs2_dir_lookup_result lookup = { NULL, };
        struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
 
-       mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_unlink(dir, dentry, dentry->d_name.len,
+                          dentry->d_name.name,
+                          (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                          (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        dquot_initialize(dir);
 
        BUG_ON(dentry->d_parent->d_inode != dir);
 
-       mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
-
-       if (inode == osb->root_inode) {
-               mlog(0, "Cannot delete the root directory\n");
+       if (inode == osb->root_inode)
                return -EPERM;
-       }
 
        status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1,
                                         OI_LS_PARENT);
@@ -843,9 +837,10 @@ static int ocfs2_unlink(struct inode *dir,
        if (OCFS2_I(inode)->ip_blkno != blkno) {
                status = -ENOENT;
 
-               mlog(0, "ip_blkno %llu != dirent blkno %llu ip_flags = %x\n",
-                    (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                    (unsigned long long)blkno, OCFS2_I(inode)->ip_flags);
+               trace_ocfs2_unlink_noent(
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                               (unsigned long long)blkno,
+                               OCFS2_I(inode)->ip_flags);
                goto leave;
        }
 
@@ -954,7 +949,8 @@ leave:
        ocfs2_free_dir_lookup_result(&orphan_insert);
        ocfs2_free_dir_lookup_result(&lookup);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
@@ -975,9 +971,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
        struct buffer_head **tmpbh;
        struct inode *tmpinode;
 
-       mlog_entry("(inode1 = %llu, inode2 = %llu)\n",
-                  (unsigned long long)oi1->ip_blkno,
-                  (unsigned long long)oi2->ip_blkno);
+       trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno,
+                               (unsigned long long)oi2->ip_blkno);
 
        if (*bh1)
                *bh1 = NULL;
@@ -988,7 +983,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
        if (oi1->ip_blkno != oi2->ip_blkno) {
                if (oi1->ip_blkno < oi2->ip_blkno) {
                        /* switch id1 and id2 around */
-                       mlog(0, "switching them around...\n");
                        tmpbh = bh2;
                        bh2 = bh1;
                        bh1 = tmpbh;
@@ -1024,8 +1018,13 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
                        mlog_errno(status);
        }
 
+       trace_ocfs2_double_lock_end(
+                       (unsigned long long)OCFS2_I(inode1)->ip_blkno,
+                       (unsigned long long)OCFS2_I(inode2)->ip_blkno);
+
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1067,10 +1066,9 @@ static int ocfs2_rename(struct inode *old_dir,
        /* At some point it might be nice to break this function up a
         * bit. */
 
-       mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n",
-                  old_dir, old_dentry, new_dir, new_dentry,
-                  old_dentry->d_name.len, old_dentry->d_name.name,
-                  new_dentry->d_name.len, new_dentry->d_name.name);
+       trace_ocfs2_rename(old_dir, old_dentry, new_dir, new_dentry,
+                          old_dentry->d_name.len, old_dentry->d_name.name,
+                          new_dentry->d_name.len, new_dentry->d_name.name);
 
        dquot_initialize(old_dir);
        dquot_initialize(new_dir);
@@ -1227,16 +1225,15 @@ static int ocfs2_rename(struct inode *old_dir,
                if (!new_inode) {
                        status = -EACCES;
 
-                       mlog(0, "We found an inode for name %.*s but VFS "
-                            "didn't give us one.\n", new_dentry->d_name.len,
-                            new_dentry->d_name.name);
+                       trace_ocfs2_rename_target_exists(new_dentry->d_name.len,
+                                               new_dentry->d_name.name);
                        goto bail;
                }
 
                if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) {
                        status = -EACCES;
 
-                       mlog(0, "Inode %llu and dir %llu disagree. flags = %x\n",
+                       trace_ocfs2_rename_disagree(
                             (unsigned long long)OCFS2_I(new_inode)->ip_blkno,
                             (unsigned long long)newfe_blkno,
                             OCFS2_I(new_inode)->ip_flags);
@@ -1259,8 +1256,7 @@ static int ocfs2_rename(struct inode *old_dir,
 
                newfe = (struct ocfs2_dinode *) newfe_bh->b_data;
 
-               mlog(0, "aha rename over existing... new_blkno=%llu "
-                    "newfebh=%p bhblocknr=%llu\n",
+               trace_ocfs2_rename_over_existing(
                     (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ?
                     (unsigned long long)newfe_bh->b_blocknr : 0ULL);
 
@@ -1476,7 +1472,8 @@ bail:
        brelse(old_dir_bh);
        brelse(new_dir_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
@@ -1501,9 +1498,8 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
         * write i_size + 1 bytes. */
        blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 
-       mlog_entry("i_blocks = %llu, i_size = %llu, blocks = %d\n",
-                       (unsigned long long)inode->i_blocks,
-                       i_size_read(inode), blocks);
+       trace_ocfs2_create_symlink_data((unsigned long long)inode->i_blocks,
+                                       i_size_read(inode), blocks);
 
        /* Sanity check -- make sure we're going to fit. */
        if (bytes_left >
@@ -1579,7 +1575,8 @@ bail:
                kfree(bhs);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1610,8 +1607,8 @@ static int ocfs2_symlink(struct inode *dir,
        sigset_t oldset;
        int did_block_signals = 0;
 
-       mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
-                  dentry, symname, dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_symlink_begin(dir, dentry, symname,
+                                 dentry->d_name.len, dentry->d_name.name);
 
        dquot_initialize(dir);
 
@@ -1713,9 +1710,10 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        did_quota_inode = 1;
 
-       mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry,
-                  inode->i_mode, dentry->d_name.len,
-                  dentry->d_name.name);
+       trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len,
+                                  dentry->d_name.name,
+                                  (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                                  inode->i_mode);
 
        status = ocfs2_mknod_locked(osb, dir, inode,
                                    0, &new_fe_bh, parent_fe_bh, handle,
@@ -1835,7 +1833,8 @@ bail:
                iput(inode);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
@@ -1844,8 +1843,6 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name)
 {
        int status, namelen;
 
-       mlog_entry_void();
-
        namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx",
                           (long long)blkno);
        if (namelen <= 0) {
@@ -1862,12 +1859,12 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name)
                goto bail;
        }
 
-       mlog(0, "built filename '%s' for orphan dir (len=%d)\n", name,
-            namelen);
+       trace_ocfs2_blkno_stringify(blkno, name, namelen);
 
        status = 0;
 bail:
-       mlog_exit(status);
+       if (status < 0)
+               mlog_errno(status);
        return status;
 }
 
@@ -1980,7 +1977,8 @@ out:
                iput(orphan_dir_inode);
        }
 
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
        return ret;
 }
 
@@ -1997,7 +1995,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
        struct ocfs2_dinode *orphan_fe;
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
-       mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
+       trace_ocfs2_orphan_add_begin(
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh);
        if (status < 0) {
@@ -2056,13 +2055,14 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        ocfs2_journal_dirty(handle, fe_bh);
 
-       mlog(0, "Inode %llu orphaned in slot %d\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
+       trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                  osb->slot_num);
 
 leave:
        brelse(orphan_dir_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2078,17 +2078,15 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        int status = 0;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 
-       mlog_entry_void();
-
        status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       mlog(0, "removing '%s' from orphan dir %llu (namelen=%d)\n",
-            name, (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
-            OCFS2_ORPHAN_NAMELEN);
+       trace_ocfs2_orphan_del(
+            (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
+            name, OCFS2_ORPHAN_NAMELEN);
 
        /* find it's spot in the orphan directory */
        status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode,
@@ -2124,7 +2122,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
 leave:
        ocfs2_free_dir_lookup_result(&lookup);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2321,9 +2320,6 @@ leave:
                iput(orphan_dir);
        }
 
-       if (status == -ENOSPC)
-               mlog(0, "Disk is full\n");
-
        if ((status < 0) && inode) {
                clear_nlink(inode);
                iput(inode);
@@ -2358,8 +2354,10 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
        struct buffer_head *di_bh = NULL;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 
-       mlog_entry("(0x%p, 0x%p, %.*s')\n", dir, dentry,
-                  dentry->d_name.len, dentry->d_name.name);
+       trace_ocfs2_mv_orphaned_inode_to_new(dir, dentry,
+                               dentry->d_name.len, dentry->d_name.name,
+                               (unsigned long long)OCFS2_I(dir)->ip_blkno,
+                               (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        status = ocfs2_inode_lock(dir, &parent_di_bh, 1);
        if (status < 0) {
@@ -2476,7 +2474,8 @@ leave:
 
        ocfs2_free_dir_lookup_result(&lookup);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
index 1a97ba1ec3fc286550d6e325d144996d64a3d1ca..409285854f647e2357223bc7a8d24c36b376a6bb 100644 (file)
@@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops;
 
 typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
 
+#ifdef CONFIG_OCFS2_FS_STATS
+struct ocfs2_lock_stats {
+       u64             ls_total;       /* Total wait in NSEC */
+       u32             ls_gets;        /* Num acquires */
+       u32             ls_fail;        /* Num failed acquires */
+
+       /* Storing max wait in usecs saves 24 bytes per inode */
+       u32             ls_max;         /* Max wait in USEC */
+};
+#endif
+
 struct ocfs2_lock_res {
        void                    *l_priv;
        struct ocfs2_lock_res_ops *l_ops;
@@ -182,15 +193,9 @@ struct ocfs2_lock_res {
        struct list_head         l_debug_list;
 
 #ifdef CONFIG_OCFS2_FS_STATS
-       unsigned long long       l_lock_num_prmode;        /* PR acquires */
-       unsigned long long       l_lock_num_exmode;        /* EX acquires */
-       unsigned int             l_lock_num_prmode_failed; /* Failed PR gets */
-       unsigned int             l_lock_num_exmode_failed; /* Failed EX gets */
-       unsigned long long       l_lock_total_prmode;      /* Tot wait for PR */
-       unsigned long long       l_lock_total_exmode;      /* Tot wait for EX */
-       unsigned int             l_lock_max_prmode;        /* Max wait for PR */
-       unsigned int             l_lock_max_exmode;        /* Max wait for EX */
-       unsigned int             l_lock_refresh;           /* Disk refreshes */
+       struct ocfs2_lock_stats  l_lock_prmode;         /* PR mode stats */
+       u32                      l_lock_refresh;        /* Disk refreshes */
+       struct ocfs2_lock_stats  l_lock_exmode;         /* EX mode stats */
 #endif
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map       l_lockdep_map;
diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h
new file mode 100644 (file)
index 0000000..a1dae5b
--- /dev/null
@@ -0,0 +1,2739 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ocfs2
+
+#if !defined(_TRACE_OCFS2_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_OCFS2_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(ocfs2__int,
+       TP_PROTO(int num),
+       TP_ARGS(num),
+       TP_STRUCT__entry(
+               __field(int, num)
+       ),
+       TP_fast_assign(
+               __entry->num = num;
+       ),
+       TP_printk("%d", __entry->num)
+);
+
+#define DEFINE_OCFS2_INT_EVENT(name)   \
+DEFINE_EVENT(ocfs2__int, name, \
+       TP_PROTO(int num),      \
+       TP_ARGS(num))
+
+DECLARE_EVENT_CLASS(ocfs2__uint,
+       TP_PROTO(unsigned int num),
+       TP_ARGS(num),
+       TP_STRUCT__entry(
+               __field(        unsigned int,   num             )
+       ),
+       TP_fast_assign(
+               __entry->num    =       num;
+       ),
+       TP_printk("%u", __entry->num)
+);
+
+#define DEFINE_OCFS2_UINT_EVENT(name)  \
+DEFINE_EVENT(ocfs2__uint, name,        \
+       TP_PROTO(unsigned int num),     \
+       TP_ARGS(num))
+
+DECLARE_EVENT_CLASS(ocfs2__ull,
+       TP_PROTO(unsigned long long blkno),
+       TP_ARGS(blkno),
+       TP_STRUCT__entry(
+               __field(unsigned long long, blkno)
+       ),
+       TP_fast_assign(
+               __entry->blkno = blkno;
+       ),
+       TP_printk("%llu", __entry->blkno)
+);
+
+#define DEFINE_OCFS2_ULL_EVENT(name)   \
+DEFINE_EVENT(ocfs2__ull, name, \
+       TP_PROTO(unsigned long long num),       \
+       TP_ARGS(num))
+
+DECLARE_EVENT_CLASS(ocfs2__pointer,
+       TP_PROTO(void *pointer),
+       TP_ARGS(pointer),
+       TP_STRUCT__entry(
+               __field(void *, pointer)
+       ),
+       TP_fast_assign(
+               __entry->pointer = pointer;
+       ),
+       TP_printk("%p", __entry->pointer)
+);
+
+#define DEFINE_OCFS2_POINTER_EVENT(name)       \
+DEFINE_EVENT(ocfs2__pointer, name,     \
+       TP_PROTO(void *pointer),        \
+       TP_ARGS(pointer))
+
+DECLARE_EVENT_CLASS(ocfs2__string,
+       TP_PROTO(const char *name),
+       TP_ARGS(name),
+       TP_STRUCT__entry(
+               __string(name,name)
+       ),
+       TP_fast_assign(
+               __assign_str(name, name);
+       ),
+       TP_printk("%s", __get_str(name))
+);
+
+#define DEFINE_OCFS2_STRING_EVENT(name)        \
+DEFINE_EVENT(ocfs2__string, name,      \
+       TP_PROTO(const char *name),     \
+       TP_ARGS(name))
+
+DECLARE_EVENT_CLASS(ocfs2__int_int,
+       TP_PROTO(int value1, int value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(int, value1)
+               __field(int, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%d %d", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_INT_INT_EVENT(name)       \
+DEFINE_EVENT(ocfs2__int_int, name,     \
+       TP_PROTO(int val1, int val2),   \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__uint_int,
+       TP_PROTO(unsigned int value1, int value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned int, value1)
+               __field(int, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%u %d", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_UINT_INT_EVENT(name)      \
+DEFINE_EVENT(ocfs2__uint_int, name,    \
+       TP_PROTO(unsigned int val1, int val2),  \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__uint_uint,
+       TP_PROTO(unsigned int value1, unsigned int value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned int, value1)
+               __field(unsigned int, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%u %u", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_UINT_UINT_EVENT(name)     \
+DEFINE_EVENT(ocfs2__uint_uint, name,   \
+       TP_PROTO(unsigned int val1, unsigned int val2), \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_uint,
+       TP_PROTO(unsigned long long value1, unsigned int value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned int, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%llu %u", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_ULL_UINT_EVENT(name)      \
+DEFINE_EVENT(ocfs2__ull_uint, name,    \
+       TP_PROTO(unsigned long long val1, unsigned int val2),   \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_int,
+       TP_PROTO(unsigned long long value1, int value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(int, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%llu %d", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_ULL_INT_EVENT(name)       \
+DEFINE_EVENT(ocfs2__ull_int, name,     \
+       TP_PROTO(unsigned long long val1, int val2),    \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_ull,
+       TP_PROTO(unsigned long long value1, unsigned long long value2),
+       TP_ARGS(value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned long long, value2)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%llu %llu", __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_ULL_ULL_EVENT(name)       \
+DEFINE_EVENT(ocfs2__ull_ull, name,     \
+       TP_PROTO(unsigned long long val1, unsigned long long val2),     \
+       TP_ARGS(val1, val2))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint,
+       TP_PROTO(unsigned long long value1,
+                unsigned long long value2, unsigned int value3),
+       TP_ARGS(value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned long long, value2)
+               __field(unsigned int, value3)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+               __entry->value3 = value3;
+       ),
+       TP_printk("%llu %llu %u",
+                 __entry->value1, __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_ULL_ULL_UINT_EVENT(name)  \
+DEFINE_EVENT(ocfs2__ull_ull_uint, name,        \
+       TP_PROTO(unsigned long long val1,       \
+                unsigned long long val2, unsigned int val3),   \
+       TP_ARGS(val1, val2, val3))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint,
+       TP_PROTO(unsigned long long value1,
+                unsigned int value2, unsigned int value3),
+       TP_ARGS(value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned int, value2)
+               __field(unsigned int, value3)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+               __entry->value3 = value3;
+       ),
+       TP_printk("%llu %u %u", __entry->value1,
+                 __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_ULL_UINT_UINT_EVENT(name) \
+DEFINE_EVENT(ocfs2__ull_uint_uint, name,       \
+       TP_PROTO(unsigned long long val1,       \
+                unsigned int val2, unsigned int val3), \
+       TP_ARGS(val1, val2, val3))
+
+DECLARE_EVENT_CLASS(ocfs2__uint_uint_uint,
+       TP_PROTO(unsigned int value1, unsigned int value2,
+                unsigned int value3),
+       TP_ARGS(value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(        unsigned int,   value1          )
+               __field(        unsigned int,   value2          )
+               __field(        unsigned int,   value3          )
+       ),
+       TP_fast_assign(
+               __entry->value1 =       value1;
+               __entry->value2 =       value2;
+               __entry->value3 =       value3;
+       ),
+       TP_printk("%u %u %u", __entry->value1, __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_UINT_UINT_UINT_EVENT(name)        \
+DEFINE_EVENT(ocfs2__uint_uint_uint, name,      \
+       TP_PROTO(unsigned int value1, unsigned int value2,      \
+                unsigned int value3),  \
+       TP_ARGS(value1, value2, value3))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_ull_ull,
+       TP_PROTO(unsigned long long value1,
+                unsigned long long value2, unsigned long long value3),
+       TP_ARGS(value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned long long, value2)
+               __field(unsigned long long, value3)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+               __entry->value3 = value3;
+       ),
+       TP_printk("%llu %llu %llu",
+                 __entry->value1, __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_ULL_ULL_ULL_EVENT(name)   \
+DEFINE_EVENT(ocfs2__ull_ull_ull, name, \
+       TP_PROTO(unsigned long long value1, unsigned long long value2,  \
+                unsigned long long value3),    \
+       TP_ARGS(value1, value2, value3))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_int_int_int,
+       TP_PROTO(unsigned long long ull, int value1, int value2, int value3),
+       TP_ARGS(ull, value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(        unsigned long long,     ull     )
+               __field(        int,    value1                  )
+               __field(        int,    value2                  )
+               __field(        int,    value3                  )
+       ),
+       TP_fast_assign(
+               __entry->ull            = ull;
+               __entry->value1         = value1;
+               __entry->value2         = value2;
+               __entry->value3         = value3;
+       ),
+       TP_printk("%llu %d %d %d",
+                 __entry->ull, __entry->value1,
+                 __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(name)       \
+DEFINE_EVENT(ocfs2__ull_int_int_int, name,     \
+       TP_PROTO(unsigned long long ull, int value1,    \
+                int value2, int value3),       \
+       TP_ARGS(ull, value1, value2, value3))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint_uint,
+       TP_PROTO(unsigned long long ull, unsigned int value1,
+                unsigned int value2, unsigned int value3),
+       TP_ARGS(ull, value1, value2, value3),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ull)
+               __field(unsigned int, value1)
+               __field(unsigned int, value2)
+               __field(unsigned int, value3)
+       ),
+       TP_fast_assign(
+               __entry->ull = ull;
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+               __entry->value3 = value3;
+       ),
+       TP_printk("%llu %u %u %u",
+                 __entry->ull, __entry->value1,
+                 __entry->value2, __entry->value3)
+);
+
+#define DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(name)    \
+DEFINE_EVENT(ocfs2__ull_uint_uint_uint, name,  \
+       TP_PROTO(unsigned long long ull, unsigned int value1,   \
+                unsigned int value2, unsigned int value3),     \
+       TP_ARGS(ull, value1, value2, value3))
+
+DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint_uint,
+       TP_PROTO(unsigned long long value1, unsigned long long value2,
+                unsigned int value3, unsigned int value4),
+       TP_ARGS(value1, value2, value3, value4),
+       TP_STRUCT__entry(
+               __field(unsigned long long, value1)
+               __field(unsigned long long, value2)
+               __field(unsigned int, value3)
+               __field(unsigned int, value4)
+       ),
+       TP_fast_assign(
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+               __entry->value3 = value3;
+               __entry->value4 = value4;
+       ),
+       TP_printk("%llu %llu %u %u",
+                 __entry->value1, __entry->value2,
+                 __entry->value3, __entry->value4)
+);
+
+#define DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(name)     \
+DEFINE_EVENT(ocfs2__ull_ull_uint_uint, name,   \
+       TP_PROTO(unsigned long long ull, unsigned long long ull1,       \
+                unsigned int value2, unsigned int value3),     \
+       TP_ARGS(ull, ull1, value2, value3))
+
+/* Trace events for fs/ocfs2/alloc.c. */
+DECLARE_EVENT_CLASS(ocfs2__btree_ops,
+       TP_PROTO(unsigned long long owner,\
+                unsigned int value1, unsigned int value2),
+       TP_ARGS(owner, value1, value2),
+       TP_STRUCT__entry(
+               __field(unsigned long long, owner)
+               __field(unsigned int, value1)
+               __field(unsigned int, value2)
+       ),
+       TP_fast_assign(
+               __entry->owner = owner;
+               __entry->value1 = value1;
+               __entry->value2 = value2;
+       ),
+       TP_printk("%llu %u %u",
+                 __entry->owner, __entry->value1, __entry->value2)
+);
+
+#define DEFINE_OCFS2_BTREE_EVENT(name) \
+DEFINE_EVENT(ocfs2__btree_ops, name,   \
+       TP_PROTO(unsigned long long owner,      \
+                unsigned int value1, unsigned int value2),     \
+       TP_ARGS(owner, value1, value2))
+
+DEFINE_OCFS2_BTREE_EVENT(ocfs2_adjust_rightmost_branch);
+
+DEFINE_OCFS2_BTREE_EVENT(ocfs2_rotate_tree_right);
+
+DEFINE_OCFS2_BTREE_EVENT(ocfs2_append_rec_to_path);
+
+DEFINE_OCFS2_BTREE_EVENT(ocfs2_insert_extent_start);
+
+DEFINE_OCFS2_BTREE_EVENT(ocfs2_add_clusters_in_btree);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_num_free_extents);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_complete_edge_insert);
+
+TRACE_EVENT(ocfs2_grow_tree,
+       TP_PROTO(unsigned long long owner, int depth),
+       TP_ARGS(owner, depth),
+       TP_STRUCT__entry(
+               __field(unsigned long long, owner)
+               __field(int, depth)
+       ),
+       TP_fast_assign(
+               __entry->owner = owner;
+               __entry->depth = depth;
+       ),
+       TP_printk("%llu %d", __entry->owner, __entry->depth)
+);
+
+TRACE_EVENT(ocfs2_rotate_subtree,
+       TP_PROTO(int subtree_root, unsigned long long blkno,
+                int depth),
+       TP_ARGS(subtree_root, blkno, depth),
+       TP_STRUCT__entry(
+               __field(int, subtree_root)
+               __field(unsigned long long, blkno)
+               __field(int, depth)
+       ),
+       TP_fast_assign(
+               __entry->subtree_root = subtree_root;
+               __entry->blkno = blkno;
+               __entry->depth = depth;
+       ),
+       TP_printk("%d %llu %d", __entry->subtree_root,
+                 __entry->blkno, __entry->depth)
+);
+
+TRACE_EVENT(ocfs2_insert_extent,
+       TP_PROTO(unsigned int ins_appending, unsigned int ins_contig,
+                int ins_contig_index, int free_records, int ins_tree_depth),
+       TP_ARGS(ins_appending, ins_contig, ins_contig_index, free_records,
+               ins_tree_depth),
+       TP_STRUCT__entry(
+               __field(unsigned int, ins_appending)
+               __field(unsigned int, ins_contig)
+               __field(int, ins_contig_index)
+               __field(int, free_records)
+               __field(int, ins_tree_depth)
+       ),
+       TP_fast_assign(
+               __entry->ins_appending = ins_appending;
+               __entry->ins_contig = ins_contig;
+               __entry->ins_contig_index = ins_contig_index;
+               __entry->free_records = free_records;
+               __entry->ins_tree_depth = ins_tree_depth;
+       ),
+       TP_printk("%u %u %d %d %d",
+                 __entry->ins_appending, __entry->ins_contig,
+                 __entry->ins_contig_index, __entry->free_records,
+                 __entry->ins_tree_depth)
+);
+
+TRACE_EVENT(ocfs2_split_extent,
+       TP_PROTO(int split_index, unsigned int c_contig_type,
+                unsigned int c_has_empty_extent,
+                unsigned int c_split_covers_rec),
+       TP_ARGS(split_index, c_contig_type,
+               c_has_empty_extent, c_split_covers_rec),
+       TP_STRUCT__entry(
+               __field(int, split_index)
+               __field(unsigned int, c_contig_type)
+               __field(unsigned int, c_has_empty_extent)
+               __field(unsigned int, c_split_covers_rec)
+       ),
+       TP_fast_assign(
+               __entry->split_index = split_index;
+               __entry->c_contig_type = c_contig_type;
+               __entry->c_has_empty_extent = c_has_empty_extent;
+               __entry->c_split_covers_rec = c_split_covers_rec;
+       ),
+       TP_printk("%d %u %u %u", __entry->split_index, __entry->c_contig_type,
+                 __entry->c_has_empty_extent, __entry->c_split_covers_rec)
+);
+
+TRACE_EVENT(ocfs2_remove_extent,
+       TP_PROTO(unsigned long long owner, unsigned int cpos,
+                unsigned int len, int index,
+                unsigned int e_cpos, unsigned int clusters),
+       TP_ARGS(owner, cpos, len, index, e_cpos, clusters),
+       TP_STRUCT__entry(
+               __field(unsigned long long, owner)
+               __field(unsigned int, cpos)
+               __field(unsigned int, len)
+               __field(int, index)
+               __field(unsigned int, e_cpos)
+               __field(unsigned int, clusters)
+       ),
+       TP_fast_assign(
+               __entry->owner = owner;
+               __entry->cpos = cpos;
+               __entry->len = len;
+               __entry->index = index;
+               __entry->e_cpos = e_cpos;
+               __entry->clusters = clusters;
+       ),
+       TP_printk("%llu %u %u %d %u %u",
+                 __entry->owner, __entry->cpos, __entry->len, __entry->index,
+                 __entry->e_cpos, __entry->clusters)
+);
+
+TRACE_EVENT(ocfs2_commit_truncate,
+       TP_PROTO(unsigned long long ino, unsigned int new_cpos,
+                unsigned int clusters, unsigned int depth),
+       TP_ARGS(ino, new_cpos, clusters, depth),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, new_cpos)
+               __field(unsigned int, clusters)
+               __field(unsigned int, depth)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->new_cpos = new_cpos;
+               __entry->clusters = clusters;
+               __entry->depth = depth;
+       ),
+       TP_printk("%llu %u %u %u",
+                 __entry->ino, __entry->new_cpos,
+                 __entry->clusters, __entry->depth)
+);
+
+TRACE_EVENT(ocfs2_validate_extent_block,
+       TP_PROTO(unsigned long long blkno),
+       TP_ARGS(blkno),
+       TP_STRUCT__entry(
+               __field(unsigned long long, blkno)
+       ),
+       TP_fast_assign(
+               __entry->blkno = blkno;
+       ),
+       TP_printk("%llu ", __entry->blkno)
+);
+
+TRACE_EVENT(ocfs2_rotate_leaf,
+       TP_PROTO(unsigned int insert_cpos, int insert_index,
+                int has_empty, int next_free,
+                unsigned int l_count),
+       TP_ARGS(insert_cpos, insert_index, has_empty,
+               next_free, l_count),
+       TP_STRUCT__entry(
+               __field(unsigned int, insert_cpos)
+               __field(int, insert_index)
+               __field(int, has_empty)
+               __field(int, next_free)
+               __field(unsigned int, l_count)
+       ),
+       TP_fast_assign(
+               __entry->insert_cpos = insert_cpos;
+               __entry->insert_index = insert_index;
+               __entry->has_empty = has_empty;
+               __entry->next_free = next_free;
+               __entry->l_count = l_count;
+       ),
+       TP_printk("%u %d %d %d %u", __entry->insert_cpos,
+                 __entry->insert_index, __entry->has_empty,
+                 __entry->next_free, __entry->l_count)
+);
+
+TRACE_EVENT(ocfs2_add_clusters_in_btree_ret,
+       TP_PROTO(int status, int reason, int err),
+       TP_ARGS(status, reason, err),
+       TP_STRUCT__entry(
+               __field(int, status)
+               __field(int, reason)
+               __field(int, err)
+       ),
+       TP_fast_assign(
+               __entry->status = status;
+               __entry->reason = reason;
+               __entry->err = err;
+       ),
+       TP_printk("%d %d %d", __entry->status,
+                 __entry->reason, __entry->err)
+);
+
+TRACE_EVENT(ocfs2_mark_extent_written,
+       TP_PROTO(unsigned long long owner, unsigned int cpos,
+                unsigned int len, unsigned int phys),
+       TP_ARGS(owner, cpos, len, phys),
+       TP_STRUCT__entry(
+               __field(unsigned long long, owner)
+               __field(unsigned int, cpos)
+               __field(unsigned int, len)
+               __field(unsigned int, phys)
+       ),
+       TP_fast_assign(
+               __entry->owner = owner;
+               __entry->cpos = cpos;
+               __entry->len = len;
+               __entry->phys = phys;
+       ),
+       TP_printk("%llu %u %u %u",
+                 __entry->owner, __entry->cpos,
+                 __entry->len, __entry->phys)
+);
+
+DECLARE_EVENT_CLASS(ocfs2__truncate_log_ops,
+       TP_PROTO(unsigned long long blkno, int index,
+                unsigned int start, unsigned int num),
+       TP_ARGS(blkno, index, start, num),
+       TP_STRUCT__entry(
+               __field(unsigned long long, blkno)
+               __field(int, index)
+               __field(unsigned int, start)
+               __field(unsigned int, num)
+       ),
+       TP_fast_assign(
+               __entry->blkno = blkno;
+               __entry->index = index;
+               __entry->start = start;
+               __entry->num = num;
+       ),
+       TP_printk("%llu %d %u %u",
+                 __entry->blkno, __entry->index,
+                 __entry->start, __entry->num)
+);
+
+#define DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(name)      \
+DEFINE_EVENT(ocfs2__truncate_log_ops, name,    \
+       TP_PROTO(unsigned long long blkno, int index,   \
+                unsigned int start, unsigned int num), \
+       TP_ARGS(blkno, index, start, num))
+
+DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_truncate_log_append);
+
+DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_replay_truncate_records);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_flush_truncate_log);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_begin_truncate_log_recovery);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_truncate_log_recovery_num);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_complete_truncate_log_recovery);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_free_cached_blocks);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_cache_cluster_dealloc);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_run_deallocs);
+
+TRACE_EVENT(ocfs2_cache_block_dealloc,
+       TP_PROTO(int type, int slot, unsigned long long suballoc,
+                unsigned long long blkno, unsigned int bit),
+       TP_ARGS(type, slot, suballoc, blkno, bit),
+       TP_STRUCT__entry(
+               __field(int, type)
+               __field(int, slot)
+               __field(unsigned long long, suballoc)
+               __field(unsigned long long, blkno)
+               __field(unsigned int, bit)
+       ),
+       TP_fast_assign(
+               __entry->type = type;
+               __entry->slot = slot;
+               __entry->suballoc = suballoc;
+               __entry->blkno = blkno;
+               __entry->bit = bit;
+       ),
+       TP_printk("%d %d %llu %llu %u",
+                 __entry->type, __entry->slot, __entry->suballoc,
+                 __entry->blkno, __entry->bit)
+);
+
+/* End of trace events for fs/ocfs2/alloc.c. */
+
+/* Trace events for fs/ocfs2/localalloc.c. */
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_la_set_sizes);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_alloc_should_use_local);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_load_local_alloc);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_begin_local_alloc_recovery);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_reserve_local_alloc_bits);
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_local_alloc_count_bits);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits_search_bitmap);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_sync_local_to_main);
+
+TRACE_EVENT(ocfs2_sync_local_to_main_free,
+       TP_PROTO(int count, int bit, unsigned long long start_blk,
+                unsigned long long blkno),
+       TP_ARGS(count, bit, start_blk, blkno),
+       TP_STRUCT__entry(
+               __field(int, count)
+               __field(int, bit)
+               __field(unsigned long long, start_blk)
+               __field(unsigned long long, blkno)
+       ),
+       TP_fast_assign(
+               __entry->count = count;
+               __entry->bit = bit;
+               __entry->start_blk = start_blk;
+               __entry->blkno = blkno;
+       ),
+       TP_printk("%d %d %llu %llu",
+                 __entry->count, __entry->bit, __entry->start_blk,
+                 __entry->blkno)
+);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_new_window);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result);
+
+/* End of trace events for fs/ocfs2/localalloc.c. */
+
+/* Trace events for fs/ocfs2/resize.c. */
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_update_last_group_and_inode);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_group_extend);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_group_add);
+
+/* End of trace events for fs/ocfs2/resize.c. */
+
+/* Trace events for fs/ocfs2/suballoc.c. */
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_group_descriptor);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_contig);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_discontig);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_block_group_alloc);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_nospc);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_no_new_group);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_reserve_new_inode_new_group);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_set_bits);
+
+TRACE_EVENT(ocfs2_relink_block_group,
+       TP_PROTO(unsigned long long i_blkno, unsigned int chain,
+                unsigned long long bg_blkno,
+                unsigned long long prev_blkno),
+       TP_ARGS(i_blkno, chain, bg_blkno, prev_blkno),
+       TP_STRUCT__entry(
+               __field(unsigned long long, i_blkno)
+               __field(unsigned int, chain)
+               __field(unsigned long long, bg_blkno)
+               __field(unsigned long long, prev_blkno)
+       ),
+       TP_fast_assign(
+               __entry->i_blkno = i_blkno;
+               __entry->chain = chain;
+               __entry->bg_blkno = bg_blkno;
+               __entry->prev_blkno = prev_blkno;
+       ),
+       TP_printk("%llu %u %llu %llu",
+                 __entry->i_blkno, __entry->chain, __entry->bg_blkno,
+                 __entry->prev_blkno)
+);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_cluster_group_search_wrong_max_bits);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cluster_group_search_max_block);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_block_group_search_max_block);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_search_chain_begin);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_succ);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_end);
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_claim_suballoc_bits);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_claim_new_inode_at_loc);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_clear_bits);
+
+TRACE_EVENT(ocfs2_free_suballoc_bits,
+       TP_PROTO(unsigned long long inode, unsigned long long group,
+                unsigned int start_bit, unsigned int count),
+       TP_ARGS(inode, group, start_bit, count),
+       TP_STRUCT__entry(
+               __field(unsigned long long, inode)
+               __field(unsigned long long, group)
+               __field(unsigned int, start_bit)
+               __field(unsigned int, count)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->group = group;
+               __entry->start_bit = start_bit;
+               __entry->count = count;
+       ),
+       TP_printk("%llu %llu %u %u", __entry->inode, __entry->group,
+                 __entry->start_bit, __entry->count)
+);
+
+TRACE_EVENT(ocfs2_free_clusters,
+       TP_PROTO(unsigned long long bg_blkno, unsigned long long start_blk,
+                unsigned int start_bit, unsigned int count),
+       TP_ARGS(bg_blkno, start_blk, start_bit, count),
+       TP_STRUCT__entry(
+               __field(unsigned long long, bg_blkno)
+               __field(unsigned long long, start_blk)
+               __field(unsigned int, start_bit)
+               __field(unsigned int, count)
+       ),
+       TP_fast_assign(
+               __entry->bg_blkno = bg_blkno;
+               __entry->start_blk = start_blk;
+               __entry->start_bit = start_bit;
+               __entry->count = count;
+       ),
+       TP_printk("%llu %llu %u %u", __entry->bg_blkno, __entry->start_blk,
+                 __entry->start_bit, __entry->count)
+);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_get_suballoc_slot_bit);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_test_suballoc_bit);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_test_inode_bit);
+
+/* End of trace events for fs/ocfs2/suballoc.c. */
+
+/* Trace events for fs/ocfs2/refcounttree.c. */
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_refcount_block);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_refcount_trees);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree_blkno);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_change_refcount_rec);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_expand_inline_ref_root);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_divide_leaf_refcount_block);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_new_leaf_refcount_block);
+
+DECLARE_EVENT_CLASS(ocfs2__refcount_tree_ops,
+       TP_PROTO(unsigned long long blkno, int index,
+                unsigned long long cpos,
+                unsigned int clusters, unsigned int refcount),
+       TP_ARGS(blkno, index, cpos, clusters, refcount),
+       TP_STRUCT__entry(
+               __field(unsigned long long, blkno)
+               __field(int, index)
+               __field(unsigned long long, cpos)
+               __field(unsigned int, clusters)
+               __field(unsigned int, refcount)
+       ),
+       TP_fast_assign(
+               __entry->blkno = blkno;
+               __entry->index = index;
+               __entry->cpos = cpos;
+               __entry->clusters = clusters;
+               __entry->refcount = refcount;
+       ),
+       TP_printk("%llu %d %llu %u %u", __entry->blkno, __entry->index,
+                 __entry->cpos, __entry->clusters, __entry->refcount)
+);
+
+#define DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(name)     \
+DEFINE_EVENT(ocfs2__refcount_tree_ops, name,           \
+       TP_PROTO(unsigned long long blkno, int index,   \
+                unsigned long long cpos,               \
+                unsigned int count, unsigned int refcount),    \
+       TP_ARGS(blkno, index, cpos, count, refcount))
+
+DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_insert_refcount_rec);
+
+TRACE_EVENT(ocfs2_split_refcount_rec,
+       TP_PROTO(unsigned long long cpos,
+                unsigned int clusters, unsigned int refcount,
+                unsigned long long split_cpos,
+                unsigned int split_clusters, unsigned int split_refcount),
+       TP_ARGS(cpos, clusters, refcount,
+               split_cpos, split_clusters, split_refcount),
+       TP_STRUCT__entry(
+               __field(unsigned long long, cpos)
+               __field(unsigned int, clusters)
+               __field(unsigned int, refcount)
+               __field(unsigned long long, split_cpos)
+               __field(unsigned int, split_clusters)
+               __field(unsigned int, split_refcount)
+       ),
+       TP_fast_assign(
+               __entry->cpos = cpos;
+               __entry->clusters = clusters;
+               __entry->refcount = refcount;
+               __entry->split_cpos = split_cpos;
+               __entry->split_clusters = split_clusters;
+               __entry->split_refcount = split_refcount;
+       ),
+       TP_printk("%llu %u %u %llu %u %u",
+                 __entry->cpos, __entry->clusters, __entry->refcount,
+                 __entry->split_cpos, __entry->split_clusters,
+                 __entry->split_refcount)
+);
+
+DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_split_refcount_rec_insert);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_increase_refcount_begin);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_change);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_increase_refcount_insert);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_split);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_remove_refcount_extent);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_restore_refcount_block);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_decrease_refcount_rec);
+
+TRACE_EVENT(ocfs2_decrease_refcount,
+       TP_PROTO(unsigned long long owner,
+                unsigned long long cpos,
+                unsigned int len, int delete),
+       TP_ARGS(owner, cpos, len, delete),
+       TP_STRUCT__entry(
+               __field(unsigned long long, owner)
+               __field(unsigned long long, cpos)
+               __field(unsigned int, len)
+               __field(int, delete)
+       ),
+       TP_fast_assign(
+               __entry->owner = owner;
+               __entry->cpos = cpos;
+               __entry->len = len;
+               __entry->delete = delete;
+       ),
+       TP_printk("%llu %llu %u %d",
+                 __entry->owner, __entry->cpos, __entry->len, __entry->delete)
+);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_mark_extent_refcounted);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_calc_refcount_meta_credits);
+
+TRACE_EVENT(ocfs2_calc_refcount_meta_credits_iterate,
+       TP_PROTO(int recs_add, unsigned long long cpos,
+                unsigned int clusters, unsigned long long r_cpos,
+                unsigned int r_clusters, unsigned int refcount, int index),
+       TP_ARGS(recs_add, cpos, clusters, r_cpos, r_clusters, refcount, index),
+       TP_STRUCT__entry(
+               __field(int, recs_add)
+               __field(unsigned long long, cpos)
+               __field(unsigned int, clusters)
+               __field(unsigned long long, r_cpos)
+               __field(unsigned int, r_clusters)
+               __field(unsigned int, refcount)
+               __field(int, index)
+       ),
+       TP_fast_assign(
+               __entry->recs_add = recs_add;
+               __entry->cpos = cpos;
+               __entry->clusters = clusters;
+               __entry->r_cpos = r_cpos;
+               __entry->r_clusters = r_clusters;
+               __entry->refcount = refcount;
+               __entry->index = index;
+       ),
+       TP_printk("%d %llu %u %llu %u %u %d",
+                 __entry->recs_add, __entry->cpos, __entry->clusters,
+                 __entry->r_cpos, __entry->r_clusters,
+                 __entry->refcount, __entry->index)
+);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_add_refcount_flag);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_prepare_refcount_change_for_del);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_lock_refcount_allocators);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_page);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_jbd);
+
+TRACE_EVENT(ocfs2_clear_ext_refcount,
+       TP_PROTO(unsigned long long ino, unsigned int cpos,
+                unsigned int len, unsigned int p_cluster,
+                unsigned int ext_flags),
+       TP_ARGS(ino, cpos, len, p_cluster, ext_flags),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, cpos)
+               __field(unsigned int, len)
+               __field(unsigned int, p_cluster)
+               __field(unsigned int, ext_flags)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->cpos = cpos;
+               __entry->len = len;
+               __entry->p_cluster = p_cluster;
+               __entry->ext_flags = ext_flags;
+       ),
+       TP_printk("%llu %u %u %u %u",
+                 __entry->ino, __entry->cpos, __entry->len,
+                 __entry->p_cluster, __entry->ext_flags)
+);
+
+TRACE_EVENT(ocfs2_replace_clusters,
+       TP_PROTO(unsigned long long ino, unsigned int cpos,
+                unsigned int old, unsigned int new, unsigned int len,
+                unsigned int ext_flags),
+       TP_ARGS(ino, cpos, old, new, len, ext_flags),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, cpos)
+               __field(unsigned int, old)
+               __field(unsigned int, new)
+               __field(unsigned int, len)
+               __field(unsigned int, ext_flags)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->cpos = cpos;
+               __entry->old = old;
+               __entry->new = new;
+               __entry->len = len;
+               __entry->ext_flags = ext_flags;
+       ),
+       TP_printk("%llu %u %u %u %u %u",
+                 __entry->ino, __entry->cpos, __entry->old, __entry->new,
+                 __entry->len, __entry->ext_flags)
+);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_make_clusters_writable);
+
+TRACE_EVENT(ocfs2_refcount_cow_hunk,
+       TP_PROTO(unsigned long long ino, unsigned int cpos,
+                unsigned int write_len, unsigned int max_cpos,
+                unsigned int cow_start, unsigned int cow_len),
+       TP_ARGS(ino, cpos, write_len, max_cpos, cow_start, cow_len),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, cpos)
+               __field(unsigned int, write_len)
+               __field(unsigned int, max_cpos)
+               __field(unsigned int, cow_start)
+               __field(unsigned int, cow_len)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->cpos = cpos;
+               __entry->write_len = write_len;
+               __entry->max_cpos = max_cpos;
+               __entry->cow_start = cow_start;
+               __entry->cow_len = cow_len;
+       ),
+       TP_printk("%llu %u %u %u %u %u",
+                 __entry->ino, __entry->cpos, __entry->write_len,
+                 __entry->max_cpos, __entry->cow_start, __entry->cow_len)
+);
+
+/* End of trace events for fs/ocfs2/refcounttree.c. */
+
+/* Trace events for fs/ocfs2/aops.c. */
+
+DECLARE_EVENT_CLASS(ocfs2__get_block,
+       TP_PROTO(unsigned long long ino, unsigned long long iblock,
+                void *bh_result, int create),
+       TP_ARGS(ino, iblock, bh_result, create),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned long long, iblock)
+               __field(void *, bh_result)
+               __field(int, create)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->iblock = iblock;
+               __entry->bh_result = bh_result;
+               __entry->create = create;
+       ),
+       TP_printk("%llu %llu %p %d",
+                 __entry->ino, __entry->iblock,
+                 __entry->bh_result, __entry->create)
+);
+
+#define DEFINE_OCFS2_GET_BLOCK_EVENT(name)     \
+DEFINE_EVENT(ocfs2__get_block, name,   \
+       TP_PROTO(unsigned long long ino, unsigned long long iblock,     \
+                void *bh_result, int create),  \
+       TP_ARGS(ino, iblock, bh_result, create))
+
+DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_symlink_get_block);
+
+DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_get_block);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_get_block_end);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_readpage);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_writepage);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_bmap);
+
+TRACE_EVENT(ocfs2_try_to_write_inline_data,
+       TP_PROTO(unsigned long long ino, unsigned int len,
+                unsigned long long pos, unsigned int flags),
+       TP_ARGS(ino, len, pos, flags),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, len)
+               __field(unsigned long long, pos)
+               __field(unsigned int, flags)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->len = len;
+               __entry->pos = pos;
+               __entry->flags = flags;
+       ),
+       TP_printk("%llu %u %llu 0x%x",
+                 __entry->ino, __entry->len, __entry->pos, __entry->flags)
+);
+
+TRACE_EVENT(ocfs2_write_begin_nolock,
+       TP_PROTO(unsigned long long ino,
+                long long i_size, unsigned int i_clusters,
+                unsigned long long pos, unsigned int len,
+                unsigned int flags, void *page,
+                unsigned int clusters, unsigned int extents_to_split),
+       TP_ARGS(ino, i_size, i_clusters, pos, len, flags,
+               page, clusters, extents_to_split),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(long long, i_size)
+               __field(unsigned int, i_clusters)
+               __field(unsigned long long, pos)
+               __field(unsigned int, len)
+               __field(unsigned int, flags)
+               __field(void *, page)
+               __field(unsigned int, clusters)
+               __field(unsigned int, extents_to_split)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->i_size = i_size;
+               __entry->i_clusters = i_clusters;
+               __entry->pos = pos;
+               __entry->len = len;
+               __entry->flags = flags;
+               __entry->page = page;
+               __entry->clusters = clusters;
+               __entry->extents_to_split = extents_to_split;
+       ),
+       TP_printk("%llu %lld %u %llu %u %u %p %u %u",
+                 __entry->ino, __entry->i_size, __entry->i_clusters,
+                 __entry->pos, __entry->len,
+                 __entry->flags, __entry->page, __entry->clusters,
+                 __entry->extents_to_split)
+);
+
+TRACE_EVENT(ocfs2_write_end_inline,
+       TP_PROTO(unsigned long long ino,
+                unsigned long long pos, unsigned int copied,
+                unsigned int id_count, unsigned int features),
+       TP_ARGS(ino, pos, copied, id_count, features),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned long long, pos)
+               __field(unsigned int, copied)
+               __field(unsigned int, id_count)
+               __field(unsigned int, features)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->pos = pos;
+               __entry->copied = copied;
+               __entry->id_count = id_count;
+               __entry->features = features;
+       ),
+       TP_printk("%llu %llu %u %u %u",
+                 __entry->ino, __entry->pos, __entry->copied,
+                 __entry->id_count, __entry->features)
+);
+
+/* End of trace events for fs/ocfs2/aops.c. */
+
+/* Trace events for fs/ocfs2/mmap.c. */
+
+TRACE_EVENT(ocfs2_fault,
+       TP_PROTO(unsigned long long ino,
+                void *area, void *page, unsigned long pgoff),
+       TP_ARGS(ino, area, page, pgoff),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(void *, area)
+               __field(void *, page)
+               __field(unsigned long, pgoff)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->area = area;
+               __entry->page = page;
+               __entry->pgoff = pgoff;
+       ),
+       TP_printk("%llu %p %p %lu",
+                 __entry->ino, __entry->area, __entry->page, __entry->pgoff)
+);
+
+/* End of trace events for fs/ocfs2/mmap.c. */
+
+/* Trace events for fs/ocfs2/file.c. */
+
+DECLARE_EVENT_CLASS(ocfs2__file_ops,
+       TP_PROTO(void *inode, void *file, void *dentry,
+                unsigned long long ino,
+                unsigned int d_len, const unsigned char *d_name,
+                unsigned long long para),
+       TP_ARGS(inode, file, dentry, ino, d_len, d_name, para),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(void *, file)
+               __field(void *, dentry)
+               __field(unsigned long long, ino)
+               __field(unsigned int, d_len)
+               __string(d_name, d_name)
+               __field(unsigned long long, para)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->file = file;
+               __entry->dentry = dentry;
+               __entry->ino = ino;
+               __entry->d_len = d_len;
+               __assign_str(d_name, d_name);
+               __entry->para = para;
+       ),
+       TP_printk("%p %p %p %llu %llu %.*s", __entry->inode, __entry->file,
+                 __entry->dentry, __entry->ino, __entry->para,
+                 __entry->d_len, __get_str(d_name))
+);
+
+#define DEFINE_OCFS2_FILE_OPS(name)                            \
+DEFINE_EVENT(ocfs2__file_ops, name,                            \
+TP_PROTO(void *inode, void *file, void *dentry,                        \
+        unsigned long long ino,                                \
+        unsigned int d_len, const unsigned char *d_name,       \
+        unsigned long long mode),                              \
+       TP_ARGS(inode, file, dentry, ino, d_len, d_name, mode))
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_open);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_release);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_sync_file);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_write);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read);
+
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_read);
+
+DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_truncate_file_error);
+
+TRACE_EVENT(ocfs2_extend_allocation,
+       TP_PROTO(unsigned long long ip_blkno, unsigned long long size,
+                unsigned int clusters, unsigned int clusters_to_add,
+                int why, int restart_func),
+       TP_ARGS(ip_blkno, size, clusters, clusters_to_add, why, restart_func),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ip_blkno)
+               __field(unsigned long long, size)
+               __field(unsigned int, clusters)
+               __field(unsigned int, clusters_to_add)
+               __field(int, why)
+               __field(int, restart_func)
+       ),
+       TP_fast_assign(
+               __entry->ip_blkno = ip_blkno;
+               __entry->size = size;
+               __entry->clusters = clusters;
+               __entry->clusters_to_add = clusters_to_add;
+               __entry->why = why;
+               __entry->restart_func = restart_func;
+       ),
+       TP_printk("%llu %llu %u %u %d %d",
+                 __entry->ip_blkno, __entry->size, __entry->clusters,
+                 __entry->clusters_to_add, __entry->why, __entry->restart_func)
+);
+
+TRACE_EVENT(ocfs2_extend_allocation_end,
+       TP_PROTO(unsigned long long ino,
+                unsigned int di_clusters, unsigned long long di_size,
+                unsigned int ip_clusters, unsigned long long i_size),
+       TP_ARGS(ino, di_clusters, di_size, ip_clusters, i_size),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, di_clusters)
+               __field(unsigned long long, di_size)
+               __field(unsigned int, ip_clusters)
+               __field(unsigned long long, i_size)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->di_clusters = di_clusters;
+               __entry->di_size = di_size;
+               __entry->ip_clusters = ip_clusters;
+               __entry->i_size = i_size;
+       ),
+       TP_printk("%llu %u %llu %u %llu", __entry->ino, __entry->di_clusters,
+                 __entry->di_size, __entry->ip_clusters, __entry->i_size)
+);
+
+TRACE_EVENT(ocfs2_write_zero_page,
+       TP_PROTO(unsigned long long ino,
+                unsigned long long abs_from, unsigned long long abs_to,
+                unsigned long index, unsigned int zero_from,
+                unsigned int zero_to),
+       TP_ARGS(ino, abs_from, abs_to, index, zero_from, zero_to),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned long long, abs_from)
+               __field(unsigned long long, abs_to)
+               __field(unsigned long, index)
+               __field(unsigned int, zero_from)
+               __field(unsigned int, zero_to)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->abs_from = abs_from;
+               __entry->abs_to = abs_to;
+               __entry->index = index;
+               __entry->zero_from = zero_from;
+               __entry->zero_to = zero_to;
+       ),
+       TP_printk("%llu %llu %llu %lu %u %u", __entry->ino,
+                 __entry->abs_from, __entry->abs_to,
+                 __entry->index, __entry->zero_from, __entry->zero_to)
+);
+
+DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend_range);
+
+DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend);
+
+TRACE_EVENT(ocfs2_setattr,
+       TP_PROTO(void *inode, void *dentry,
+                unsigned long long ino,
+                unsigned int d_len, const unsigned char *d_name,
+                unsigned int ia_valid, unsigned int ia_mode,
+                unsigned int ia_uid, unsigned int ia_gid),
+       TP_ARGS(inode, dentry, ino, d_len, d_name,
+               ia_valid, ia_mode, ia_uid, ia_gid),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(void *, dentry)
+               __field(unsigned long long, ino)
+               __field(unsigned int, d_len)
+               __string(d_name, d_name)
+               __field(unsigned int, ia_valid)
+               __field(unsigned int, ia_mode)
+               __field(unsigned int, ia_uid)
+               __field(unsigned int, ia_gid)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->dentry = dentry;
+               __entry->ino = ino;
+               __entry->d_len = d_len;
+               __assign_str(d_name, d_name);
+               __entry->ia_valid = ia_valid;
+               __entry->ia_mode = ia_mode;
+               __entry->ia_uid = ia_uid;
+               __entry->ia_gid = ia_gid;
+       ),
+       TP_printk("%p %p %llu %.*s %u %u %u %u", __entry->inode,
+                 __entry->dentry, __entry->ino, __entry->d_len,
+                 __get_str(d_name), __entry->ia_valid, __entry->ia_mode,
+                 __entry->ia_uid, __entry->ia_gid)
+);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_write_remove_suid);
+
+DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_partial_clusters);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range1);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range2);
+
+DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_remove_inode_range);
+
+TRACE_EVENT(ocfs2_prepare_inode_for_write,
+       TP_PROTO(unsigned long long ino, unsigned long long saved_pos,
+                int appending, unsigned long count,
+                int *direct_io, int *has_refcount),
+       TP_ARGS(ino, saved_pos, appending, count, direct_io, has_refcount),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned long long, saved_pos)
+               __field(int, appending)
+               __field(unsigned long, count)
+               __field(int, direct_io)
+               __field(int, has_refcount)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->saved_pos = saved_pos;
+               __entry->appending = appending;
+               __entry->count = count;
+               __entry->direct_io = direct_io ? *direct_io : -1;
+               __entry->has_refcount = has_refcount ? *has_refcount : -1;
+       ),
+       TP_printk("%llu %llu %d %lu %d %d", __entry->ino,
+                 __entry->saved_pos, __entry->appending, __entry->count,
+                 __entry->direct_io, __entry->has_refcount)
+);
+
+DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret);
+
+/* End of trace events for fs/ocfs2/file.c. */
+
+/* Trace events for fs/ocfs2/inode.c. */
+
+TRACE_EVENT(ocfs2_iget_begin,
+       TP_PROTO(unsigned long long ino, unsigned int flags, int sysfile_type),
+       TP_ARGS(ino, flags, sysfile_type),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(unsigned int, flags)
+               __field(int, sysfile_type)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->flags = flags;
+               __entry->sysfile_type = sysfile_type;
+       ),
+       TP_printk("%llu %u %d", __entry->ino,
+                 __entry->flags, __entry->sysfile_type)
+);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_iget5_locked);
+
+TRACE_EVENT(ocfs2_iget_end,
+       TP_PROTO(void *inode, unsigned long long ino),
+       TP_ARGS(inode, ino),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(unsigned long long, ino)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->ino = ino;
+       ),
+       TP_printk("%p %llu", __entry->inode, __entry->ino)
+);
+
+TRACE_EVENT(ocfs2_find_actor,
+       TP_PROTO(void *inode, unsigned long long ino,
+                void *args,  unsigned long long fi_blkno),
+       TP_ARGS(inode, ino, args, fi_blkno),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(unsigned long long, ino)
+               __field(void *, args)
+               __field(unsigned long long, fi_blkno)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->ino = ino;
+               __entry->args = args;
+               __entry->fi_blkno = fi_blkno;
+       ),
+       TP_printk("%p %llu %p %llu", __entry->inode, __entry->ino,
+                 __entry->args, __entry->fi_blkno)
+);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_populate_inode);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_read_locked_inode);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_check_orphan_recovery_state);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_inode_block);
+
+TRACE_EVENT(ocfs2_inode_is_valid_to_delete,
+       TP_PROTO(void *task, void *dc_task, unsigned long long ino,
+                unsigned int flags),
+       TP_ARGS(task, dc_task, ino, flags),
+       TP_STRUCT__entry(
+               __field(void *, task)
+               __field(void *, dc_task)
+               __field(unsigned long long, ino)
+               __field(unsigned int, flags)
+       ),
+       TP_fast_assign(
+               __entry->task = task;
+               __entry->dc_task = dc_task;
+               __entry->ino = ino;
+               __entry->flags = flags;
+       ),
+       TP_printk("%p %p %llu %u", __entry->task, __entry->dc_task,
+                 __entry->ino, __entry->flags)
+);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_query_inode_wipe_begin);
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_query_inode_wipe_succ);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_query_inode_wipe_end);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_cleanup_delete_inode);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_delete_inode);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_clear_inode);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_drop_inode);
+
+TRACE_EVENT(ocfs2_inode_revalidate,
+       TP_PROTO(void *inode, unsigned long long ino,
+                unsigned int flags),
+       TP_ARGS(inode, ino, flags),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(unsigned long long, ino)
+               __field(unsigned int, flags)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->ino = ino;
+               __entry->flags = flags;
+       ),
+       TP_printk("%p %llu %u", __entry->inode, __entry->ino, __entry->flags)
+);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_mark_inode_dirty);
+
+/* End of trace events for fs/ocfs2/inode.c. */
+
+/* Trace events for fs/ocfs2/extent_map.c. */
+
+TRACE_EVENT(ocfs2_read_virt_blocks,
+       TP_PROTO(void *inode, unsigned long long vblock, int nr,
+                void *bhs, unsigned int flags, void *validate),
+       TP_ARGS(inode, vblock, nr, bhs, flags, validate),
+       TP_STRUCT__entry(
+               __field(void *, inode)
+               __field(unsigned long long, vblock)
+               __field(int, nr)
+               __field(void *, bhs)
+               __field(unsigned int, flags)
+               __field(void *, validate)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->vblock = vblock;
+               __entry->nr = nr;
+               __entry->bhs = bhs;
+               __entry->flags = flags;
+               __entry->validate = validate;
+       ),
+       TP_printk("%p %llu %d %p %x %p", __entry->inode, __entry->vblock,
+                 __entry->nr, __entry->bhs, __entry->flags, __entry->validate)
+);
+
+/* End of trace events for fs/ocfs2/extent_map.c. */
+
+/* Trace events for fs/ocfs2/slot_map.c. */
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_refresh_slot_info);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers_block);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_find_slot);
+
+/* End of trace events for fs/ocfs2/slot_map.c. */
+
+/* Trace events for fs/ocfs2/heartbeat.c. */
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_do_node_down);
+
+/* End of trace events for fs/ocfs2/heartbeat.c. */
+
+/* Trace events for fs/ocfs2/super.c. */
+
+TRACE_EVENT(ocfs2_remount,
+       TP_PROTO(unsigned long s_flags, unsigned long osb_flags, int flags),
+       TP_ARGS(s_flags, osb_flags, flags),
+       TP_STRUCT__entry(
+               __field(unsigned long, s_flags)
+               __field(unsigned long, osb_flags)
+               __field(int, flags)
+       ),
+       TP_fast_assign(
+               __entry->s_flags = s_flags;
+               __entry->osb_flags = osb_flags;
+               __entry->flags = flags;
+       ),
+       TP_printk("%lu %lu %d", __entry->s_flags,
+                 __entry->osb_flags, __entry->flags)
+);
+
+TRACE_EVENT(ocfs2_fill_super,
+       TP_PROTO(void *sb, void *data, int silent),
+       TP_ARGS(sb, data, silent),
+       TP_STRUCT__entry(
+               __field(void *, sb)
+               __field(void *, data)
+               __field(int, silent)
+       ),
+       TP_fast_assign(
+               __entry->sb = sb;
+               __entry->data = data;
+               __entry->silent = silent;
+       ),
+       TP_printk("%p %p %d", __entry->sb,
+                 __entry->data, __entry->silent)
+);
+
+TRACE_EVENT(ocfs2_parse_options,
+       TP_PROTO(int is_remount, char *options),
+       TP_ARGS(is_remount, options),
+       TP_STRUCT__entry(
+               __field(int, is_remount)
+               __string(options, options)
+       ),
+       TP_fast_assign(
+               __entry->is_remount = is_remount;
+               __assign_str(options, options);
+       ),
+       TP_printk("%d %s", __entry->is_remount, __get_str(options))
+);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_put_super);
+
+TRACE_EVENT(ocfs2_statfs,
+       TP_PROTO(void *sb, void *buf),
+       TP_ARGS(sb, buf),
+       TP_STRUCT__entry(
+               __field(void *, sb)
+               __field(void *, buf)
+       ),
+       TP_fast_assign(
+               __entry->sb = sb;
+               __entry->buf = buf;
+       ),
+       TP_printk("%p %p", __entry->sb, __entry->buf)
+);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_dismount_volume);
+
+TRACE_EVENT(ocfs2_initialize_super,
+       TP_PROTO(char *label, char *uuid_str, unsigned long long root_dir,
+                unsigned long long system_dir, int cluster_bits),
+       TP_ARGS(label, uuid_str, root_dir, system_dir, cluster_bits),
+       TP_STRUCT__entry(
+               __string(label, label)
+               __string(uuid_str, uuid_str)
+               __field(unsigned long long, root_dir)
+               __field(unsigned long long, system_dir)
+               __field(int, cluster_bits)
+       ),
+       TP_fast_assign(
+               __assign_str(label, label);
+               __assign_str(uuid_str, uuid_str);
+               __entry->root_dir = root_dir;
+               __entry->system_dir = system_dir;
+               __entry->cluster_bits = cluster_bits;
+       ),
+       TP_printk("%s %s %llu %llu %d", __get_str(label), __get_str(uuid_str),
+                 __entry->root_dir, __entry->system_dir, __entry->cluster_bits)
+);
+
+/* End of trace events for fs/ocfs2/super.c. */
+
+/* Trace events for fs/ocfs2/xattr.c. */
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_xattr_block);
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_xattr_extend_allocation);
+
+TRACE_EVENT(ocfs2_init_xattr_set_ctxt,
+       TP_PROTO(const char *name, int meta, int clusters, int credits),
+       TP_ARGS(name, meta, clusters, credits),
+       TP_STRUCT__entry(
+               __string(name, name)
+               __field(int, meta)
+               __field(int, clusters)
+               __field(int, credits)
+       ),
+       TP_fast_assign(
+               __assign_str(name, name);
+               __entry->meta = meta;
+               __entry->clusters = clusters;
+               __entry->credits = credits;
+       ),
+       TP_printk("%s %d %d %d", __get_str(name), __entry->meta,
+                 __entry->clusters, __entry->credits)
+);
+
+DECLARE_EVENT_CLASS(ocfs2__xattr_find,
+       TP_PROTO(unsigned long long ino, const char *name, int name_index,
+                unsigned int hash, unsigned long long location,
+                int xe_index),
+       TP_ARGS(ino, name, name_index, hash, location, xe_index),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __string(name, name)
+               __field(int, name_index)
+               __field(unsigned int, hash)
+               __field(unsigned long long, location)
+               __field(int, xe_index)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __assign_str(name, name);
+               __entry->name_index = name_index;
+               __entry->hash = hash;
+               __entry->location = location;
+               __entry->xe_index = xe_index;
+       ),
+       TP_printk("%llu %s %d %u %llu %d", __entry->ino, __get_str(name),
+                 __entry->name_index, __entry->hash, __entry->location,
+                 __entry->xe_index)
+);
+
+#define DEFINE_OCFS2_XATTR_FIND_EVENT(name)                                    \
+DEFINE_EVENT(ocfs2__xattr_find, name,                                  \
+TP_PROTO(unsigned long long ino, const char *name, int name_index,     \
+        unsigned int hash, unsigned long long bucket,                  \
+        int xe_index),                                                 \
+       TP_ARGS(ino, name, name_index, hash, bucket, xe_index))
+
+DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_bucket_find);
+
+DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find);
+
+DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find_rec);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_iterate_xattr_buckets);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_iterate_xattr_bucket);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cp_xattr_block_to_bucket_begin);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cp_xattr_block_to_bucket_end);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block_begin);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_defrag_xattr_bucket);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_bucket_cross_cluster);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_divide_xattr_bucket_begin);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_divide_xattr_bucket_move);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_cp_xattr_bucket);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_buckets);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_adjust_xattr_cross_cluster);
+
+DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_begin);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_add_new_xattr_cluster);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_insert);
+
+DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_extend_xattr_bucket);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_add_new_xattr_bucket);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_xattr_bucket_value_truncate);
+
+DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_rm_xattr_cluster);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_header);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_create_empty_xattr_block);
+
+DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_bucket);
+
+DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_index_block);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_xattr_bucket_value_refcount);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_reflink_xattr_buckets);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_rec);
+
+/* End of trace events for fs/ocfs2/xattr.c. */
+
+/* Trace events for fs/ocfs2/reservations.c. */
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_insert);
+
+DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_begin);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_end);
+
+TRACE_EVENT(ocfs2_resv_find_window_begin,
+       TP_PROTO(unsigned int r_start, unsigned int r_end, unsigned int goal,
+                unsigned int wanted, int empty_root),
+       TP_ARGS(r_start, r_end, goal, wanted, empty_root),
+       TP_STRUCT__entry(
+               __field(unsigned int, r_start)
+               __field(unsigned int, r_end)
+               __field(unsigned int, goal)
+               __field(unsigned int, wanted)
+               __field(int, empty_root)
+       ),
+       TP_fast_assign(
+               __entry->r_start = r_start;
+               __entry->r_end = r_end;
+               __entry->goal = goal;
+               __entry->wanted = wanted;
+               __entry->empty_root = empty_root;
+       ),
+       TP_printk("%u %u %u %u %d", __entry->r_start, __entry->r_end,
+                 __entry->goal, __entry->wanted, __entry->empty_root)
+);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_find_window_prev);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_resv_find_window_next);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cannibalize_resv_begin);
+
+TRACE_EVENT(ocfs2_cannibalize_resv_end,
+       TP_PROTO(unsigned int start, unsigned int end, unsigned int len,
+                unsigned int last_start, unsigned int last_len),
+       TP_ARGS(start, end, len, last_start, last_len),
+       TP_STRUCT__entry(
+               __field(unsigned int, start)
+               __field(unsigned int, end)
+               __field(unsigned int, len)
+               __field(unsigned int, last_start)
+               __field(unsigned int, last_len)
+       ),
+       TP_fast_assign(
+               __entry->start = start;
+               __entry->end = end;
+               __entry->len = len;
+               __entry->last_start = last_start;
+               __entry->last_len = last_len;
+       ),
+       TP_printk("%u %u %u %u %u", __entry->start, __entry->end,
+                 __entry->len, __entry->last_start, __entry->last_len)
+);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_resv_bits);
+
+TRACE_EVENT(ocfs2_resmap_claimed_bits_begin,
+       TP_PROTO(unsigned int cstart, unsigned int cend, unsigned int clen,
+                unsigned int r_start, unsigned int r_end, unsigned int r_len,
+                unsigned int last_start, unsigned int last_len),
+       TP_ARGS(cstart, cend, clen, r_start, r_end,
+               r_len, last_start, last_len),
+       TP_STRUCT__entry(
+               __field(unsigned int, cstart)
+               __field(unsigned int, cend)
+               __field(unsigned int, clen)
+               __field(unsigned int, r_start)
+               __field(unsigned int, r_end)
+               __field(unsigned int, r_len)
+               __field(unsigned int, last_start)
+               __field(unsigned int, last_len)
+       ),
+       TP_fast_assign(
+               __entry->cstart = cstart;
+               __entry->cend = cend;
+               __entry->clen = clen;
+               __entry->r_start = r_start;
+               __entry->r_end = r_end;
+               __entry->r_len = r_len;
+               __entry->last_start = last_start;
+               __entry->last_len = last_len;
+       ),
+       TP_printk("%u %u %u %u %u %u %u %u",
+                 __entry->cstart, __entry->cend, __entry->clen,
+                 __entry->r_start, __entry->r_end, __entry->r_len,
+                 __entry->last_start, __entry->last_len)
+);
+
+TRACE_EVENT(ocfs2_resmap_claimed_bits_end,
+       TP_PROTO(unsigned int start, unsigned int end, unsigned int len,
+                unsigned int last_start, unsigned int last_len),
+       TP_ARGS(start, end, len, last_start, last_len),
+       TP_STRUCT__entry(
+               __field(unsigned int, start)
+               __field(unsigned int, end)
+               __field(unsigned int, len)
+               __field(unsigned int, last_start)
+               __field(unsigned int, last_len)
+       ),
+       TP_fast_assign(
+               __entry->start = start;
+               __entry->end = end;
+               __entry->len = len;
+               __entry->last_start = last_start;
+               __entry->last_len = last_len;
+       ),
+       TP_printk("%u %u %u %u %u", __entry->start, __entry->end,
+                 __entry->len, __entry->last_start, __entry->last_len)
+);
+
+/* End of trace events for fs/ocfs2/reservations.c. */
+
+/* Trace events for fs/ocfs2/quota_local.c. */
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_recover_local_quota_file);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_finish_quota_recovery);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(olq_set_dquot);
+
+/* End of trace events for fs/ocfs2/quota_local.c. */
+
+/* Trace events for fs/ocfs2/quota_global.c. */
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_quota_block);
+
+TRACE_EVENT(ocfs2_sync_dquot,
+       TP_PROTO(unsigned int dq_id, long long dqb_curspace,
+                long long spacechange, long long curinodes,
+                long long inodechange),
+       TP_ARGS(dq_id, dqb_curspace, spacechange, curinodes, inodechange),
+       TP_STRUCT__entry(
+               __field(unsigned int, dq_id)
+               __field(long long, dqb_curspace)
+               __field(long long, spacechange)
+               __field(long long, curinodes)
+               __field(long long, inodechange)
+       ),
+       TP_fast_assign(
+               __entry->dq_id = dq_id;
+               __entry->dqb_curspace = dqb_curspace;
+               __entry->spacechange = spacechange;
+               __entry->curinodes = curinodes;
+               __entry->inodechange = inodechange;
+       ),
+       TP_printk("%u %lld %lld %lld %lld", __entry->dq_id,
+                 __entry->dqb_curspace, __entry->spacechange,
+                 __entry->curinodes, __entry->inodechange)
+);
+
+TRACE_EVENT(ocfs2_sync_dquot_helper,
+       TP_PROTO(unsigned int dq_id, unsigned int dq_type, unsigned long type,
+                const char *s_id),
+       TP_ARGS(dq_id, dq_type, type, s_id),
+
+       TP_STRUCT__entry(
+               __field(unsigned int, dq_id)
+               __field(unsigned int, dq_type)
+               __field(unsigned long, type)
+               __string(s_id, s_id)
+       ),
+       TP_fast_assign(
+               __entry->dq_id = dq_id;
+               __entry->dq_type = dq_type;
+               __entry->type = type;
+               __assign_str(s_id, s_id);
+       ),
+       TP_printk("%u %u %lu %s", __entry->dq_id, __entry->dq_type,
+                 __entry->type, __get_str(s_id))
+);
+
+DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_write_dquot);
+
+DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_release_dquot);
+
+DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_acquire_dquot);
+
+DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_mark_dquot_dirty);
+
+/* End of trace events for fs/ocfs2/quota_global.c. */
+
+/* Trace events for fs/ocfs2/dir.c. */
+DEFINE_OCFS2_INT_EVENT(ocfs2_search_dirblock);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_dir_block);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_find_entry_el);
+
+TRACE_EVENT(ocfs2_dx_dir_search,
+       TP_PROTO(unsigned long long ino, int namelen, const char *name,
+                unsigned int major_hash, unsigned int minor_hash,
+                unsigned long long blkno),
+       TP_ARGS(ino, namelen, name, major_hash, minor_hash, blkno),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(int, namelen)
+               __string(name, name)
+               __field(unsigned int, major_hash)
+               __field(unsigned int,minor_hash)
+               __field(unsigned long long, blkno)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->namelen = namelen;
+               __assign_str(name, name);
+               __entry->major_hash = major_hash;
+               __entry->minor_hash = minor_hash;
+               __entry->blkno = blkno;
+       ),
+       TP_printk("%llu %.*s %u %u %llu", __entry->ino,
+                  __entry->namelen, __get_str(name),
+                 __entry->major_hash, __entry->minor_hash, __entry->blkno)
+);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_dx_dir_search_leaf_info);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_delete_entry_dx);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_readdir);
+
+TRACE_EVENT(ocfs2_find_files_on_disk,
+       TP_PROTO(int namelen, const char *name, void *blkno,
+                unsigned long long dir),
+       TP_ARGS(namelen, name, blkno, dir),
+       TP_STRUCT__entry(
+               __field(int, namelen)
+               __string(name, name)
+               __field(void *, blkno)
+               __field(unsigned long long, dir)
+       ),
+       TP_fast_assign(
+               __entry->namelen = namelen;
+               __assign_str(name, name);
+               __entry->blkno = blkno;
+               __entry->dir = dir;
+       ),
+       TP_printk("%.*s %p %llu", __entry->namelen, __get_str(name),
+                 __entry->blkno, __entry->dir)
+);
+
+TRACE_EVENT(ocfs2_check_dir_for_entry,
+       TP_PROTO(unsigned long long dir, int namelen, const char *name),
+       TP_ARGS(dir, namelen, name),
+       TP_STRUCT__entry(
+               __field(unsigned long long, dir)
+               __field(int, namelen)
+               __string(name, name)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __entry->namelen = namelen;
+               __assign_str(name, name);
+       ),
+       TP_printk("%llu %.*s", __entry->dir,
+                 __entry->namelen, __get_str(name))
+);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_dx_dir_attach_index);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_format_cluster);
+
+TRACE_EVENT(ocfs2_dx_dir_index_root_block,
+       TP_PROTO(unsigned long long dir,
+                unsigned int major_hash, unsigned int minor_hash,
+                int namelen, const char *name, unsigned int num_used),
+       TP_ARGS(dir, major_hash, minor_hash, namelen, name, num_used),
+       TP_STRUCT__entry(
+               __field(unsigned long long, dir)
+               __field(unsigned int, major_hash)
+               __field(unsigned int, minor_hash)
+               __field(int, namelen)
+               __string(name, name)
+               __field(unsigned int, num_used)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __entry->major_hash = major_hash;
+               __entry->minor_hash = minor_hash;
+               __entry->namelen = namelen;
+               __assign_str(name, name);
+               __entry->num_used = num_used;
+       ),
+       TP_printk("%llu %x %x %.*s %u", __entry->dir,
+                 __entry->major_hash, __entry->minor_hash,
+                  __entry->namelen, __get_str(name), __entry->num_used)
+);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_extend_dir);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_rebalance);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_dx_dir_rebalance_split);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_prepare_dir_for_insert);
+
+/* End of trace events for fs/ocfs2/dir.c. */
+
+/* Trace events for fs/ocfs2/namei.c. */
+
+DECLARE_EVENT_CLASS(ocfs2__dentry_ops,
+       TP_PROTO(void *dir, void *dentry, int name_len, const char *name,
+                unsigned long long dir_blkno, unsigned long long extra),
+       TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra),
+       TP_STRUCT__entry(
+               __field(void *, dir)
+               __field(void *, dentry)
+               __field(int, name_len)
+               __string(name, name)
+               __field(unsigned long long, dir_blkno)
+               __field(unsigned long long, extra)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __entry->dentry = dentry;
+               __entry->name_len = name_len;
+               __assign_str(name, name);
+               __entry->dir_blkno = dir_blkno;
+               __entry->extra = extra;
+       ),
+       TP_printk("%p %p %.*s %llu %llu", __entry->dir, __entry->dentry,
+                 __entry->name_len, __get_str(name),
+                 __entry->dir_blkno, __entry->extra)
+);
+
+#define DEFINE_OCFS2_DENTRY_OPS(name)                                  \
+DEFINE_EVENT(ocfs2__dentry_ops, name,                                  \
+TP_PROTO(void *dir, void *dentry, int name_len, const char *name,      \
+        unsigned long long dir_blkno, unsigned long long extra),       \
+       TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra))
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_lookup);
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_mkdir);
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_create);
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_unlink);
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_symlink_create);
+
+DEFINE_OCFS2_DENTRY_OPS(ocfs2_mv_orphaned_inode_to_new);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_lookup_ret);
+
+TRACE_EVENT(ocfs2_mknod,
+       TP_PROTO(void *dir, void *dentry, int name_len, const char *name,
+                unsigned long long dir_blkno, unsigned long dev, int mode),
+       TP_ARGS(dir, dentry, name_len, name, dir_blkno, dev, mode),
+       TP_STRUCT__entry(
+               __field(void *, dir)
+               __field(void *, dentry)
+               __field(int, name_len)
+               __string(name, name)
+               __field(unsigned long long, dir_blkno)
+               __field(unsigned long, dev)
+               __field(int, mode)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __entry->dentry = dentry;
+               __entry->name_len = name_len;
+               __assign_str(name, name);
+               __entry->dir_blkno = dir_blkno;
+               __entry->dev = dev;
+               __entry->mode = mode;
+       ),
+       TP_printk("%p %p %.*s %llu %lu %d", __entry->dir, __entry->dentry,
+                 __entry->name_len, __get_str(name),
+                 __entry->dir_blkno, __entry->dev, __entry->mode)
+);
+
+TRACE_EVENT(ocfs2_link,
+       TP_PROTO(unsigned long long ino, int old_len, const char *old_name,
+                int name_len, const char *name),
+       TP_ARGS(ino, old_len, old_name, name_len, name),
+       TP_STRUCT__entry(
+               __field(unsigned long long, ino)
+               __field(int, old_len)
+               __string(old_name, old_name)
+               __field(int, name_len)
+               __string(name, name)
+       ),
+       TP_fast_assign(
+               __entry->ino = ino;
+               __entry->old_len = old_len;
+               __assign_str(old_name, old_name);
+               __entry->name_len = name_len;
+               __assign_str(name, name);
+       ),
+       TP_printk("%llu %.*s %.*s", __entry->ino,
+                 __entry->old_len, __get_str(old_name),
+                 __entry->name_len, __get_str(name))
+);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_unlink_noent);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock_end);
+
+TRACE_EVENT(ocfs2_rename,
+       TP_PROTO(void *old_dir, void *old_dentry,
+                void *new_dir, void *new_dentry,
+                int old_len, const char *old_name,
+                int new_len, const char *new_name),
+       TP_ARGS(old_dir, old_dentry, new_dir, new_dentry,
+               old_len, old_name, new_len, new_name),
+       TP_STRUCT__entry(
+               __field(void *, old_dir)
+               __field(void *, old_dentry)
+               __field(void *, new_dir)
+               __field(void *, new_dentry)
+               __field(int, old_len)
+               __string(old_name, old_name)
+               __field(int, new_len)
+               __string(new_name, new_name)
+       ),
+       TP_fast_assign(
+               __entry->old_dir = old_dir;
+               __entry->old_dentry = old_dentry;
+               __entry->new_dir = new_dir;
+               __entry->new_dentry = new_dentry;
+               __entry->old_len = old_len;
+               __assign_str(old_name, old_name);
+               __entry->new_len = new_len;
+               __assign_str(new_name, new_name);
+       ),
+       TP_printk("%p %p %p %p %.*s %.*s",
+                 __entry->old_dir, __entry->old_dentry,
+                 __entry->new_dir, __entry->new_dentry,
+                 __entry->old_len, __get_str(old_name),
+                 __entry->new_len, __get_str(new_name))
+);
+
+TRACE_EVENT(ocfs2_rename_target_exists,
+       TP_PROTO(int new_len, const char *new_name),
+       TP_ARGS(new_len, new_name),
+       TP_STRUCT__entry(
+               __field(int, new_len)
+               __string(new_name, new_name)
+       ),
+       TP_fast_assign(
+               __entry->new_len = new_len;
+               __assign_str(new_name, new_name);
+       ),
+       TP_printk("%.*s", __entry->new_len, __get_str(new_name))
+);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_rename_disagree);
+
+TRACE_EVENT(ocfs2_rename_over_existing,
+       TP_PROTO(unsigned long long new_blkno, void *new_bh,
+                unsigned long long newdi_blkno),
+       TP_ARGS(new_blkno, new_bh, newdi_blkno),
+       TP_STRUCT__entry(
+               __field(unsigned long long, new_blkno)
+               __field(void *, new_bh)
+               __field(unsigned long long, newdi_blkno)
+       ),
+       TP_fast_assign(
+               __entry->new_blkno = new_blkno;
+               __entry->new_bh = new_bh;
+               __entry->newdi_blkno = newdi_blkno;
+       ),
+       TP_printk("%llu %p %llu", __entry->new_blkno, __entry->new_bh,
+                 __entry->newdi_blkno)
+);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_create_symlink_data);
+
+TRACE_EVENT(ocfs2_symlink_begin,
+       TP_PROTO(void *dir, void *dentry, const char *symname,
+                int len, const char *name),
+       TP_ARGS(dir, dentry, symname, len, name),
+       TP_STRUCT__entry(
+               __field(void *, dir)
+               __field(void *, dentry)
+               __field(const char *, symname)
+               __field(int, len)
+               __string(name, name)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __entry->dentry = dentry;
+               __entry->symname = symname;
+               __entry->len = len;
+               __assign_str(name, name);
+       ),
+       TP_printk("%p %p %s %.*s", __entry->dir, __entry->dentry,
+                 __entry->symname, __entry->len, __get_str(name))
+);
+
+TRACE_EVENT(ocfs2_blkno_stringify,
+       TP_PROTO(unsigned long long blkno, const char *name, int namelen),
+       TP_ARGS(blkno, name, namelen),
+       TP_STRUCT__entry(
+               __field(unsigned long long, blkno)
+               __string(name, name)
+               __field(int, namelen)
+       ),
+       TP_fast_assign(
+               __entry->blkno = blkno;
+               __assign_str(name, name);
+               __entry->namelen = namelen;
+       ),
+       TP_printk("%llu %s %d", __entry->blkno, __get_str(name),
+                 __entry->namelen)
+);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_add_begin);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_orphan_add_end);
+
+TRACE_EVENT(ocfs2_orphan_del,
+       TP_PROTO(unsigned long long dir, const char *name, int namelen),
+       TP_ARGS(dir, name, namelen),
+       TP_STRUCT__entry(
+               __field(unsigned long long, dir)
+               __string(name, name)
+               __field(int, namelen)
+       ),
+       TP_fast_assign(
+               __entry->dir = dir;
+               __assign_str(name, name);
+               __entry->namelen = namelen;
+       ),
+       TP_printk("%llu %s %d", __entry->dir, __get_str(name),
+                 __entry->namelen)
+);
+
+/* End of trace events for fs/ocfs2/namei.c. */
+
+/* Trace events for fs/ocfs2/dcache.c. */
+
+TRACE_EVENT(ocfs2_dentry_revalidate,
+       TP_PROTO(void *dentry, int len, const char *name),
+       TP_ARGS(dentry, len, name),
+       TP_STRUCT__entry(
+               __field(void *, dentry)
+               __field(int, len)
+               __string(name, name)
+       ),
+       TP_fast_assign(
+               __entry->dentry = dentry;
+               __entry->len = len;
+               __assign_str(name, name);
+       ),
+       TP_printk("%p %.*s", __entry->dentry, __entry->len, __get_str(name))
+);
+
+TRACE_EVENT(ocfs2_dentry_revalidate_negative,
+       TP_PROTO(int len, const char *name, unsigned long pgen,
+                unsigned long gen),
+       TP_ARGS(len, name, pgen, gen),
+       TP_STRUCT__entry(
+               __field(int, len)
+               __string(name, name)
+               __field(unsigned long, pgen)
+               __field(unsigned long, gen)
+       ),
+       TP_fast_assign(
+               __entry->len = len;
+               __assign_str(name, name);
+               __entry->pgen = pgen;
+               __entry->gen = gen;
+       ),
+       TP_printk("%.*s %lu %lu", __entry->len, __get_str(name),
+                 __entry->pgen, __entry->gen)
+);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_delete);
+
+DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_dentry_revalidate_orphaned);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_nofsdata);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_dentry_revalidate_ret);
+
+TRACE_EVENT(ocfs2_find_local_alias,
+       TP_PROTO(int len, const char *name),
+       TP_ARGS(len, name),
+       TP_STRUCT__entry(
+               __field(int, len)
+               __string(name, name)
+       ),
+       TP_fast_assign(
+               __entry->len = len;
+               __assign_str(name, name);
+       ),
+       TP_printk("%.*s", __entry->len, __get_str(name))
+);
+
+TRACE_EVENT(ocfs2_dentry_attach_lock,
+       TP_PROTO(int len, const char *name,
+                unsigned long long parent, void *fsdata),
+       TP_ARGS(len, name, parent, fsdata),
+       TP_STRUCT__entry(
+               __field(int, len)
+               __string(name, name)
+               __field(unsigned long long, parent)
+               __field(void *, fsdata)
+       ),
+       TP_fast_assign(
+               __entry->len = len;
+               __assign_str(name, name);
+               __entry->parent = parent;
+               __entry->fsdata = fsdata;
+       ),
+       TP_printk("%.*s %llu %p", __entry->len, __get_str(name),
+                 __entry->parent, __entry->fsdata)
+);
+
+TRACE_EVENT(ocfs2_dentry_attach_lock_found,
+       TP_PROTO(const char *name, unsigned long long parent,
+                unsigned long long ino),
+       TP_ARGS(name, parent, ino),
+       TP_STRUCT__entry(
+               __string(name, name)
+               __field(unsigned long long, parent)
+               __field(unsigned long long, ino)
+       ),
+       TP_fast_assign(
+               __assign_str(name, name);
+               __entry->parent = parent;
+               __entry->ino = ino;
+       ),
+       TP_printk("%s %llu %llu", __get_str(name), __entry->parent, __entry->ino)
+);
+/* End of trace events for fs/ocfs2/dcache.c. */
+
+/* Trace events for fs/ocfs2/export.c. */
+
+TRACE_EVENT(ocfs2_get_dentry_begin,
+       TP_PROTO(void *sb, void *handle, unsigned long long blkno),
+       TP_ARGS(sb, handle, blkno),
+       TP_STRUCT__entry(
+               __field(void *, sb)
+               __field(void *, handle)
+               __field(unsigned long long, blkno)
+       ),
+       TP_fast_assign(
+               __entry->sb = sb;
+               __entry->handle = handle;
+               __entry->blkno = blkno;
+       ),
+       TP_printk("%p %p %llu", __entry->sb, __entry->handle, __entry->blkno)
+);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_get_dentry_test_bit);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_get_dentry_stale);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_get_dentry_generation);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_dentry_end);
+
+TRACE_EVENT(ocfs2_get_parent,
+       TP_PROTO(void *child, int len, const char *name,
+                unsigned long long ino),
+       TP_ARGS(child, len, name, ino),
+       TP_STRUCT__entry(
+               __field(void *, child)
+               __field(int, len)
+               __string(name, name)
+               __field(unsigned long long, ino)
+       ),
+       TP_fast_assign(
+               __entry->child = child;
+               __entry->len = len;
+               __assign_str(name, name);
+               __entry->ino = ino;
+       ),
+       TP_printk("%p %.*s %llu", __entry->child, __entry->len,
+                 __get_str(name), __entry->ino)
+);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_parent_end);
+
+TRACE_EVENT(ocfs2_encode_fh_begin,
+       TP_PROTO(void *dentry, int name_len, const char *name,
+                void *fh, int len, int connectable),
+       TP_ARGS(dentry, name_len, name, fh, len, connectable),
+       TP_STRUCT__entry(
+               __field(void *, dentry)
+               __field(int, name_len)
+               __string(name, name)
+               __field(void *, fh)
+               __field(int, len)
+               __field(int, connectable)
+       ),
+       TP_fast_assign(
+               __entry->dentry = dentry;
+               __entry->name_len = name_len;
+               __assign_str(name, name);
+               __entry->fh = fh;
+               __entry->len = len;
+               __entry->connectable = connectable;
+       ),
+       TP_printk("%p %.*s %p %d %d", __entry->dentry, __entry->name_len,
+                 __get_str(name), __entry->fh, __entry->len,
+                 __entry->connectable)
+);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_self);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_parent);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_encode_fh_type);
+
+/* End of trace events for fs/ocfs2/export.c. */
+
+/* Trace events for fs/ocfs2/journal.c. */
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_commit_cache_begin);
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_commit_cache_end);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_extend_trans);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart);
+
+DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_journal_init);
+
+DEFINE_OCFS2_UINT_EVENT(ocfs2_journal_init_maxlen);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_journal_shutdown);
+
+DEFINE_OCFS2_POINTER_EVENT(ocfs2_journal_shutdown_wait);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_complete_recovery);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_complete_recovery_end);
+
+TRACE_EVENT(ocfs2_complete_recovery_slot,
+       TP_PROTO(int slot, unsigned long long la_ino,
+                unsigned long long tl_ino, void *qrec),
+       TP_ARGS(slot, la_ino, tl_ino, qrec),
+       TP_STRUCT__entry(
+               __field(int, slot)
+               __field(unsigned long long, la_ino)
+               __field(unsigned long long, tl_ino)
+               __field(void *, qrec)
+       ),
+       TP_fast_assign(
+               __entry->slot = slot;
+               __entry->la_ino = la_ino;
+               __entry->tl_ino = tl_ino;
+               __entry->qrec = qrec;
+       ),
+       TP_printk("%d %llu %llu %p", __entry->slot, __entry->la_ino,
+                 __entry->tl_ino, __entry->qrec)
+);
+
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_recovery_thread_node);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_recovery_thread_end);
+
+TRACE_EVENT(ocfs2_recovery_thread,
+       TP_PROTO(int node_num, int osb_node_num, int disable,
+                void *recovery_thread, int map_set),
+       TP_ARGS(node_num, osb_node_num, disable, recovery_thread, map_set),
+       TP_STRUCT__entry(
+               __field(int, node_num)
+               __field(int, osb_node_num)
+               __field(int,disable)
+               __field(void *, recovery_thread)
+               __field(int,map_set)
+       ),
+       TP_fast_assign(
+               __entry->node_num = node_num;
+               __entry->osb_node_num = osb_node_num;
+               __entry->disable = disable;
+               __entry->recovery_thread = recovery_thread;
+               __entry->map_set = map_set;
+       ),
+       TP_printk("%d %d %d %p %d", __entry->node_num,
+                  __entry->osb_node_num, __entry->disable,
+                  __entry->recovery_thread, __entry->map_set)
+);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_replay_journal_recovered);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_lock_err);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_skip);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_recover_node);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_recover_node_skip);
+
+DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_mark_dead_nodes);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_begin);
+
+DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_end);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_filldir);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_recover_orphans);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_recover_orphans_iput);
+
+DEFINE_OCFS2_INT_EVENT(ocfs2_wait_on_mount);
+
+/* End of trace events for fs/ocfs2/journal.c. */
+
+/* Trace events for fs/ocfs2/buffer_head_io.c. */
+
+DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_read_blocks_sync);
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_read_blocks_sync_jbd);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_read_blocks_from_disk);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_bh);
+
+DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_end);
+
+TRACE_EVENT(ocfs2_write_block,
+       TP_PROTO(unsigned long long block, void *ci),
+       TP_ARGS(block, ci),
+       TP_STRUCT__entry(
+               __field(unsigned long long, block)
+               __field(void *, ci)
+       ),
+       TP_fast_assign(
+               __entry->block = block;
+               __entry->ci = ci;
+       ),
+       TP_printk("%llu %p", __entry->block, __entry->ci)
+);
+
+TRACE_EVENT(ocfs2_read_blocks_begin,
+       TP_PROTO(void *ci, unsigned long long block,
+                unsigned int nr, int flags),
+       TP_ARGS(ci, block, nr, flags),
+       TP_STRUCT__entry(
+               __field(void *, ci)
+               __field(unsigned long long, block)
+               __field(unsigned int, nr)
+               __field(int, flags)
+       ),
+       TP_fast_assign(
+               __entry->ci = ci;
+               __entry->block = block;
+               __entry->nr = nr;
+               __entry->flags = flags;
+       ),
+       TP_printk("%p %llu %u %d", __entry->ci, __entry->block,
+                 __entry->nr, __entry->flags)
+);
+
+/* End of trace events for fs/ocfs2/buffer_head_io.c. */
+
+/* Trace events for fs/ocfs2/uptodate.c. */
+
+DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_copied_metadata_tree);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_metadata_cache_purge);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_buffer_cached_begin);
+
+TRACE_EVENT(ocfs2_buffer_cached_end,
+       TP_PROTO(int index, void *item),
+       TP_ARGS(index, item),
+       TP_STRUCT__entry(
+               __field(int, index)
+               __field(void *, item)
+       ),
+       TP_fast_assign(
+               __entry->index = index;
+               __entry->item = item;
+       ),
+       TP_printk("%d %p", __entry->index, __entry->item)
+);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_append_cache_array);
+
+DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_insert_cache_tree);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_expand_cache);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_set_buffer_uptodate);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_set_buffer_uptodate_begin);
+
+DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_remove_metadata_array);
+
+DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_remove_metadata_tree);
+
+DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_remove_block_from_cache);
+
+/* End of trace events for fs/ocfs2/uptodate.c. */
+#endif /* _TRACE_OCFS2_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE ocfs2_trace
+#include <trace/define_trace.h>
index a73f641664818e2a6c93d30d192b3a70303fecee..279aef68025b3155f7e9efccd5b63409927deae3 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/writeback.h>
 #include <linux/workqueue.h>
 
-#define MLOG_MASK_PREFIX ML_QUOTA
 #include <cluster/masklog.h>
 
 #include "ocfs2_fs.h"
@@ -27,6 +26,7 @@
 #include "super.h"
 #include "buffer_head_io.h"
 #include "quota.h"
+#include "ocfs2_trace.h"
 
 /*
  * Locking of quotas with OCFS2 is rather complex. Here are rules that
@@ -130,8 +130,7 @@ int ocfs2_validate_quota_block(struct super_block *sb, struct buffer_head *bh)
        struct ocfs2_disk_dqtrailer *dqt =
                ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data);
 
-       mlog(0, "Validating quota block %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_quota_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -341,8 +340,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
        u64 pcount;
        int status;
 
-       mlog_entry_void();
-
        /* Read global header */
        gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
                        OCFS2_INVALID_SLOT);
@@ -402,7 +399,8 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
                              msecs_to_jiffies(oinfo->dqi_syncms));
 
 out_err:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 out_unlock:
        ocfs2_unlock_global_qf(oinfo, 0);
@@ -508,9 +506,10 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
        olditime = dquot->dq_dqb.dqb_itime;
        oldbtime = dquot->dq_dqb.dqb_btime;
        ocfs2_global_disk2memdqb(dquot, &dqblk);
-       mlog(0, "Syncing global dquot %u space %lld+%lld, inodes %lld+%lld\n",
-            dquot->dq_id, dquot->dq_dqb.dqb_curspace, (long long)spacechange,
-            dquot->dq_dqb.dqb_curinodes, (long long)inodechange);
+       trace_ocfs2_sync_dquot(dquot->dq_id, dquot->dq_dqb.dqb_curspace,
+                              (long long)spacechange,
+                              dquot->dq_dqb.dqb_curinodes,
+                              (long long)inodechange);
        if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
                dquot->dq_dqb.dqb_curspace += spacechange;
        if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
@@ -594,8 +593,8 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
        struct ocfs2_super *osb = OCFS2_SB(sb);
        int status = 0;
 
-       mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id,
-                  dquot->dq_type, type, sb->s_id);
+       trace_ocfs2_sync_dquot_helper(dquot->dq_id, dquot->dq_type,
+                                     type, sb->s_id);
        if (type != dquot->dq_type)
                goto out;
        status = ocfs2_lock_global_qf(oinfo, 1);
@@ -621,7 +620,6 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
 out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 out:
-       mlog_exit(status);
        return status;
 }
 
@@ -647,7 +645,7 @@ static int ocfs2_write_dquot(struct dquot *dquot)
        struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
        int status = 0;
 
-       mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
+       trace_ocfs2_write_dquot(dquot->dq_id, dquot->dq_type);
 
        handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS);
        if (IS_ERR(handle)) {
@@ -660,7 +658,6 @@ static int ocfs2_write_dquot(struct dquot *dquot)
        mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
        ocfs2_commit_trans(osb, handle);
 out:
-       mlog_exit(status);
        return status;
 }
 
@@ -686,7 +683,7 @@ static int ocfs2_release_dquot(struct dquot *dquot)
        struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
        int status = 0;
 
-       mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
+       trace_ocfs2_release_dquot(dquot->dq_id, dquot->dq_type);
 
        mutex_lock(&dquot->dq_lock);
        /* Check whether we are not racing with some other dqget() */
@@ -722,7 +719,8 @@ out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 out:
        mutex_unlock(&dquot->dq_lock);
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -743,7 +741,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
        int need_alloc = ocfs2_global_qinit_alloc(sb, type);
        handle_t *handle;
 
-       mlog_entry("id=%u, type=%d", dquot->dq_id, type);
+       trace_ocfs2_acquire_dquot(dquot->dq_id, type);
        mutex_lock(&dquot->dq_lock);
        /*
         * We need an exclusive lock, because we're going to update use count
@@ -809,7 +807,8 @@ out_dq:
        set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
 out:
        mutex_unlock(&dquot->dq_lock);
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -829,7 +828,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
        handle_t *handle;
        struct ocfs2_super *osb = OCFS2_SB(sb);
 
-       mlog_entry("id=%u, type=%d", dquot->dq_id, type);
+       trace_ocfs2_mark_dquot_dirty(dquot->dq_id, type);
 
        /* In case user set some limits, sync dquot immediately to global
         * quota file so that information propagates quicker */
@@ -866,7 +865,8 @@ out_dlock:
 out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 out:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -877,8 +877,6 @@ static int ocfs2_write_info(struct super_block *sb, int type)
        int status = 0;
        struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
 
-       mlog_entry_void();
-
        status = ocfs2_lock_global_qf(oinfo, 1);
        if (status < 0)
                goto out;
@@ -893,7 +891,8 @@ static int ocfs2_write_info(struct super_block *sb, int type)
 out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 out:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
index dc78764ccc4c6211bacee0a409f23606e24b3997..dc8007fc924718c6d461b22cee52e4a8fbd6ae7d 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/quotaops.h>
 #include <linux/module.h>
 
-#define MLOG_MASK_PREFIX ML_QUOTA
 #include <cluster/masklog.h>
 
 #include "ocfs2_fs.h"
@@ -23,6 +22,7 @@
 #include "quota.h"
 #include "uptodate.h"
 #include "super.h"
+#include "ocfs2_trace.h"
 
 /* Number of local quota structures per block */
 static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
@@ -475,7 +475,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
        struct ocfs2_recovery_chunk *rchunk, *next;
        qsize_t spacechange, inodechange;
 
-       mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type);
+       trace_ocfs2_recover_local_quota_file((unsigned long)lqinode->i_ino, type);
 
        list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) {
                chunk = rchunk->rc_chunk;
@@ -575,7 +575,8 @@ out_put_bh:
        }
        if (status < 0)
                free_recovery_list(&(rec->r_list[type]));
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -600,7 +601,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
        for (type = 0; type < MAXQUOTAS; type++) {
                if (list_empty(&(rec->r_list[type])))
                        continue;
-               mlog(0, "Recovering quota in slot %d\n", slot_num);
+               trace_ocfs2_finish_quota_recovery(slot_num);
                lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num);
                if (!lqinode) {
                        status = -ENOENT;
@@ -882,9 +883,10 @@ static void olq_set_dquot(struct buffer_head *bh, void *private)
        dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes -
                                          od->dq_originodes);
        spin_unlock(&dq_data_lock);
-       mlog(0, "Writing local dquot %u space %lld inodes %lld\n",
-            od->dq_dquot.dq_id, (long long)le64_to_cpu(dqblk->dqb_spacemod),
-            (long long)le64_to_cpu(dqblk->dqb_inodemod));
+       trace_olq_set_dquot(
+               (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod),
+               (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod),
+               od->dq_dquot.dq_id);
 }
 
 /* Write dquot to local quota file */
index c384d634872a24cc673b1cd0f4e9b837cc433982..5d32749c896dc069d1353f09b75f1aadf42ac886 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/sort.h>
-#define MLOG_MASK_PREFIX ML_REFCOUNT
 #include <cluster/masklog.h>
 #include "ocfs2.h"
 #include "inode.h"
@@ -34,6 +33,7 @@
 #include "aops.h"
 #include "xattr.h"
 #include "namei.h"
+#include "ocfs2_trace.h"
 
 #include <linux/bio.h>
 #include <linux/blkdev.h>
@@ -84,8 +84,7 @@ static int ocfs2_validate_refcount_block(struct super_block *sb,
        struct ocfs2_refcount_block *rb =
                (struct ocfs2_refcount_block *)bh->b_data;
 
-       mlog(0, "Validating refcount block %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_refcount_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -545,8 +544,8 @@ void ocfs2_purge_refcount_trees(struct ocfs2_super *osb)
        while ((node = rb_last(root)) != NULL) {
                tree = rb_entry(node, struct ocfs2_refcount_tree, rf_node);
 
-               mlog(0, "Purge tree %llu\n",
-                    (unsigned long long) tree->rf_blkno);
+               trace_ocfs2_purge_refcount_trees(
+                               (unsigned long long) tree->rf_blkno);
 
                rb_erase(&tree->rf_node, root);
                ocfs2_free_refcount_tree(tree);
@@ -575,7 +574,8 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
 
        BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
 
-       mlog(0, "create tree for inode %lu\n", inode->i_ino);
+       trace_ocfs2_create_refcount_tree(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
        ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
        if (ret) {
@@ -646,8 +646,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
        di->i_refcount_loc = cpu_to_le64(first_blkno);
        spin_unlock(&oi->ip_lock);
 
-       mlog(0, "created tree for inode %lu, refblock %llu\n",
-            inode->i_ino, (unsigned long long)first_blkno);
+       trace_ocfs2_create_refcount_tree_blkno((unsigned long long)first_blkno);
 
        ocfs2_journal_dirty(handle, di_bh);
 
@@ -1256,8 +1255,9 @@ static int ocfs2_change_refcount_rec(handle_t *handle,
                goto out;
        }
 
-       mlog(0, "change index %d, old count %u, change %d\n", index,
-            le32_to_cpu(rec->r_refcount), change);
+       trace_ocfs2_change_refcount_rec(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               index, le32_to_cpu(rec->r_refcount), change);
        le32_add_cpu(&rec->r_refcount, change);
 
        if (!rec->r_refcount) {
@@ -1353,8 +1353,8 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 
        ocfs2_journal_dirty(handle, ref_root_bh);
 
-       mlog(0, "new leaf block %llu, used %u\n", (unsigned long long)blkno,
-            le16_to_cpu(new_rb->rf_records.rl_used));
+       trace_ocfs2_expand_inline_ref_root((unsigned long long)blkno,
+               le16_to_cpu(new_rb->rf_records.rl_used));
 
        *ref_leaf_bh = new_bh;
        new_bh = NULL;
@@ -1466,9 +1466,9 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh,
                        (struct ocfs2_refcount_block *)new_bh->b_data;
        struct ocfs2_refcount_list *new_rl = &new_rb->rf_records;
 
-       mlog(0, "split old leaf refcount block %llu, count = %u, used = %u\n",
-            (unsigned long long)ref_leaf_bh->b_blocknr,
-            le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used));
+       trace_ocfs2_divide_leaf_refcount_block(
+               (unsigned long long)ref_leaf_bh->b_blocknr,
+               le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used));
 
        /*
         * XXX: Improvement later.
@@ -1601,8 +1601,8 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 
        ocfs2_init_refcount_extent_tree(&ref_et, ci, ref_root_bh);
 
-       mlog(0, "insert new leaf block %llu at %u\n",
-            (unsigned long long)new_bh->b_blocknr, new_cpos);
+       trace_ocfs2_new_leaf_refcount_block(
+                       (unsigned long long)new_bh->b_blocknr, new_cpos);
 
        /* Insert the new leaf block with the specific offset cpos. */
        ret = ocfs2_insert_extent(handle, &ref_et, new_cpos, new_bh->b_blocknr,
@@ -1794,11 +1794,10 @@ static int ocfs2_insert_refcount_rec(handle_t *handle,
                        (le16_to_cpu(rf_list->rl_used) - index) *
                         sizeof(struct ocfs2_refcount_rec));
 
-       mlog(0, "insert refcount record start %llu, len %u, count %u "
-            "to leaf block %llu at index %d\n",
-            (unsigned long long)le64_to_cpu(rec->r_cpos),
-            le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount),
-            (unsigned long long)ref_leaf_bh->b_blocknr, index);
+       trace_ocfs2_insert_refcount_rec(
+               (unsigned long long)ref_leaf_bh->b_blocknr, index,
+               (unsigned long long)le64_to_cpu(rec->r_cpos),
+               le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount));
 
        rf_list->rl_recs[index] = *rec;
 
@@ -1850,10 +1849,12 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
 
        BUG_ON(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL);
 
-       mlog(0, "original r_pos %llu, cluster %u, split %llu, cluster %u\n",
-            le64_to_cpu(orig_rec->r_cpos), le32_to_cpu(orig_rec->r_clusters),
-            le64_to_cpu(split_rec->r_cpos),
-            le32_to_cpu(split_rec->r_clusters));
+       trace_ocfs2_split_refcount_rec(le64_to_cpu(orig_rec->r_cpos),
+               le32_to_cpu(orig_rec->r_clusters),
+               le32_to_cpu(orig_rec->r_refcount),
+               le64_to_cpu(split_rec->r_cpos),
+               le32_to_cpu(split_rec->r_clusters),
+               le32_to_cpu(split_rec->r_refcount));
 
        /*
         * If we just need to split the header or tail clusters,
@@ -1967,12 +1968,11 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
 
        if (split_rec->r_refcount) {
                rf_list->rl_recs[index] = *split_rec;
-               mlog(0, "insert refcount record start %llu, len %u, count %u "
-                    "to leaf block %llu at index %d\n",
-                    (unsigned long long)le64_to_cpu(split_rec->r_cpos),
-                    le32_to_cpu(split_rec->r_clusters),
-                    le32_to_cpu(split_rec->r_refcount),
-                    (unsigned long long)ref_leaf_bh->b_blocknr, index);
+               trace_ocfs2_split_refcount_rec_insert(
+                       (unsigned long long)ref_leaf_bh->b_blocknr, index,
+                       (unsigned long long)le64_to_cpu(split_rec->r_cpos),
+                       le32_to_cpu(split_rec->r_clusters),
+                       le32_to_cpu(split_rec->r_refcount));
 
                if (merge)
                        ocfs2_refcount_rec_merge(rb, index);
@@ -1997,7 +1997,7 @@ static int __ocfs2_increase_refcount(handle_t *handle,
        struct ocfs2_refcount_rec rec;
        unsigned int set_len = 0;
 
-       mlog(0, "Tree owner %llu, add refcount start %llu, len %u\n",
+       trace_ocfs2_increase_refcount_begin(
             (unsigned long long)ocfs2_metadata_cache_owner(ci),
             (unsigned long long)cpos, len);
 
@@ -2024,9 +2024,9 @@ static int __ocfs2_increase_refcount(handle_t *handle,
                 */
                if (rec.r_refcount && le64_to_cpu(rec.r_cpos) == cpos &&
                    set_len <= len) {
-                       mlog(0, "increase refcount rec, start %llu, len %u, "
-                            "count %u\n", (unsigned long long)cpos, set_len,
-                            le32_to_cpu(rec.r_refcount));
+                       trace_ocfs2_increase_refcount_change(
+                               (unsigned long long)cpos, set_len,
+                               le32_to_cpu(rec.r_refcount));
                        ret = ocfs2_change_refcount_rec(handle, ci,
                                                        ref_leaf_bh, index,
                                                        merge, 1);
@@ -2037,7 +2037,7 @@ static int __ocfs2_increase_refcount(handle_t *handle,
                } else if (!rec.r_refcount) {
                        rec.r_refcount = cpu_to_le32(1);
 
-                       mlog(0, "insert refcount rec, start %llu, len %u\n",
+                       trace_ocfs2_increase_refcount_insert(
                             (unsigned long long)le64_to_cpu(rec.r_cpos),
                             set_len);
                        ret = ocfs2_insert_refcount_rec(handle, ci, ref_root_bh,
@@ -2055,8 +2055,7 @@ static int __ocfs2_increase_refcount(handle_t *handle,
                        rec.r_clusters = cpu_to_le32(set_len);
                        le32_add_cpu(&rec.r_refcount, 1);
 
-                       mlog(0, "split refcount rec, start %llu, "
-                            "len %u, count %u\n",
+                       trace_ocfs2_increase_refcount_split(
                             (unsigned long long)le64_to_cpu(rec.r_cpos),
                             set_len, le32_to_cpu(rec.r_refcount));
                        ret = ocfs2_split_refcount_rec(handle, ci,
@@ -2095,6 +2094,11 @@ static int ocfs2_remove_refcount_extent(handle_t *handle,
 
        BUG_ON(rb->rf_records.rl_used);
 
+       trace_ocfs2_remove_refcount_extent(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)ref_leaf_bh->b_blocknr,
+               le32_to_cpu(rb->rf_cpos));
+
        ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
        ret = ocfs2_remove_extent(handle, &et, le32_to_cpu(rb->rf_cpos),
                                  1, meta_ac, dealloc);
@@ -2137,7 +2141,7 @@ static int ocfs2_remove_refcount_extent(handle_t *handle,
        if (!rb->rf_list.l_next_free_rec) {
                BUG_ON(rb->rf_clusters);
 
-               mlog(0, "reset refcount tree root %llu to be a record block.\n",
+               trace_ocfs2_restore_refcount_block(
                     (unsigned long long)ref_root_bh->b_blocknr);
 
                rb->rf_flags = 0;
@@ -2184,6 +2188,10 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle,
        BUG_ON(cpos + len >
               le64_to_cpu(rec->r_cpos) + le32_to_cpu(rec->r_clusters));
 
+       trace_ocfs2_decrease_refcount_rec(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)cpos, len);
+
        if (cpos == le64_to_cpu(rec->r_cpos) &&
            len == le32_to_cpu(rec->r_clusters))
                ret = ocfs2_change_refcount_rec(handle, ci,
@@ -2195,12 +2203,6 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle,
 
                le32_add_cpu(&split.r_refcount, -1);
 
-               mlog(0, "split refcount rec, start %llu, "
-                    "len %u, count %u, original start %llu, len %u\n",
-                    (unsigned long long)le64_to_cpu(split.r_cpos),
-                    len, le32_to_cpu(split.r_refcount),
-                    (unsigned long long)le64_to_cpu(rec->r_cpos),
-                    le32_to_cpu(rec->r_clusters));
                ret = ocfs2_split_refcount_rec(handle, ci,
                                               ref_root_bh, ref_leaf_bh,
                                               &split, index, 1,
@@ -2239,10 +2241,9 @@ static int __ocfs2_decrease_refcount(handle_t *handle,
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
        struct buffer_head *ref_leaf_bh = NULL;
 
-       mlog(0, "Tree owner %llu, decrease refcount start %llu, "
-            "len %u, delete %u\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            (unsigned long long)cpos, len, delete);
+       trace_ocfs2_decrease_refcount(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)cpos, len, delete);
 
        while (len) {
                ret = ocfs2_get_refcount_rec(ci, ref_root_bh,
@@ -2352,8 +2353,8 @@ static int ocfs2_mark_extent_refcounted(struct inode *inode,
 {
        int ret;
 
-       mlog(0, "Inode %lu refcount tree cpos %u, len %u, phys cluster %u\n",
-            inode->i_ino, cpos, len, phys);
+       trace_ocfs2_mark_extent_refcounted(OCFS2_I(inode)->ip_blkno,
+                                          cpos, len, phys);
 
        if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) {
                ocfs2_error(inode->i_sb, "Inode %lu want to use refcount "
@@ -2392,8 +2393,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
        struct buffer_head *ref_leaf_bh = NULL, *prev_bh = NULL;
        u32 len;
 
-       mlog(0, "start_cpos %llu, clusters %u\n",
-            (unsigned long long)start_cpos, clusters);
        while (clusters) {
                ret = ocfs2_get_refcount_rec(ci, ref_root_bh,
                                             cpos, clusters, &rec,
@@ -2427,12 +2426,11 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
 
                rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data;
 
-               mlog(0, "recs_add %d,cpos %llu, clusters %u, rec->r_cpos %llu,"
-                    "rec->r_clusters %u, rec->r_refcount %u, index %d\n",
-                    recs_add, (unsigned long long)cpos, clusters,
-                    (unsigned long long)le64_to_cpu(rec.r_cpos),
-                    le32_to_cpu(rec.r_clusters),
-                    le32_to_cpu(rec.r_refcount), index);
+               trace_ocfs2_calc_refcount_meta_credits_iterate(
+                               recs_add, (unsigned long long)cpos, clusters,
+                               (unsigned long long)le64_to_cpu(rec.r_cpos),
+                               le32_to_cpu(rec.r_clusters),
+                               le32_to_cpu(rec.r_refcount), index);
 
                len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) +
                          le32_to_cpu(rec.r_clusters)) - cpos;
@@ -2488,7 +2486,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
        if (!ref_blocks)
                goto out;
 
-       mlog(0, "we need ref_blocks %d\n", ref_blocks);
        *meta_add += ref_blocks;
        *credits += ref_blocks;
 
@@ -2514,6 +2511,10 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
        }
 
 out:
+
+       trace_ocfs2_calc_refcount_meta_credits(
+               (unsigned long long)start_cpos, clusters,
+               *meta_add, *credits);
        brelse(ref_leaf_bh);
        brelse(prev_bh);
        return ret;
@@ -2578,8 +2579,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
                goto out;
        }
 
-       mlog(0, "reserve new metadata %d blocks, credits = %d\n",
-            *ref_blocks, *credits);
+       trace_ocfs2_prepare_refcount_change_for_del(*ref_blocks, *credits);
 
 out:
        brelse(ref_root_bh);
@@ -2886,8 +2886,7 @@ static int ocfs2_lock_refcount_allocators(struct super_block *sb,
                goto out;
        }
 
-       mlog(0, "reserve new metadata %d, clusters %u, credits = %d\n",
-            meta_add, num_clusters, *credits);
+       trace_ocfs2_lock_refcount_allocators(meta_add, *credits);
        ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(sb), meta_add,
                                                meta_ac);
        if (ret) {
@@ -2937,8 +2936,8 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
        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);
+       trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster,
+                                              new_cluster, new_len);
 
        readahead_pages =
                (ocfs2_cow_contig_clusters(sb) <<
@@ -3031,8 +3030,8 @@ static int ocfs2_duplicate_clusters_by_jbd(handle_t *handle,
        struct buffer_head *old_bh = NULL;
        struct buffer_head *new_bh = NULL;
 
-       mlog(0, "old_cluster %u, new %u, len %u\n", old_cluster,
-            new_cluster, new_len);
+       trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster,
+                                              new_cluster, new_len);
 
        for (i = 0; i < blocks; i++, old_block++, new_block++) {
                new_bh = sb_getblk(osb->sb, new_block);
@@ -3085,8 +3084,8 @@ static int ocfs2_clear_ext_refcount(handle_t *handle,
        struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
        u64 ino = ocfs2_metadata_cache_owner(et->et_ci);
 
-       mlog(0, "inode %llu cpos %u, len %u, p_cluster %u, ext_flags %u\n",
-            (unsigned long long)ino, cpos, len, p_cluster, ext_flags);
+       trace_ocfs2_clear_ext_refcount((unsigned long long)ino,
+                                      cpos, len, p_cluster, ext_flags);
 
        memset(&replace_rec, 0, sizeof(replace_rec));
        replace_rec.e_cpos = cpu_to_le32(cpos);
@@ -3141,8 +3140,8 @@ static int ocfs2_replace_clusters(handle_t *handle,
        struct ocfs2_caching_info *ci = context->data_et.et_ci;
        u64 ino = ocfs2_metadata_cache_owner(ci);
 
-       mlog(0, "inode %llu, cpos %u, old %u, new %u, len %u, ext_flags %u\n",
-            (unsigned long long)ino, cpos, old, new, len, ext_flags);
+       trace_ocfs2_replace_clusters((unsigned long long)ino,
+                                    cpos, old, new, len, ext_flags);
 
        /*If the old clusters is unwritten, no need to duplicate. */
        if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) {
@@ -3236,8 +3235,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb,
        struct ocfs2_caching_info *ref_ci = &context->ref_tree->rf_ci;
        struct ocfs2_refcount_rec rec;
 
-       mlog(0, "cpos %u, p_cluster %u, num_clusters %u, e_flags %u\n",
-            cpos, p_cluster, num_clusters, e_flags);
+       trace_ocfs2_make_clusters_writable(cpos, p_cluster,
+                                          num_clusters, e_flags);
 
        ret = ocfs2_lock_refcount_allocators(sb, p_cluster, num_clusters,
                                             &context->data_et,
@@ -3475,9 +3474,9 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
                goto out;
        }
 
-       mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, "
-            "cow_len %u\n", inode->i_ino,
-            cpos, write_len, cow_start, cow_len);
+       trace_ocfs2_refcount_cow_hunk(OCFS2_I(inode)->ip_blkno,
+                                     cpos, write_len, max_cpos,
+                                     cow_start, cow_len);
 
        BUG_ON(cow_len == 0);
 
@@ -3756,8 +3755,7 @@ int ocfs2_add_refcount_flag(struct inode *inode,
                goto out;
        }
 
-       mlog(0, "reserve new metadata %d, credits = %d\n",
-            ref_blocks, credits);
+       trace_ocfs2_add_refcount_flag(ref_blocks, credits);
 
        if (ref_blocks) {
                ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb),
index 3e78db361bc70b3ffc327a6f21b6d4580305d0eb..41ffd36c689c23ff15bccb8d0b1a7e15526d999b 100644 (file)
 #include <linux/bitops.h>
 #include <linux/list.h>
 
-#define MLOG_MASK_PREFIX ML_RESERVATIONS
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
+#include "ocfs2_trace.h"
 
 #ifdef CONFIG_OCFS2_DEBUG_FS
 #define OCFS2_CHECK_RESERVATIONS
@@ -321,8 +321,7 @@ static void ocfs2_resv_insert(struct ocfs2_reservation_map *resmap,
 
        assert_spin_locked(&resv_lock);
 
-       mlog(0, "Insert reservation start: %u len: %u\n", new->r_start,
-            new->r_len);
+       trace_ocfs2_resv_insert(new->r_start, new->r_len);
 
        while (*p) {
                parent = *p;
@@ -423,8 +422,8 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap,
        unsigned int best_start, best_len = 0;
        int offset, start, found;
 
-       mlog(0, "Find %u bits within range (%u, len %u) resmap len: %u\n",
-            wanted, search_start, search_len, resmap->m_bitmap_len);
+       trace_ocfs2_resmap_find_free_bits_begin(search_start, search_len,
+                                               wanted, resmap->m_bitmap_len);
 
        found = best_start = best_len = 0;
 
@@ -463,7 +462,7 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap,
        *rlen = best_len;
        *rstart = best_start;
 
-       mlog(0, "Found start: %u len: %u\n", best_start, best_len);
+       trace_ocfs2_resmap_find_free_bits_end(best_start, best_len);
 
        return *rlen;
 }
@@ -487,9 +486,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
         * - our window should be last in all reservations
         * - need to make sure we don't go past end of bitmap
         */
-
-       mlog(0, "resv start: %u resv end: %u goal: %u wanted: %u\n",
-            resv->r_start, ocfs2_resv_end(resv), goal, wanted);
+       trace_ocfs2_resv_find_window_begin(resv->r_start, ocfs2_resv_end(resv),
+                                          goal, wanted, RB_EMPTY_ROOT(root));
 
        assert_spin_locked(&resv_lock);
 
@@ -498,9 +496,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
                 * Easiest case - empty tree. We can just take
                 * whatever window of free bits we want.
                 */
-
-               mlog(0, "Empty root\n");
-
                clen = ocfs2_resmap_find_free_bits(resmap, wanted, goal,
                                                   resmap->m_bitmap_len - goal,
                                                   &cstart, &clen);
@@ -524,8 +519,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
        prev_resv = ocfs2_find_resv_lhs(resmap, goal);
 
        if (prev_resv == NULL) {
-               mlog(0, "Goal on LHS of leftmost window\n");
-
                /*
                 * A NULL here means that the search code couldn't
                 * find a window that starts before goal.
@@ -570,13 +563,15 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
                next_resv = NULL;
        }
 
+       trace_ocfs2_resv_find_window_prev(prev_resv->r_start,
+                                         ocfs2_resv_end(prev_resv));
+
        prev = &prev_resv->r_node;
 
        /* Now we do a linear search for a window, starting at 'prev_rsv' */
        while (1) {
                next = rb_next(prev);
                if (next) {
-                       mlog(0, "One more resv found in linear search\n");
                        next_resv = rb_entry(next,
                                             struct ocfs2_alloc_reservation,
                                             r_node);
@@ -585,7 +580,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
                        gap_end = next_resv->r_start - 1;
                        gap_len = gap_end - gap_start + 1;
                } else {
-                       mlog(0, "No next node\n");
                        /*
                         * We're at the rightmost edge of the
                         * tree. See if a reservation between this
@@ -596,6 +590,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
                        gap_end = resmap->m_bitmap_len - 1;
                }
 
+               trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1,
+                                       next ? ocfs2_resv_end(next_resv) : -1);
                /*
                 * No need to check this gap if we have already found
                 * a larger region of free bits.
@@ -654,8 +650,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap,
        lru_resv = list_first_entry(&resmap->m_lru,
                                    struct ocfs2_alloc_reservation, r_lru);
 
-       mlog(0, "lru resv: start: %u len: %u end: %u\n", lru_resv->r_start,
-            lru_resv->r_len, ocfs2_resv_end(lru_resv));
+       trace_ocfs2_cannibalize_resv_begin(lru_resv->r_start,
+                                          lru_resv->r_len,
+                                          ocfs2_resv_end(lru_resv));
 
        /*
         * Cannibalize (some or all) of the target reservation and
@@ -684,10 +681,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap,
                resv->r_len = shrink;
        }
 
-       mlog(0, "Reservation now looks like: r_start: %u r_end: %u "
-            "r_len: %u r_last_start: %u r_last_len: %u\n",
-            resv->r_start, ocfs2_resv_end(resv), resv->r_len,
-            resv->r_last_start, resv->r_last_len);
+       trace_ocfs2_cannibalize_resv_end(resv->r_start, ocfs2_resv_end(resv),
+                                        resv->r_len, resv->r_last_start,
+                                        resv->r_last_len);
 
        ocfs2_resv_insert(resmap, resv);
 }
@@ -748,7 +744,6 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap,
                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
@@ -757,6 +752,7 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap,
                 * that inode.
                 */
                ocfs2_resv_find_window(resmap, resv, wanted);
+               trace_ocfs2_resmap_resv_bits(resv->r_start, resv->r_len);
        }
 
        BUG_ON(ocfs2_resv_empty(resv));
@@ -813,10 +809,10 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap,
 
        spin_lock(&resv_lock);
 
-       mlog(0, "claim bits: cstart: %u cend: %u clen: %u r_start: %u "
-            "r_end: %u r_len: %u, r_last_start: %u r_last_len: %u\n",
-            cstart, cend, clen, resv->r_start, ocfs2_resv_end(resv),
-            resv->r_len, resv->r_last_start, resv->r_last_len);
+       trace_ocfs2_resmap_claimed_bits_begin(cstart, cend, clen, resv->r_start,
+                                             ocfs2_resv_end(resv), resv->r_len,
+                                             resv->r_last_start,
+                                             resv->r_last_len);
 
        BUG_ON(cstart < resv->r_start);
        BUG_ON(cstart > ocfs2_resv_end(resv));
@@ -833,10 +829,9 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap,
        if (!ocfs2_resv_empty(resv))
                ocfs2_resv_mark_lru(resmap, resv);
 
-       mlog(0, "Reservation now looks like: r_start: %u r_end: %u "
-            "r_len: %u r_last_start: %u r_last_len: %u\n",
-            resv->r_start, ocfs2_resv_end(resv), resv->r_len,
-            resv->r_last_start, resv->r_last_len);
+       trace_ocfs2_resmap_claimed_bits_end(resv->r_start, ocfs2_resv_end(resv),
+                                           resv->r_len, resv->r_last_start,
+                                           resv->r_last_len);
 
        ocfs2_check_resmap(resmap);
 
index dacd553d861769a4c3c0aab53b462b3a444fc872..ec55add7604a0e964447efa954e4424bf1a39016 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 
-#define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -39,6 +38,7 @@
 #include "super.h"
 #include "sysfile.h"
 #include "uptodate.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 #include "suballoc.h"
@@ -82,7 +82,6 @@ static u16 ocfs2_calc_new_backup_super(struct inode *inode,
                backups++;
        }
 
-       mlog_exit_void();
        return backups;
 }
 
@@ -103,8 +102,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
        u16 cl_bpc = le16_to_cpu(cl->cl_bpc);
        u16 cl_cpg = le16_to_cpu(cl->cl_cpg);
 
-       mlog_entry("(new_clusters=%d, first_new_cluster = %u)\n",
-                  new_clusters, first_new_cluster);
+       trace_ocfs2_update_last_group_and_inode(new_clusters,
+                                               first_new_cluster);
 
        ret = ocfs2_journal_access_gd(handle, INODE_CACHE(bm_inode),
                                      group_bh, OCFS2_JOURNAL_ACCESS_WRITE);
@@ -176,7 +175,8 @@ out_rollback:
                le16_add_cpu(&group->bg_free_bits_count, -1 * num_bits);
        }
 out:
-       mlog_exit(ret);
+       if (ret)
+               mlog_errno(ret);
        return ret;
 }
 
@@ -281,8 +281,6 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
        u32 first_new_cluster;
        u64 lgd_blkno;
 
-       mlog_entry_void();
-
        if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
                return -EROFS;
 
@@ -342,7 +340,8 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
                goto out_unlock;
        }
 
-       mlog(0, "extend the last group at %llu, new clusters = %d\n",
+
+       trace_ocfs2_group_extend(
             (unsigned long long)le64_to_cpu(group->bg_blkno), new_clusters);
 
        handle = ocfs2_start_trans(osb, OCFS2_GROUP_EXTEND_CREDITS);
@@ -377,7 +376,6 @@ out_mutex:
        iput(main_bm_inode);
 
 out:
-       mlog_exit_void();
        return ret;
 }
 
@@ -472,8 +470,6 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        struct ocfs2_chain_rec *cr;
        u16 cl_bpc;
 
-       mlog_entry_void();
-
        if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
                return -EROFS;
 
@@ -520,8 +516,8 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
                goto out_unlock;
        }
 
-       mlog(0, "Add a new group  %llu in chain = %u, length = %u\n",
-            (unsigned long long)input->group, input->chain, input->clusters);
+       trace_ocfs2_group_add((unsigned long long)input->group,
+                              input->chain, input->clusters, input->frees);
 
        handle = ocfs2_start_trans(osb, OCFS2_GROUP_ADD_CREDITS);
        if (IS_ERR(handle)) {
@@ -589,6 +585,5 @@ out_mutex:
        iput(main_bm_inode);
 
 out:
-       mlog_exit_void();
        return ret;
 }
index ab4e0172cc1d11abc3c5d70c62a9298d652fb096..26fc0014d50936137d0afb898b7c9541e8026087 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 
-#define MLOG_MASK_PREFIX ML_SUPER
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -39,6 +38,7 @@
 #include "slot_map.h"
 #include "super.h"
 #include "sysfile.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -142,8 +142,7 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
        BUG_ON(si->si_blocks == 0);
        BUG_ON(si->si_bh == NULL);
 
-       mlog(0, "Refreshing slot map, reading %u block(s)\n",
-            si->si_blocks);
+       trace_ocfs2_refresh_slot_info(si->si_blocks);
 
        /*
         * We pass -1 as blocknr because we expect all of si->si_bh to
@@ -381,8 +380,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
        /* The size checks above should ensure this */
        BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks);
 
-       mlog(0, "Slot map needs %u buffers for %llu bytes\n",
-            si->si_blocks, bytes);
+       trace_ocfs2_map_slot_buffers(bytes, si->si_blocks);
 
        si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks,
                            GFP_KERNEL);
@@ -400,8 +398,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
                        goto bail;
                }
 
-               mlog(0, "Reading slot map block %u at %llu\n", i,
-                    (unsigned long long)blkno);
+               trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i);
 
                bh = NULL;  /* Acquire a fresh bh */
                status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno,
@@ -475,8 +472,6 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
        int slot;
        struct ocfs2_slot_info *si;
 
-       mlog_entry_void();
-
        si = osb->slot_info;
 
        spin_lock(&osb->osb_lock);
@@ -505,14 +500,13 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
        osb->slot_num = slot;
        spin_unlock(&osb->osb_lock);
 
-       mlog(0, "taking node slot %d\n", osb->slot_num);
+       trace_ocfs2_find_slot(osb->slot_num);
 
        status = ocfs2_update_disk_slot(osb, si, osb->slot_num);
        if (status < 0)
                mlog_errno(status);
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
index 71998d4d61d5caa9f80e0a01d6816729260849c1..ab6e2061074fafba4bdc9bf0b9cc7f911cb15dfd 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 
-#define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -44,6 +43,7 @@
 #include "super.h"
 #include "sysfile.h"
 #include "uptodate.h"
+#include "ocfs2_trace.h"
 
 #include "buffer_head_io.h"
 
@@ -308,8 +308,8 @@ static int ocfs2_validate_group_descriptor(struct super_block *sb,
        int rc;
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
 
-       mlog(0, "Validating group descriptor %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_group_descriptor(
+                                       (unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -389,8 +389,6 @@ static int ocfs2_block_group_fill(handle_t *handle,
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
        struct super_block * sb = alloc_inode->i_sb;
 
-       mlog_entry_void();
-
        if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) {
                ocfs2_error(alloc_inode->i_sb, "group block (%llu) != "
                            "b_blocknr (%llu)",
@@ -436,7 +434,8 @@ static int ocfs2_block_group_fill(handle_t *handle,
         * allocation time. */
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -477,8 +476,8 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle,
 
        /* setup the group */
        bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "new descriptor, record %u, at block %llu\n",
-            alloc_rec, (unsigned long long)bg_blkno);
+       trace_ocfs2_block_group_alloc_contig(
+            (unsigned long long)bg_blkno, alloc_rec);
 
        bg_bh = sb_getblk(osb->sb, bg_blkno);
        if (!bg_bh) {
@@ -657,8 +656,8 @@ ocfs2_block_group_alloc_discontig(handle_t *handle,
 
        /* setup the group */
        bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "new descriptor, record %u, at block %llu\n",
-            alloc_rec, (unsigned long long)bg_blkno);
+       trace_ocfs2_block_group_alloc_discontig(
+                               (unsigned long long)bg_blkno, alloc_rec);
 
        bg_bh = sb_getblk(osb->sb, bg_blkno);
        if (!bg_bh) {
@@ -707,8 +706,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode));
 
-       mlog_entry_void();
-
        cl = &fe->id2.i_chain;
        status = ocfs2_reserve_clusters_with_limit(osb,
                                                   le16_to_cpu(cl->cl_cpg),
@@ -730,8 +727,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
        }
 
        if (last_alloc_group && *last_alloc_group != 0) {
-               mlog(0, "use old allocation group %llu for block group alloc\n",
-                    (unsigned long long)*last_alloc_group);
+               trace_ocfs2_block_group_alloc(
+                               (unsigned long long)*last_alloc_group);
                ac->ac_last_group = *last_alloc_group;
        }
 
@@ -796,7 +793,8 @@ bail:
 
        brelse(bg_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -814,8 +812,6 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
        struct ocfs2_dinode *fe;
        u32 free_bits;
 
-       mlog_entry_void();
-
        alloc_inode = ocfs2_get_system_file_inode(osb, type, slot);
        if (!alloc_inode) {
                mlog_errno(-EINVAL);
@@ -855,16 +851,15 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
        if (bits_wanted > free_bits) {
                /* cluster bitmap never grows */
                if (ocfs2_is_cluster_bitmap(alloc_inode)) {
-                       mlog(0, "Disk Full: wanted=%u, free_bits=%u\n",
-                            bits_wanted, free_bits);
+                       trace_ocfs2_reserve_suballoc_bits_nospc(bits_wanted,
+                                                               free_bits);
                        status = -ENOSPC;
                        goto bail;
                }
 
                if (!(flags & ALLOC_NEW_GROUP)) {
-                       mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, "
-                            "and we don't alloc a new group for it.\n",
-                            slot, bits_wanted, free_bits);
+                       trace_ocfs2_reserve_suballoc_bits_no_new_group(
+                                               slot, bits_wanted, free_bits);
                        status = -ENOSPC;
                        goto bail;
                }
@@ -890,7 +885,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
 bail:
        brelse(bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1052,7 +1048,8 @@ bail:
                *ac = NULL;
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1119,8 +1116,8 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
                spin_lock(&osb->osb_lock);
                osb->osb_inode_alloc_group = alloc_group;
                spin_unlock(&osb->osb_lock);
-               mlog(0, "after reservation, new allocation group is "
-                    "%llu\n", (unsigned long long)alloc_group);
+               trace_ocfs2_reserve_new_inode_new_group(
+                       (unsigned long long)alloc_group);
 
                /*
                 * Some inodes must be freed by us, so try to allocate
@@ -1152,7 +1149,8 @@ bail:
                *ac = NULL;
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1189,8 +1187,6 @@ static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
 {
        int status;
 
-       mlog_entry_void();
-
        *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
        if (!(*ac)) {
                status = -ENOMEM;
@@ -1229,7 +1225,8 @@ bail:
                *ac = NULL;
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1357,15 +1354,12 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        void *bitmap = bg->bg_bitmap;
        int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
 
-       mlog_entry_void();
-
        /* All callers get the descriptor via
         * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
        BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
        BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);
 
-       mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
-            num_bits);
+       trace_ocfs2_block_group_set_bits(bit_off, num_bits);
 
        if (ocfs2_is_cluster_bitmap(alloc_inode))
                journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
@@ -1394,7 +1388,8 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        ocfs2_journal_dirty(handle, group_bh);
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1437,10 +1432,10 @@ static int ocfs2_relink_block_group(handle_t *handle,
        BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
        BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(prev_bg));
 
-       mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
-            (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
-            (unsigned long long)le64_to_cpu(bg->bg_blkno),
-            (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));
+       trace_ocfs2_relink_block_group(
+               (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
+               (unsigned long long)le64_to_cpu(bg->bg_blkno),
+               (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));
 
        fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
        bg_ptr = le64_to_cpu(bg->bg_next_group);
@@ -1484,7 +1479,8 @@ out_rollback:
                prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1525,10 +1521,10 @@ static int ocfs2_cluster_group_search(struct inode *inode,
                if ((gd_cluster_off + max_bits) >
                    OCFS2_I(inode)->ip_clusters) {
                        max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off;
-                       mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n",
-                            (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                            le16_to_cpu(gd->bg_bits),
-                            OCFS2_I(inode)->ip_clusters, max_bits);
+                       trace_ocfs2_cluster_group_search_wrong_max_bits(
+                               (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                               le16_to_cpu(gd->bg_bits),
+                               OCFS2_I(inode)->ip_clusters, max_bits);
                }
 
                ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
@@ -1542,9 +1538,9 @@ static int ocfs2_cluster_group_search(struct inode *inode,
                                                          gd_cluster_off +
                                                          res->sr_bit_offset +
                                                          res->sr_bits);
-                       mlog(0, "Checking %llu against %llu\n",
-                            (unsigned long long)blkoff,
-                            (unsigned long long)max_block);
+                       trace_ocfs2_cluster_group_search_max_block(
+                               (unsigned long long)blkoff,
+                               (unsigned long long)max_block);
                        if (blkoff > max_block)
                                return -ENOSPC;
                }
@@ -1588,9 +1584,9 @@ static int ocfs2_block_group_search(struct inode *inode,
                if (!ret && max_block) {
                        blkoff = le64_to_cpu(bg->bg_blkno) +
                                res->sr_bit_offset + res->sr_bits;
-                       mlog(0, "Checking %llu against %llu\n",
-                            (unsigned long long)blkoff,
-                            (unsigned long long)max_block);
+                       trace_ocfs2_block_group_search_max_block(
+                               (unsigned long long)blkoff,
+                               (unsigned long long)max_block);
                        if (blkoff > max_block)
                                ret = -ENOSPC;
                }
@@ -1756,9 +1752,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        struct ocfs2_group_desc *bg;
 
        chain = ac->ac_chain;
-       mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n",
-            bits_wanted, chain,
-            (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);
+       trace_ocfs2_search_chain_begin(
+               (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno,
+               bits_wanted, chain);
 
        status = ocfs2_read_group_descriptor(alloc_inode, fe,
                                             le64_to_cpu(cl->cl_recs[chain].c_blkno),
@@ -1799,8 +1795,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                goto bail;
        }
 
-       mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
-            res->sr_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
+       trace_ocfs2_search_chain_succ(
+               (unsigned long long)le64_to_cpu(bg->bg_blkno), res->sr_bits);
 
        res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno);
 
@@ -1861,8 +1857,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                goto bail;
        }
 
-       mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
-            (unsigned long long)le64_to_cpu(fe->i_blkno));
+       trace_ocfs2_search_chain_end(
+                       (unsigned long long)le64_to_cpu(fe->i_blkno),
+                       res->sr_bits);
 
 out_loc_only:
        *bits_left = le16_to_cpu(bg->bg_free_bits_count);
@@ -1870,7 +1867,8 @@ bail:
        brelse(group_bh);
        brelse(prev_group_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1888,8 +1886,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
        struct ocfs2_chain_list *cl;
        struct ocfs2_dinode *fe;
 
-       mlog_entry_void();
-
        BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
        BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given));
        BUG_ON(!ac->ac_bh);
@@ -1945,8 +1941,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
                goto bail;
        }
 
-       mlog(0, "Search of victim chain %u came up with nothing, "
-            "trying all chains now.\n", victim);
+       trace_ocfs2_claim_suballoc_bits(victim);
 
        /* If we didn't pick a good victim, then just default to
         * searching each chain in order. Don't allow chain relinking
@@ -1984,7 +1979,8 @@ set_hint:
        }
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2021,7 +2017,8 @@ int ocfs2_claim_metadata(handle_t *handle,
        *num_bits = res.sr_bits;
        status = 0;
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2172,8 +2169,8 @@ int ocfs2_claim_new_inode_at_loc(handle_t *handle,
                goto out;
        }
 
-       mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
-            (unsigned long long)di_blkno);
+       trace_ocfs2_claim_new_inode_at_loc((unsigned long long)di_blkno,
+                                          res->sr_bits);
 
        atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
 
@@ -2201,8 +2198,6 @@ int ocfs2_claim_new_inode(handle_t *handle,
        int status;
        struct ocfs2_suballoc_result res;
 
-       mlog_entry_void();
-
        BUG_ON(!ac);
        BUG_ON(ac->ac_bits_given != 0);
        BUG_ON(ac->ac_bits_wanted != 1);
@@ -2230,7 +2225,8 @@ int ocfs2_claim_new_inode(handle_t *handle,
        ocfs2_save_inode_ac_group(dir, ac);
        status = 0;
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2307,8 +2303,6 @@ int __ocfs2_claim_clusters(handle_t *handle,
        struct ocfs2_suballoc_result res = { .sr_blkno = 0, };
        struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb);
 
-       mlog_entry_void();
-
        BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
 
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
@@ -2363,7 +2357,8 @@ int __ocfs2_claim_clusters(handle_t *handle,
        ac->ac_bits_given += *num_clusters;
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2392,13 +2387,11 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
        unsigned int tmp;
        struct ocfs2_group_desc *undo_bg = NULL;
 
-       mlog_entry_void();
-
        /* The caller got this descriptor from
         * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
        BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
 
-       mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
+       trace_ocfs2_block_group_clear_bits(bit_off, num_bits);
 
        BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode));
        status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode),
@@ -2463,8 +2456,6 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle,
        struct buffer_head *group_bh = NULL;
        struct ocfs2_group_desc *group;
 
-       mlog_entry_void();
-
        /* The alloc_bh comes from ocfs2_free_dinode() or
         * ocfs2_free_clusters().  The callers have all locked the
         * allocator and gotten alloc_bh from the lock call.  This
@@ -2473,9 +2464,10 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle,
        BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
        BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl));
 
-       mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n",
-            (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count,
-            (unsigned long long)bg_blkno, start_bit);
+       trace_ocfs2_free_suballoc_bits(
+               (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno,
+               (unsigned long long)bg_blkno,
+               start_bit, count);
 
        status = ocfs2_read_group_descriptor(alloc_inode, fe, bg_blkno,
                                             &group_bh);
@@ -2511,7 +2503,8 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle,
 bail:
        brelse(group_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2556,11 +2549,8 @@ static int _ocfs2_free_clusters(handle_t *handle,
 
        /* You can't ever have a contiguous set of clusters
         * bigger than a block group bitmap so we never have to worry
-        * about looping on them. */
-
-       mlog_entry_void();
-
-       /* This is expensive. We can safely remove once this stuff has
+        * about looping on them.
+        * This is expensive. We can safely remove once this stuff has
         * gotten tested really well. */
        BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk)));
 
@@ -2569,10 +2559,9 @@ static int _ocfs2_free_clusters(handle_t *handle,
        ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
                                     &bg_start_bit);
 
-       mlog(0, "want to free %u clusters starting at block %llu\n",
-            num_clusters, (unsigned long long)start_blk);
-       mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
-            (unsigned long long)bg_blkno, bg_start_bit);
+       trace_ocfs2_free_clusters((unsigned long long)bg_blkno,
+                       (unsigned long long)start_blk,
+                       bg_start_bit, num_clusters);
 
        status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
                                           bg_start_bit, bg_blkno,
@@ -2586,7 +2575,8 @@ static int _ocfs2_free_clusters(handle_t *handle,
                                         num_clusters);
 
 out:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2756,7 +2746,7 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno,
        struct buffer_head *inode_bh = NULL;
        struct ocfs2_dinode *inode_fe;
 
-       mlog_entry("blkno: %llu\n", (unsigned long long)blkno);
+       trace_ocfs2_get_suballoc_slot_bit((unsigned long long)blkno);
 
        /* dirty read disk */
        status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh);
@@ -2793,7 +2783,8 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno,
 bail:
        brelse(inode_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2816,8 +2807,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
        u64 bg_blkno;
        int status;
 
-       mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno,
-                  (unsigned int)bit);
+       trace_ocfs2_test_suballoc_bit((unsigned long long)blkno,
+                                     (unsigned int)bit);
 
        alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data;
        if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) {
@@ -2844,7 +2835,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
 bail:
        brelse(group_bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2869,7 +2861,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
        struct inode *inode_alloc_inode;
        struct buffer_head *alloc_bh = NULL;
 
-       mlog_entry("blkno: %llu", (unsigned long long)blkno);
+       trace_ocfs2_test_inode_bit((unsigned long long)blkno);
 
        status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot,
                                             &group_blkno, &suballoc_bit);
@@ -2910,6 +2902,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
        iput(inode_alloc_inode);
        brelse(alloc_bh);
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
index 236ed1bdca2c5aa39e3140f490f5ba644610ec05..69fa11b35aa4ccd821729a0460d68d7b1ee72d83 100644 (file)
@@ -42,7 +42,9 @@
 #include <linux/seq_file.h>
 #include <linux/quotaops.h>
 
-#define MLOG_MASK_PREFIX ML_SUPER
+#define CREATE_TRACE_POINTS
+#include "ocfs2_trace.h"
+
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -441,8 +443,6 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
        int status = 0;
        int i;
 
-       mlog_entry_void();
-
        new = ocfs2_iget(osb, osb->root_blkno, OCFS2_FI_FLAG_SYSFILE, 0);
        if (IS_ERR(new)) {
                status = PTR_ERR(new);
@@ -478,7 +478,8 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
        }
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -488,8 +489,6 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
        int status = 0;
        int i;
 
-       mlog_entry_void();
-
        for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1;
             i < NUM_SYSTEM_INODES;
             i++) {
@@ -508,7 +507,8 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
        }
 
 bail:
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -517,8 +517,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
        int i;
        struct inode *inode;
 
-       mlog_entry_void();
-
        for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) {
                inode = osb->global_system_inodes[i];
                if (inode) {
@@ -540,7 +538,7 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
        }
 
        if (!osb->local_system_inodes)
-               goto out;
+               return;
 
        for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) {
                if (osb->local_system_inodes[i]) {
@@ -551,9 +549,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
 
        kfree(osb->local_system_inodes);
        osb->local_system_inodes = NULL;
-
-out:
-       mlog_exit(0);
 }
 
 /* We're allocating fs objects, use GFP_NOFS */
@@ -684,12 +679,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                }
 
                if (*flags & MS_RDONLY) {
-                       mlog(0, "Going to ro mode.\n");
                        sb->s_flags |= MS_RDONLY;
                        osb->osb_flags |= OCFS2_OSB_SOFT_RO;
                } else {
-                       mlog(0, "Making ro filesystem writeable.\n");
-
                        if (osb->osb_flags & OCFS2_OSB_ERROR_FS) {
                                mlog(ML_ERROR, "Cannot remount RDWR "
                                     "filesystem due to previous errors.\n");
@@ -707,6 +699,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                        sb->s_flags &= ~MS_RDONLY;
                        osb->osb_flags &= ~OCFS2_OSB_SOFT_RO;
                }
+               trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags);
 unlock_osb:
                spin_unlock(&osb->osb_lock);
                /* Enable quota accounting after remounting RW */
@@ -1032,7 +1025,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        char nodestr[8];
        struct ocfs2_blockcheck_stats stats;
 
-       mlog_entry("%p, %p, %i", sb, data, silent);
+       trace_ocfs2_fill_super(sb, data, silent);
 
        if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) {
                status = -EINVAL;
@@ -1208,7 +1201,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
                        mlog_errno(status);
                        atomic_set(&osb->vol_state, VOLUME_DISABLED);
                        wake_up(&osb->osb_mount_event);
-                       mlog_exit(status);
                        return status;
                }
        }
@@ -1222,7 +1214,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        /* Start this when the mount is almost sure of being successful */
        ocfs2_orphan_scan_start(osb);
 
-       mlog_exit(status);
        return status;
 
 read_super_error:
@@ -1237,7 +1228,8 @@ read_super_error:
                ocfs2_dismount_volume(sb, 1);
        }
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -1320,8 +1312,7 @@ static int ocfs2_parse_options(struct super_block *sb,
        char *p;
        u32 tmp;
 
-       mlog_entry("remount: %d, options: \"%s\"\n", is_remount,
-                  options ? options : "(none)");
+       trace_ocfs2_parse_options(is_remount, options ? options : "(none)");
 
        mopt->commit_interval = 0;
        mopt->mount_opt = OCFS2_MOUNT_NOINTR;
@@ -1538,7 +1529,6 @@ static int ocfs2_parse_options(struct super_block *sb,
        status = 1;
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -1629,8 +1619,6 @@ static int __init ocfs2_init(void)
 {
        int status;
 
-       mlog_entry_void();
-
        ocfs2_print_version();
 
        status = init_ocfs2_uptodate_cache();
@@ -1664,10 +1652,9 @@ leave:
        if (status < 0) {
                ocfs2_free_mem_caches();
                exit_ocfs2_uptodate_cache();
+               mlog_errno(status);
        }
 
-       mlog_exit(status);
-
        if (status >= 0) {
                return register_filesystem(&ocfs2_fs_type);
        } else
@@ -1676,8 +1663,6 @@ leave:
 
 static void __exit ocfs2_exit(void)
 {
-       mlog_entry_void();
-
        if (ocfs2_wq) {
                flush_workqueue(ocfs2_wq);
                destroy_workqueue(ocfs2_wq);
@@ -1692,18 +1677,14 @@ static void __exit ocfs2_exit(void)
        unregister_filesystem(&ocfs2_fs_type);
 
        exit_ocfs2_uptodate_cache();
-
-       mlog_exit_void();
 }
 
 static void ocfs2_put_super(struct super_block *sb)
 {
-       mlog_entry("(0x%p)\n", sb);
+       trace_ocfs2_put_super(sb);
 
        ocfs2_sync_blockdev(sb);
        ocfs2_dismount_volume(sb, 0);
-
-       mlog_exit_void();
 }
 
 static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -1715,7 +1696,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct buffer_head *bh = NULL;
        struct inode *inode = NULL;
 
-       mlog_entry("(%p, %p)\n", dentry->d_sb, buf);
+       trace_ocfs2_statfs(dentry->d_sb, buf);
 
        osb = OCFS2_SB(dentry->d_sb);
 
@@ -1762,7 +1743,8 @@ bail:
        if (inode)
                iput(inode);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
 
        return status;
 }
@@ -1882,8 +1864,6 @@ static int ocfs2_mount_volume(struct super_block *sb)
        int unlock_super = 0;
        struct ocfs2_super *osb = OCFS2_SB(sb);
 
-       mlog_entry_void();
-
        if (ocfs2_is_hard_readonly(osb))
                goto leave;
 
@@ -1928,7 +1908,6 @@ leave:
        if (unlock_super)
                ocfs2_super_unlock(osb, 1);
 
-       mlog_exit(status);
        return status;
 }
 
@@ -1938,7 +1917,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
        struct ocfs2_super *osb = NULL;
        char nodestr[8];
 
-       mlog_entry("(0x%p)\n", sb);
+       trace_ocfs2_dismount_volume(sb);
 
        BUG_ON(!sb);
        osb = OCFS2_SB(sb);
@@ -2090,8 +2069,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
        struct ocfs2_super *osb;
        u64 total_blocks;
 
-       mlog_entry_void();
-
        osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL);
        if (!osb) {
                status = -ENOMEM;
@@ -2155,7 +2132,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
                status = -EINVAL;
                goto bail;
        }
-       mlog(0, "max_slots for this device: %u\n", osb->max_slots);
 
        ocfs2_orphan_scan_init(osb);
 
@@ -2294,7 +2270,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
        osb->s_clustersize_bits =
                le32_to_cpu(di->id2.i_super.s_clustersize_bits);
        osb->s_clustersize = 1 << osb->s_clustersize_bits;
-       mlog(0, "clusterbits=%d\n", osb->s_clustersize_bits);
 
        if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE ||
            osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) {
@@ -2333,11 +2308,10 @@ static int ocfs2_initialize_super(struct super_block *sb,
                le64_to_cpu(di->id2.i_super.s_first_cluster_group);
        osb->fs_generation = le32_to_cpu(di->i_fs_generation);
        osb->uuid_hash = le32_to_cpu(di->id2.i_super.s_uuid_hash);
-       mlog(0, "vol_label: %s\n", osb->vol_label);
-       mlog(0, "uuid: %s\n", osb->uuid_str);
-       mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n",
-            (unsigned long long)osb->root_blkno,
-            (unsigned long long)osb->system_dir_blkno);
+       trace_ocfs2_initialize_super(osb->vol_label, osb->uuid_str,
+                                    (unsigned long long)osb->root_blkno,
+                                    (unsigned long long)osb->system_dir_blkno,
+                                    osb->s_clustersize_bits);
 
        osb->osb_dlm_debug = ocfs2_new_dlm_debug();
        if (!osb->osb_dlm_debug) {
@@ -2380,7 +2354,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
        }
 
 bail:
-       mlog_exit(status);
        return status;
 }
 
@@ -2396,8 +2369,6 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
 {
        int status = -EAGAIN;
 
-       mlog_entry_void();
-
        if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
                   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) {
                /* We have to do a raw check of the feature here */
@@ -2452,7 +2423,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
        }
 
 out:
-       mlog_exit(status);
+       if (status && status != -EAGAIN)
+               mlog_errno(status);
        return status;
 }
 
@@ -2465,8 +2437,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                                                  * recover
                                                  * ourselves. */
 
-       mlog_entry_void();
-
        /* Init our journal object. */
        status = ocfs2_journal_init(osb->journal, &dirty);
        if (status < 0) {
@@ -2516,8 +2486,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                 * ourselves as mounted. */
        }
 
-       mlog(0, "Journal loaded.\n");
-
        status = ocfs2_load_local_alloc(osb);
        if (status < 0) {
                mlog_errno(status);
@@ -2549,7 +2517,8 @@ finally:
        if (local_alloc)
                kfree(local_alloc);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return status;
 }
 
@@ -2561,8 +2530,6 @@ finally:
  */
 static void ocfs2_delete_osb(struct ocfs2_super *osb)
 {
-       mlog_entry_void();
-
        /* This function assumes that the caller has the main osb resource */
 
        ocfs2_free_slot_info(osb);
@@ -2580,8 +2547,6 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
        kfree(osb->uuid_str);
        ocfs2_put_dlm_debug(osb->osb_dlm_debug);
        memset(osb, 0, sizeof(struct ocfs2_super));
-
-       mlog_exit_void();
 }
 
 /* Put OCFS2 into a readonly state, or (if the user specifies it),
index 9975457c981f904ca18a512dd7bcbe0f092ac664..5d22872e2bb36012b711ac7720a90bee24717b15 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/pagemap.h>
 #include <linux/namei.h>
 
-#define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -62,8 +61,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode,
        char *link = NULL;
        struct ocfs2_dinode *fe;
 
-       mlog_entry_void();
-
        status = ocfs2_read_inode_block(inode, bh);
        if (status < 0) {
                mlog_errno(status);
@@ -74,7 +71,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode,
        fe = (struct ocfs2_dinode *) (*bh)->b_data;
        link = (char *) fe->id2.i_symlink;
 bail:
-       mlog_exit(status);
 
        return link;
 }
@@ -88,8 +84,6 @@ static int ocfs2_readlink(struct dentry *dentry,
        struct buffer_head *bh = NULL;
        struct inode *inode = dentry->d_inode;
 
-       mlog_entry_void();
-
        link = ocfs2_fast_symlink_getlink(inode, &bh);
        if (IS_ERR(link)) {
                ret = PTR_ERR(link);
@@ -104,7 +98,8 @@ static int ocfs2_readlink(struct dentry *dentry,
 
        brelse(bh);
 out:
-       mlog_exit(ret);
+       if (ret < 0)
+               mlog_errno(ret);
        return ret;
 }
 
@@ -117,8 +112,6 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry,
        struct inode *inode = dentry->d_inode;
        struct buffer_head *bh = NULL;
 
-       mlog_entry_void();
-
        BUG_ON(!ocfs2_inode_is_fast_symlink(inode));
        target = ocfs2_fast_symlink_getlink(inode, &bh);
        if (IS_ERR(target)) {
@@ -142,7 +135,8 @@ bail:
        nd_set_link(nd, status ? ERR_PTR(status) : link);
        brelse(bh);
 
-       mlog_exit(status);
+       if (status)
+               mlog_errno(status);
        return NULL;
 }
 
index 902efb23b6a66cbe086e3d6f0b95fb883d6f95b2..3d635f4bbb201dba77cc79bd57feb67862744d4b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 
-#define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
index a0a120e82b9712fce6d128a4ab536be2b9dd2d0a..52eaf33d346fd5bdd0b5a9ee5e201f514c03aca5 100644 (file)
 #include <linux/buffer_head.h>
 #include <linux/rbtree.h>
 
-#define MLOG_MASK_PREFIX ML_UPTODATE
-
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
 
 #include "inode.h"
 #include "uptodate.h"
+#include "ocfs2_trace.h"
 
 struct ocfs2_meta_cache_item {
        struct rb_node  c_node;
@@ -152,8 +151,8 @@ static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root)
        while ((node = rb_last(root)) != NULL) {
                item = rb_entry(node, struct ocfs2_meta_cache_item, c_node);
 
-               mlog(0, "Purge item %llu\n",
-                    (unsigned long long) item->c_block);
+               trace_ocfs2_purge_copied_metadata_tree(
+                                       (unsigned long long) item->c_block);
 
                rb_erase(&item->c_node, root);
                kmem_cache_free(ocfs2_uptodate_cachep, item);
@@ -180,9 +179,9 @@ void ocfs2_metadata_cache_purge(struct ocfs2_caching_info *ci)
        tree = !(ci->ci_flags & OCFS2_CACHE_FL_INLINE);
        to_purge = ci->ci_num_cached;
 
-       mlog(0, "Purge %u %s items from Owner %llu\n", to_purge,
-            tree ? "array" : "tree",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci));
+       trace_ocfs2_metadata_cache_purge(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               to_purge, tree);
 
        /* If we're a tree, save off the root so that we can safely
         * initialize the cache. We do the work to free tree members
@@ -249,10 +248,10 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci,
 
        ocfs2_metadata_cache_lock(ci);
 
-       mlog(0, "Owner %llu, query block %llu (inline = %u)\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            (unsigned long long) bh->b_blocknr,
-            !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE));
+       trace_ocfs2_buffer_cached_begin(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long) bh->b_blocknr,
+               !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE));
 
        if (ci->ci_flags & OCFS2_CACHE_FL_INLINE)
                index = ocfs2_search_cache_array(ci, bh->b_blocknr);
@@ -261,7 +260,7 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci,
 
        ocfs2_metadata_cache_unlock(ci);
 
-       mlog(0, "index = %d, item = %p\n", index, item);
+       trace_ocfs2_buffer_cached_end(index, item);
 
        return (index != -1) || (item != NULL);
 }
@@ -306,8 +305,9 @@ static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci,
 {
        BUG_ON(ci->ci_num_cached >= OCFS2_CACHE_INFO_MAX_ARRAY);
 
-       mlog(0, "block %llu takes position %u\n", (unsigned long long) block,
-            ci->ci_num_cached);
+       trace_ocfs2_append_cache_array(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)block, ci->ci_num_cached);
 
        ci->ci_cache.ci_array[ci->ci_num_cached] = block;
        ci->ci_num_cached++;
@@ -324,8 +324,9 @@ static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci,
        struct rb_node **p = &ci->ci_cache.ci_tree.rb_node;
        struct ocfs2_meta_cache_item *tmp;
 
-       mlog(0, "Insert block %llu num = %u\n", (unsigned long long) block,
-            ci->ci_num_cached);
+       trace_ocfs2_insert_cache_tree(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)block, ci->ci_num_cached);
 
        while(*p) {
                parent = *p;
@@ -389,9 +390,9 @@ static void ocfs2_expand_cache(struct ocfs2_caching_info *ci,
                tree[i] = NULL;
        }
 
-       mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            ci->ci_flags, ci->ci_num_cached);
+       trace_ocfs2_expand_cache(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               ci->ci_flags, ci->ci_num_cached);
 }
 
 /* Slow path function - memory allocation is necessary. See the
@@ -405,9 +406,9 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci,
        struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] =
                { NULL, };
 
-       mlog(0, "Owner %llu, block %llu, expand = %d\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            (unsigned long long)block, expand_tree);
+       trace_ocfs2_set_buffer_uptodate(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)block, expand_tree);
 
        new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS);
        if (!new) {
@@ -433,7 +434,6 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci,
 
        ocfs2_metadata_cache_lock(ci);
        if (ocfs2_insert_can_use_array(ci)) {
-               mlog(0, "Someone cleared the tree underneath us\n");
                /* Ok, items were removed from the cache in between
                 * locks. Detect this and revert back to the fast path */
                ocfs2_append_cache_array(ci, block);
@@ -490,9 +490,9 @@ void ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci,
        if (ocfs2_buffer_cached(ci, bh))
                return;
 
-       mlog(0, "Owner %llu, inserting block %llu\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_set_buffer_uptodate_begin(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)bh->b_blocknr);
 
        /* No need to recheck under spinlock - insertion is guarded by
         * co_io_lock() */
@@ -542,8 +542,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci,
        BUG_ON(index >= ci->ci_num_cached);
        BUG_ON(!ci->ci_num_cached);
 
-       mlog(0, "remove index %d (num_cached = %u\n", index,
-            ci->ci_num_cached);
+       trace_ocfs2_remove_metadata_array(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               index, ci->ci_num_cached);
 
        ci->ci_num_cached--;
 
@@ -559,8 +560,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci,
 static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci,
                                       struct ocfs2_meta_cache_item *item)
 {
-       mlog(0, "remove block %llu from tree\n",
-            (unsigned long long) item->c_block);
+       trace_ocfs2_remove_metadata_tree(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long)item->c_block);
 
        rb_erase(&item->c_node, &ci->ci_cache.ci_tree);
        ci->ci_num_cached--;
@@ -573,10 +575,10 @@ static void ocfs2_remove_block_from_cache(struct ocfs2_caching_info *ci,
        struct ocfs2_meta_cache_item *item = NULL;
 
        ocfs2_metadata_cache_lock(ci);
-       mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n",
-            (unsigned long long)ocfs2_metadata_cache_owner(ci),
-            (unsigned long long) block, ci->ci_num_cached,
-            ci->ci_flags & OCFS2_CACHE_FL_INLINE);
+       trace_ocfs2_remove_block_from_cache(
+               (unsigned long long)ocfs2_metadata_cache_owner(ci),
+               (unsigned long long) block, ci->ci_num_cached,
+               ci->ci_flags);
 
        if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) {
                index = ocfs2_search_cache_array(ci, block);
@@ -626,9 +628,6 @@ int __init init_ocfs2_uptodate_cache(void)
        if (!ocfs2_uptodate_cachep)
                return -ENOMEM;
 
-       mlog(0, "%u inlined cache items per inode.\n",
-            OCFS2_CACHE_INFO_MAX_ARRAY);
-
        return 0;
 }
 
index 6bb602486c6bdf92a635855d120d8c724b34aef5..57a215dc2d9b73039fe376a49fdc5bc01ea44359 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/string.h>
 #include <linux/security.h>
 
-#define MLOG_MASK_PREFIX ML_XATTR
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -57,6 +56,7 @@
 #include "xattr.h"
 #include "refcounttree.h"
 #include "acl.h"
+#include "ocfs2_trace.h"
 
 struct ocfs2_xattr_def_value_root {
        struct ocfs2_xattr_value_root   xv;
@@ -474,8 +474,7 @@ static int ocfs2_validate_xattr_block(struct super_block *sb,
        struct ocfs2_xattr_block *xb =
                (struct ocfs2_xattr_block *)bh->b_data;
 
-       mlog(0, "Validating xattr block %llu\n",
-            (unsigned long long)bh->b_blocknr);
+       trace_ocfs2_validate_xattr_block((unsigned long long)bh->b_blocknr);
 
        BUG_ON(!buffer_uptodate(bh));
 
@@ -715,11 +714,11 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,
        u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters);
        struct ocfs2_extent_tree et;
 
-       mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
-
        ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb);
 
        while (clusters_to_add) {
+               trace_ocfs2_xattr_extend_allocation(clusters_to_add);
+
                status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh,
                                       OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
@@ -754,8 +753,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,
                         */
                        BUG_ON(why == RESTART_META);
 
-                       mlog(0, "restarting xattr value extension for %u"
-                            " clusters,.\n", clusters_to_add);
                        credits = ocfs2_calc_extend_credits(inode->i_sb,
                                                            &vb->vb_xv->xr_list,
                                                            clusters_to_add);
@@ -3246,8 +3243,8 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode,
        }
 
        meta_add += extra_meta;
-       mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, "
-            "credits = %d\n", xi->xi_name, meta_add, clusters_add, *credits);
+       trace_ocfs2_init_xattr_set_ctxt(xi->xi_name, meta_add,
+                                       clusters_add, *credits);
 
        if (meta_add) {
                ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add,
@@ -3887,8 +3884,10 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
 
        if (found) {
                xs->here = &xs->header->xh_entries[index];
-               mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name,
-                    (unsigned long long)bucket_blkno(xs->bucket), index);
+               trace_ocfs2_xattr_bucket_find(OCFS2_I(inode)->ip_blkno,
+                       name, name_index, name_hash,
+                       (unsigned long long)bucket_blkno(xs->bucket),
+                       index);
        } else
                ret = -ENODATA;
 
@@ -3915,8 +3914,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode,
        if (le16_to_cpu(el->l_next_free_rec) == 0)
                return -ENODATA;
 
-       mlog(0, "find xattr %s, hash = %u, index = %d in xattr tree\n",
-            name, name_hash, name_index);
+       trace_ocfs2_xattr_index_block_find(OCFS2_I(inode)->ip_blkno,
+                                       name, name_index, name_hash,
+                                       (unsigned long long)root_bh->b_blocknr,
+                                       -1);
 
        ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &first_hash,
                                  &num_clusters, el);
@@ -3927,9 +3928,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode,
 
        BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash);
 
-       mlog(0, "find xattr extent rec %u clusters from %llu, the first hash "
-            "in the rec is %u\n", num_clusters, (unsigned long long)p_blkno,
-            first_hash);
+       trace_ocfs2_xattr_index_block_find_rec(OCFS2_I(inode)->ip_blkno,
+                                       name, name_index, first_hash,
+                                       (unsigned long long)p_blkno,
+                                       num_clusters);
 
        ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash,
                                      p_blkno, first_hash, num_clusters, xs);
@@ -3955,8 +3957,9 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
                return -ENOMEM;
        }
 
-       mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n",
-            clusters, (unsigned long long)blkno);
+       trace_ocfs2_iterate_xattr_buckets(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               (unsigned long long)blkno, clusters);
 
        for (i = 0; i < num_buckets; i++, blkno += bucket->bu_blocks) {
                ret = ocfs2_read_xattr_bucket(bucket, blkno);
@@ -3972,8 +3975,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
                if (i == 0)
                        num_buckets = le16_to_cpu(bucket_xh(bucket)->xh_num_buckets);
 
-               mlog(0, "iterating xattr bucket %llu, first hash %u\n",
-                    (unsigned long long)blkno,
+               trace_ocfs2_iterate_xattr_bucket((unsigned long long)blkno,
                     le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash));
                if (func) {
                        ret = func(inode, bucket, para);
@@ -4173,9 +4175,9 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
        char *src = xb_bh->b_data;
        char *target = bucket_block(bucket, blks - 1);
 
-       mlog(0, "cp xattr from block %llu to bucket %llu\n",
-            (unsigned long long)xb_bh->b_blocknr,
-            (unsigned long long)bucket_blkno(bucket));
+       trace_ocfs2_cp_xattr_block_to_bucket_begin(
+                               (unsigned long long)xb_bh->b_blocknr,
+                               (unsigned long long)bucket_blkno(bucket));
 
        for (i = 0; i < blks; i++)
                memset(bucket_block(bucket, i), 0, blocksize);
@@ -4211,8 +4213,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
        for (i = 0; i < count; i++)
                le16_add_cpu(&xh->xh_entries[i].xe_name_offset, off_change);
 
-       mlog(0, "copy entry: start = %u, size = %u, offset_change = %u\n",
-            offset, size, off_change);
+       trace_ocfs2_cp_xattr_block_to_bucket_end(offset, size, off_change);
 
        sort(target + offset, count, sizeof(struct ocfs2_xattr_entry),
             cmp_xe, swap_xe);
@@ -4261,8 +4262,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
        struct ocfs2_xattr_tree_root *xr;
        u16 xb_flags = le16_to_cpu(xb->xb_flags);
 
-       mlog(0, "create xattr index block for %llu\n",
-            (unsigned long long)xb_bh->b_blocknr);
+       trace_ocfs2_xattr_create_index_block_begin(
+                               (unsigned long long)xb_bh->b_blocknr);
 
        BUG_ON(xb_flags & OCFS2_XATTR_INDEXED);
        BUG_ON(!xs->bucket);
@@ -4295,8 +4296,7 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
         */
        blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off);
 
-       mlog(0, "allocate 1 cluster from %llu to xattr block\n",
-            (unsigned long long)blkno);
+       trace_ocfs2_xattr_create_index_block((unsigned long long)blkno);
 
        ret = ocfs2_init_xattr_bucket(xs->bucket, blkno);
        if (ret) {
@@ -4400,8 +4400,7 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode,
        entries = (char *)xh->xh_entries;
        xh_free_start = le16_to_cpu(xh->xh_free_start);
 
-       mlog(0, "adjust xattr bucket in %llu, count = %u, "
-            "xh_free_start = %u, xh_name_value_len = %u.\n",
+       trace_ocfs2_defrag_xattr_bucket(
             (unsigned long long)blkno, le16_to_cpu(xh->xh_count),
             xh_free_start, le16_to_cpu(xh->xh_name_value_len));
 
@@ -4503,8 +4502,9 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode,
        BUG_ON(le16_to_cpu(bucket_xh(first)->xh_num_buckets) < num_buckets);
        BUG_ON(OCFS2_XATTR_BUCKET_SIZE == OCFS2_SB(sb)->s_clustersize);
 
-       mlog(0, "move half of xattrs in cluster %llu to %llu\n",
-            (unsigned long long)last_cluster_blkno, (unsigned long long)new_blkno);
+       trace_ocfs2_mv_xattr_bucket_cross_cluster(
+                               (unsigned long long)last_cluster_blkno,
+                               (unsigned long long)new_blkno);
 
        ret = ocfs2_mv_xattr_buckets(inode, handle, bucket_blkno(first),
                                     last_cluster_blkno, new_blkno,
@@ -4614,8 +4614,8 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
        struct ocfs2_xattr_entry *xe;
        int blocksize = inode->i_sb->s_blocksize;
 
-       mlog(0, "move some of xattrs from bucket %llu to %llu\n",
-            (unsigned long long)blk, (unsigned long long)new_blk);
+       trace_ocfs2_divide_xattr_bucket_begin((unsigned long long)blk,
+                                             (unsigned long long)new_blk);
 
        s_bucket = ocfs2_xattr_bucket_new(inode);
        t_bucket = ocfs2_xattr_bucket_new(inode);
@@ -4714,9 +4714,9 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
         */
        xe = &xh->xh_entries[start];
        len = sizeof(struct ocfs2_xattr_entry) * (count - start);
-       mlog(0, "mv xattr entry len %d from %d to %d\n", len,
-            (int)((char *)xe - (char *)xh),
-            (int)((char *)xh->xh_entries - (char *)xh));
+       trace_ocfs2_divide_xattr_bucket_move(len,
+                       (int)((char *)xe - (char *)xh),
+                       (int)((char *)xh->xh_entries - (char *)xh));
        memmove((char *)xh->xh_entries, (char *)xe, len);
        xe = &xh->xh_entries[count - start];
        len = sizeof(struct ocfs2_xattr_entry) * start;
@@ -4788,9 +4788,9 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
 
        BUG_ON(s_blkno == t_blkno);
 
-       mlog(0, "cp bucket %llu to %llu, target is %d\n",
-            (unsigned long long)s_blkno, (unsigned long long)t_blkno,
-            t_is_new);
+       trace_ocfs2_cp_xattr_bucket((unsigned long long)s_blkno,
+                                   (unsigned long long)t_blkno,
+                                   t_is_new);
 
        s_bucket = ocfs2_xattr_bucket_new(inode);
        t_bucket = ocfs2_xattr_bucket_new(inode);
@@ -4862,8 +4862,8 @@ static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle,
        int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
        struct ocfs2_xattr_bucket *old_first, *new_first;
 
-       mlog(0, "mv xattrs from cluster %llu to %llu\n",
-            (unsigned long long)last_blk, (unsigned long long)to_blk);
+       trace_ocfs2_mv_xattr_buckets((unsigned long long)last_blk,
+                                    (unsigned long long)to_blk);
 
        BUG_ON(start_bucket >= num_buckets);
        if (start_bucket) {
@@ -5013,9 +5013,9 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode,
 {
        int ret;
 
-       mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n",
-            (unsigned long long)bucket_blkno(first), prev_clusters,
-            (unsigned long long)new_blk);
+       trace_ocfs2_adjust_xattr_cross_cluster(
+                       (unsigned long long)bucket_blkno(first),
+                       (unsigned long long)new_blk, prev_clusters);
 
        if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) {
                ret = ocfs2_mv_xattr_bucket_cross_cluster(inode,
@@ -5088,10 +5088,10 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_extent_tree et;
 
-       mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, "
-            "previous xattr blkno = %llu\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno,
-            prev_cpos, (unsigned long long)bucket_blkno(first));
+       trace_ocfs2_add_new_xattr_cluster_begin(
+               (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               (unsigned long long)bucket_blkno(first),
+               prev_cpos, prev_clusters);
 
        ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(inode), root_bh);
 
@@ -5113,8 +5113,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
        BUG_ON(num_bits > clusters_to_add);
 
        block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n",
-            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       trace_ocfs2_add_new_xattr_cluster((unsigned long long)block, num_bits);
 
        if (bucket_blkno(first) + (prev_clusters * bpc) == block &&
            (prev_clusters + num_bits) << osb->s_clustersize_bits <=
@@ -5130,8 +5129,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
                 */
                v_start = prev_cpos + prev_clusters;
                *num_clusters = prev_clusters + num_bits;
-               mlog(0, "Add contiguous %u clusters to previous extent rec.\n",
-                    num_bits);
        } else {
                ret = ocfs2_adjust_xattr_cross_cluster(inode,
                                                       handle,
@@ -5147,8 +5144,8 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
                }
        }
 
-       mlog(0, "Insert %u clusters at block %llu for xattr at %u\n",
-            num_bits, (unsigned long long)block, v_start);
+       trace_ocfs2_add_new_xattr_cluster_insert((unsigned long long)block,
+                                                v_start, num_bits);
        ret = ocfs2_insert_extent(handle, &et, v_start, block,
                                  num_bits, 0, ctxt->meta_ac);
        if (ret < 0) {
@@ -5183,9 +5180,9 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode,
        u64 end_blk;
        u16 new_bucket = le16_to_cpu(bucket_xh(first)->xh_num_buckets);
 
-       mlog(0, "extend xattr bucket in %llu, xattr extend rec starting "
-            "from %llu, len = %u\n", (unsigned long long)target_blk,
-            (unsigned long long)bucket_blkno(first), num_clusters);
+       trace_ocfs2_extend_xattr_bucket((unsigned long long)target_blk,
+                                       (unsigned long long)bucket_blkno(first),
+                                       num_clusters, new_bucket);
 
        /* The extent must have room for an additional bucket */
        BUG_ON(new_bucket >=
@@ -5265,8 +5262,8 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode,
        /* The bucket at the front of the extent */
        struct ocfs2_xattr_bucket *first;
 
-       mlog(0, "Add new xattr bucket starting from %llu\n",
-            (unsigned long long)bucket_blkno(target));
+       trace_ocfs2_add_new_xattr_bucket(
+                               (unsigned long long)bucket_blkno(target));
 
        /* The first bucket of the original extent */
        first = ocfs2_xattr_bucket_new(inode);
@@ -5382,8 +5379,8 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
         * modified something.  We have to assume they did, and dirty
         * the whole bucket.  This leaves us in a consistent state.
         */
-       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
-            xe_off, (unsigned long long)bucket_blkno(bucket), len);
+       trace_ocfs2_xattr_bucket_value_truncate(
+                       (unsigned long long)bucket_blkno(bucket), xe_off, len);
        ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt);
        if (ret) {
                mlog_errno(ret);
@@ -5433,8 +5430,9 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode,
 
        ocfs2_init_dealloc_ctxt(&dealloc);
 
-       mlog(0, "rm xattr extent rec at %u len = %u, start from %llu\n",
-            cpos, len, (unsigned long long)blkno);
+       trace_ocfs2_rm_xattr_cluster(
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)blkno, cpos, len);
 
        ocfs2_remove_xattr_clusters_from_cache(INODE_CACHE(inode), blkno,
                                               len);
@@ -5538,7 +5536,7 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode,
        int ret;
        struct ocfs2_xa_loc loc;
 
-       mlog_entry("Set xattr %s in xattr bucket\n", xi->xi_name);
+       trace_ocfs2_xattr_set_entry_bucket(xi->xi_name);
 
        ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
                                       xs->not_found ? NULL : xs->here);
@@ -5570,7 +5568,6 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode,
 
 
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -5581,7 +5578,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
 {
        int ret;
 
-       mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name);
+       trace_ocfs2_xattr_set_entry_index_block(xi->xi_name);
 
        ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
        if (!ret)
@@ -5637,7 +5634,6 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
                mlog_errno(ret);
 
 out:
-       mlog_exit(ret);
        return ret;
 }
 
@@ -6041,9 +6037,9 @@ static int ocfs2_xattr_bucket_value_refcount(struct inode *inode,
        if (ocfs2_meta_ecc(OCFS2_SB(inode->i_sb)))
                p = &refcount;
 
-       mlog(0, "refcount bucket %llu, count = %u\n",
-            (unsigned long long)bucket_blkno(bucket),
-            le16_to_cpu(xh->xh_count));
+       trace_ocfs2_xattr_bucket_value_refcount(
+                               (unsigned long long)bucket_blkno(bucket),
+                               le16_to_cpu(xh->xh_count));
        for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
                xe = &xh->xh_entries[i];
 
@@ -6339,8 +6335,8 @@ static int ocfs2_reflink_xattr_header(handle_t *handle,
        u32 clusters, cpos, p_cluster, num_clusters;
        unsigned int ext_flags = 0;
 
-       mlog(0, "reflink xattr in container %llu, count = %u\n",
-            (unsigned long long)old_bh->b_blocknr, le16_to_cpu(xh->xh_count));
+       trace_ocfs2_reflink_xattr_header((unsigned long long)old_bh->b_blocknr,
+                                        le16_to_cpu(xh->xh_count));
 
        last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)];
        for (i = 0, j = 0; i < le16_to_cpu(xh->xh_count); i++, j++) {
@@ -6540,8 +6536,8 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
                goto out;
        }
 
-       mlog(0, "create new xattr block for inode %llu, index = %d\n",
-            (unsigned long long)fe_bh->b_blocknr, indexed);
+       trace_ocfs2_create_empty_xattr_block(
+                               (unsigned long long)fe_bh->b_blocknr, indexed);
        ret = ocfs2_create_xattr_block(inode, fe_bh, &ctxt, indexed,
                                       ret_bh);
        if (ret)
@@ -6952,8 +6948,8 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,
                if (ret)
                        mlog_errno(ret);
 
-               mlog(0, "insert new xattr extent rec start %llu len %u to %u\n",
-                    (unsigned long long)new_blkno, num_clusters, reflink_cpos);
+               trace_ocfs2_reflink_xattr_buckets((unsigned long long)new_blkno,
+                                                 num_clusters, reflink_cpos);
 
                len -= num_clusters;
                blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters);
@@ -6982,8 +6978,7 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,
        struct ocfs2_alloc_context *data_ac = NULL;
        struct ocfs2_extent_tree et;
 
-       mlog(0, "reflink xattr buckets %llu len %u\n",
-            (unsigned long long)blkno, len);
+       trace_ocfs2_reflink_xattr_rec((unsigned long long)blkno, len);
 
        ocfs2_init_xattr_tree_extent_tree(&et,
                                          INODE_CACHE(args->reflink->new_inode),
index 7c708a418acc38412f4a4d77626be3dc4b39e03f..2e7addfd9803559ca03a2527aaab161006e3b482 100644 (file)
@@ -182,7 +182,8 @@ static void m_stop(struct seq_file *m, void *v)
        struct proc_maps_private *priv = m->private;
        struct vm_area_struct *vma = v;
 
-       vma_stop(priv, vma);
+       if (!IS_ERR(vma))
+               vma_stop(priv, vma);
        if (priv->task)
                put_task_struct(priv->task);
 }
index c05324d3282c0bae23ac943b8b1b47d7e9dfe416..596bb2c9de429f76e5c1642aa545906a673956a2 100644 (file)
@@ -93,75 +93,6 @@ xfs_buf_vmap_len(
        return (bp->b_page_count * PAGE_SIZE) - bp->b_offset;
 }
 
-/*
- *     Page Region interfaces.
- *
- *     For pages in filesystems where the blocksize is smaller than the
- *     pagesize, we use the page->private field (long) to hold a bitmap
- *     of uptodate regions within the page.
- *
- *     Each such region is "bytes per page / bits per long" bytes long.
- *
- *     NBPPR == number-of-bytes-per-page-region
- *     BTOPR == bytes-to-page-region (rounded up)
- *     BTOPRT == bytes-to-page-region-truncated (rounded down)
- */
-#if (BITS_PER_LONG == 32)
-#define PRSHIFT                (PAGE_CACHE_SHIFT - 5)  /* (32 == 1<<5) */
-#elif (BITS_PER_LONG == 64)
-#define PRSHIFT                (PAGE_CACHE_SHIFT - 6)  /* (64 == 1<<6) */
-#else
-#error BITS_PER_LONG must be 32 or 64
-#endif
-#define NBPPR          (PAGE_CACHE_SIZE/BITS_PER_LONG)
-#define BTOPR(b)       (((unsigned int)(b) + (NBPPR - 1)) >> PRSHIFT)
-#define BTOPRT(b)      (((unsigned int)(b) >> PRSHIFT))
-
-STATIC unsigned long
-page_region_mask(
-       size_t          offset,
-       size_t          length)
-{
-       unsigned long   mask;
-       int             first, final;
-
-       first = BTOPR(offset);
-       final = BTOPRT(offset + length - 1);
-       first = min(first, final);
-
-       mask = ~0UL;
-       mask <<= BITS_PER_LONG - (final - first);
-       mask >>= BITS_PER_LONG - (final);
-
-       ASSERT(offset + length <= PAGE_CACHE_SIZE);
-       ASSERT((final - first) < BITS_PER_LONG && (final - first) >= 0);
-
-       return mask;
-}
-
-STATIC void
-set_page_region(
-       struct page     *page,
-       size_t          offset,
-       size_t          length)
-{
-       set_page_private(page,
-               page_private(page) | page_region_mask(offset, length));
-       if (page_private(page) == ~0UL)
-               SetPageUptodate(page);
-}
-
-STATIC int
-test_page_region(
-       struct page     *page,
-       size_t          offset,
-       size_t          length)
-{
-       unsigned long   mask = page_region_mask(offset, length);
-
-       return (mask && (page_private(page) & mask) == mask);
-}
-
 /*
  * xfs_buf_lru_add - add a buffer to the LRU.
  *
@@ -332,7 +263,7 @@ xfs_buf_free(
 
        ASSERT(list_empty(&bp->b_lru));
 
-       if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
+       if (bp->b_flags & _XBF_PAGES) {
                uint            i;
 
                if (xfs_buf_is_vmapped(bp))
@@ -342,25 +273,22 @@ xfs_buf_free(
                for (i = 0; i < bp->b_page_count; i++) {
                        struct page     *page = bp->b_pages[i];
 
-                       if (bp->b_flags & _XBF_PAGE_CACHE)
-                               ASSERT(!PagePrivate(page));
-                       page_cache_release(page);
+                       __free_page(page);
                }
-       }
+       } else if (bp->b_flags & _XBF_KMEM)
+               kmem_free(bp->b_addr);
        _xfs_buf_free_pages(bp);
        xfs_buf_deallocate(bp);
 }
 
 /*
- *     Finds all pages for buffer in question and builds it's page list.
+ * Allocates all the pages for buffer in question and builds it's page list.
  */
 STATIC int
-_xfs_buf_lookup_pages(
+xfs_buf_allocate_memory(
        xfs_buf_t               *bp,
        uint                    flags)
 {
-       struct address_space    *mapping = bp->b_target->bt_mapping;
-       size_t                  blocksize = bp->b_target->bt_bsize;
        size_t                  size = bp->b_count_desired;
        size_t                  nbytes, offset;
        gfp_t                   gfp_mask = xb_to_gfp(flags);
@@ -369,29 +297,55 @@ _xfs_buf_lookup_pages(
        xfs_off_t               end;
        int                     error;
 
+       /*
+        * for buffers that are contained within a single page, just allocate
+        * the memory from the heap - there's no need for the complexity of
+        * page arrays to keep allocation down to order 0.
+        */
+       if (bp->b_buffer_length < PAGE_SIZE) {
+               bp->b_addr = kmem_alloc(bp->b_buffer_length, xb_to_km(flags));
+               if (!bp->b_addr) {
+                       /* low memory - use alloc_page loop instead */
+                       goto use_alloc_page;
+               }
+
+               if (((unsigned long)(bp->b_addr + bp->b_buffer_length - 1) &
+                                                               PAGE_MASK) !=
+                   ((unsigned long)bp->b_addr & PAGE_MASK)) {
+                       /* b_addr spans two pages - use alloc_page instead */
+                       kmem_free(bp->b_addr);
+                       bp->b_addr = NULL;
+                       goto use_alloc_page;
+               }
+               bp->b_offset = offset_in_page(bp->b_addr);
+               bp->b_pages = bp->b_page_array;
+               bp->b_pages[0] = virt_to_page(bp->b_addr);
+               bp->b_page_count = 1;
+               bp->b_flags |= XBF_MAPPED | _XBF_KMEM;
+               return 0;
+       }
+
+use_alloc_page:
        end = bp->b_file_offset + bp->b_buffer_length;
        page_count = xfs_buf_btoc(end) - xfs_buf_btoct(bp->b_file_offset);
-
        error = _xfs_buf_get_pages(bp, page_count, flags);
        if (unlikely(error))
                return error;
-       bp->b_flags |= _XBF_PAGE_CACHE;
 
        offset = bp->b_offset;
-       first = bp->b_file_offset >> PAGE_CACHE_SHIFT;
+       first = bp->b_file_offset >> PAGE_SHIFT;
+       bp->b_flags |= _XBF_PAGES;
 
        for (i = 0; i < bp->b_page_count; i++) {
                struct page     *page;
                uint            retries = 0;
-
-             retry:
-               page = find_or_create_page(mapping, first + i, gfp_mask);
+retry:
+               page = alloc_page(gfp_mask);
                if (unlikely(page == NULL)) {
                        if (flags & XBF_READ_AHEAD) {
                                bp->b_page_count = i;
-                               for (i = 0; i < bp->b_page_count; i++)
-                                       unlock_page(bp->b_pages[i]);
-                               return -ENOMEM;
+                               error = ENOMEM;
+                               goto out_free_pages;
                        }
 
                        /*
@@ -412,33 +366,16 @@ _xfs_buf_lookup_pages(
 
                XFS_STATS_INC(xb_page_found);
 
-               nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset);
+               nbytes = min_t(size_t, size, PAGE_SIZE - offset);
                size -= nbytes;
-
-               ASSERT(!PagePrivate(page));
-               if (!PageUptodate(page)) {
-                       page_count--;
-                       if (blocksize >= PAGE_CACHE_SIZE) {
-                               if (flags & XBF_READ)
-                                       bp->b_flags |= _XBF_PAGE_LOCKED;
-                       } else if (!PagePrivate(page)) {
-                               if (test_page_region(page, offset, nbytes))
-                                       page_count++;
-                       }
-               }
-
                bp->b_pages[i] = page;
                offset = 0;
        }
+       return 0;
 
-       if (!(bp->b_flags & _XBF_PAGE_LOCKED)) {
-               for (i = 0; i < bp->b_page_count; i++)
-                       unlock_page(bp->b_pages[i]);
-       }
-
-       if (page_count == bp->b_page_count)
-               bp->b_flags |= XBF_DONE;
-
+out_free_pages:
+       for (i = 0; i < bp->b_page_count; i++)
+               __free_page(bp->b_pages[i]);
        return error;
 }
 
@@ -450,14 +387,23 @@ _xfs_buf_map_pages(
        xfs_buf_t               *bp,
        uint                    flags)
 {
-       /* A single page buffer is always mappable */
+       ASSERT(bp->b_flags & _XBF_PAGES);
        if (bp->b_page_count == 1) {
+               /* A single page buffer is always mappable */
                bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
                bp->b_flags |= XBF_MAPPED;
        } else if (flags & XBF_MAPPED) {
-               bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
-                                       -1, PAGE_KERNEL);
-               if (unlikely(bp->b_addr == NULL))
+               int retried = 0;
+
+               do {
+                       bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
+                                               -1, PAGE_KERNEL);
+                       if (bp->b_addr)
+                               break;
+                       vm_unmap_aliases();
+               } while (retried++ <= 1);
+
+               if (!bp->b_addr)
                        return -ENOMEM;
                bp->b_addr += bp->b_offset;
                bp->b_flags |= XBF_MAPPED;
@@ -568,9 +514,14 @@ found:
                }
        }
 
+       /*
+        * if the buffer is stale, clear all the external state associated with
+        * it. We need to keep flags such as how we allocated the buffer memory
+        * intact here.
+        */
        if (bp->b_flags & XBF_STALE) {
                ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0);
-               bp->b_flags &= XBF_MAPPED;
+               bp->b_flags &= XBF_MAPPED | _XBF_KMEM | _XBF_PAGES;
        }
 
        trace_xfs_buf_find(bp, flags, _RET_IP_);
@@ -591,7 +542,7 @@ xfs_buf_get(
        xfs_buf_flags_t         flags)
 {
        xfs_buf_t               *bp, *new_bp;
-       int                     error = 0, i;
+       int                     error = 0;
 
        new_bp = xfs_buf_allocate(flags);
        if (unlikely(!new_bp))
@@ -599,7 +550,7 @@ xfs_buf_get(
 
        bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);
        if (bp == new_bp) {
-               error = _xfs_buf_lookup_pages(bp, flags);
+               error = xfs_buf_allocate_memory(bp, flags);
                if (error)
                        goto no_buffer;
        } else {
@@ -608,9 +559,6 @@ xfs_buf_get(
                        return NULL;
        }
 
-       for (i = 0; i < bp->b_page_count; i++)
-               mark_page_accessed(bp->b_pages[i]);
-
        if (!(bp->b_flags & XBF_MAPPED)) {
                error = _xfs_buf_map_pages(bp, flags);
                if (unlikely(error)) {
@@ -711,8 +659,7 @@ xfs_buf_readahead(
 {
        struct backing_dev_info *bdi;
 
-       bdi = target->bt_mapping->backing_dev_info;
-       if (bdi_read_congested(bdi))
+       if (bdi_read_congested(target->bt_bdi))
                return;
 
        xfs_buf_read(target, ioff, isize,
@@ -790,10 +737,10 @@ xfs_buf_associate_memory(
        size_t                  buflen;
        int                     page_count;
 
-       pageaddr = (unsigned long)mem & PAGE_CACHE_MASK;
+       pageaddr = (unsigned long)mem & PAGE_MASK;
        offset = (unsigned long)mem - pageaddr;
-       buflen = PAGE_CACHE_ALIGN(len + offset);
-       page_count = buflen >> PAGE_CACHE_SHIFT;
+       buflen = PAGE_ALIGN(len + offset);
+       page_count = buflen >> PAGE_SHIFT;
 
        /* Free any previous set of page pointers */
        if (bp->b_pages)
@@ -810,13 +757,12 @@ xfs_buf_associate_memory(
 
        for (i = 0; i < bp->b_page_count; i++) {
                bp->b_pages[i] = mem_to_page((void *)pageaddr);
-               pageaddr += PAGE_CACHE_SIZE;
+               pageaddr += PAGE_SIZE;
        }
 
        bp->b_count_desired = len;
        bp->b_buffer_length = buflen;
        bp->b_flags |= XBF_MAPPED;
-       bp->b_flags &= ~_XBF_PAGE_LOCKED;
 
        return 0;
 }
@@ -923,20 +869,7 @@ xfs_buf_rele(
 
 
 /*
- *     Mutual exclusion on buffers.  Locking model:
- *
- *     Buffers associated with inodes for which buffer locking
- *     is not enabled are not protected by semaphores, and are
- *     assumed to be exclusively owned by the caller.  There is a
- *     spinlock in the buffer, used by the caller when concurrent
- *     access is possible.
- */
-
-/*
- *     Locks a buffer object, if it is not already locked.  Note that this in
- *     no way locks the underlying pages, so it is only useful for
- *     synchronizing concurrent use of buffer objects, not for synchronizing
- *     independent access to the underlying pages.
+ *     Lock a buffer object, if it is not already locked.
  *
  *     If we come across a stale, pinned, locked buffer, we know that we are
  *     being asked to lock a buffer that has been reallocated. Because it is
@@ -970,10 +903,7 @@ xfs_buf_lock_value(
 }
 
 /*
- *     Locks a buffer object.
- *     Note that this in no way locks the underlying pages, so it is only
- *     useful for synchronizing concurrent use of buffer objects, not for
- *     synchronizing independent access to the underlying pages.
+ *     Lock a buffer object.
  *
  *     If we come across a stale, pinned, locked buffer, we know that we
  *     are being asked to lock a buffer that has been reallocated. Because
@@ -1246,10 +1176,8 @@ _xfs_buf_ioend(
        xfs_buf_t               *bp,
        int                     schedule)
 {
-       if (atomic_dec_and_test(&bp->b_io_remaining) == 1) {
-               bp->b_flags &= ~_XBF_PAGE_LOCKED;
+       if (atomic_dec_and_test(&bp->b_io_remaining) == 1)
                xfs_buf_ioend(bp, schedule);
-       }
 }
 
 STATIC void
@@ -1258,35 +1186,12 @@ xfs_buf_bio_end_io(
        int                     error)
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
-       unsigned int            blocksize = bp->b_target->bt_bsize;
-       struct bio_vec          *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
 
        xfs_buf_ioerror(bp, -error);
 
        if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
                invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
 
-       do {
-               struct page     *page = bvec->bv_page;
-
-               ASSERT(!PagePrivate(page));
-               if (unlikely(bp->b_error)) {
-                       if (bp->b_flags & XBF_READ)
-                               ClearPageUptodate(page);
-               } else if (blocksize >= PAGE_CACHE_SIZE) {
-                       SetPageUptodate(page);
-               } else if (!PagePrivate(page) &&
-                               (bp->b_flags & _XBF_PAGE_CACHE)) {
-                       set_page_region(page, bvec->bv_offset, bvec->bv_len);
-               }
-
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-
-               if (bp->b_flags & _XBF_PAGE_LOCKED)
-                       unlock_page(page);
-       } while (bvec >= bio->bi_io_vec);
-
        _xfs_buf_ioend(bp, 1);
        bio_put(bio);
 }
@@ -1300,7 +1205,6 @@ _xfs_buf_ioapply(
        int                     offset = bp->b_offset;
        int                     size = bp->b_count_desired;
        sector_t                sector = bp->b_bn;
-       unsigned int            blocksize = bp->b_target->bt_bsize;
 
        total_nr_pages = bp->b_page_count;
        map_i = 0;
@@ -1321,29 +1225,6 @@ _xfs_buf_ioapply(
                     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
        }
 
-       /* Special code path for reading a sub page size buffer in --
-        * we populate up the whole page, and hence the other metadata
-        * in the same page.  This optimization is only valid when the
-        * filesystem block size is not smaller than the page size.
-        */
-       if ((bp->b_buffer_length < PAGE_CACHE_SIZE) &&
-           ((bp->b_flags & (XBF_READ|_XBF_PAGE_LOCKED)) ==
-             (XBF_READ|_XBF_PAGE_LOCKED)) &&
-           (blocksize >= PAGE_CACHE_SIZE)) {
-               bio = bio_alloc(GFP_NOIO, 1);
-
-               bio->bi_bdev = bp->b_target->bt_bdev;
-               bio->bi_sector = sector - (offset >> BBSHIFT);
-               bio->bi_end_io = xfs_buf_bio_end_io;
-               bio->bi_private = bp;
-
-               bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0);
-               size = 0;
-
-               atomic_inc(&bp->b_io_remaining);
-
-               goto submit_io;
-       }
 
 next_chunk:
        atomic_inc(&bp->b_io_remaining);
@@ -1357,8 +1238,9 @@ next_chunk:
        bio->bi_end_io = xfs_buf_bio_end_io;
        bio->bi_private = bp;
 
+
        for (; size && nr_pages; nr_pages--, map_i++) {
-               int     rbytes, nbytes = PAGE_CACHE_SIZE - offset;
+               int     rbytes, nbytes = PAGE_SIZE - offset;
 
                if (nbytes > size)
                        nbytes = size;
@@ -1373,7 +1255,6 @@ next_chunk:
                total_nr_pages--;
        }
 
-submit_io:
        if (likely(bio->bi_size)) {
                if (xfs_buf_is_vmapped(bp)) {
                        flush_kernel_vmap_range(bp->b_addr,
@@ -1383,18 +1264,7 @@ submit_io:
                if (size)
                        goto next_chunk;
        } else {
-               /*
-                * if we get here, no pages were added to the bio. However,
-                * we can't just error out here - if the pages are locked then
-                * we have to unlock them otherwise we can hang on a later
-                * access to the page.
-                */
                xfs_buf_ioerror(bp, EIO);
-               if (bp->b_flags & _XBF_PAGE_LOCKED) {
-                       int i;
-                       for (i = 0; i < bp->b_page_count; i++)
-                               unlock_page(bp->b_pages[i]);
-               }
                bio_put(bio);
        }
 }
@@ -1458,8 +1328,8 @@ xfs_buf_offset(
                return XFS_BUF_PTR(bp) + offset;
 
        offset += bp->b_offset;
-       page = bp->b_pages[offset >> PAGE_CACHE_SHIFT];
-       return (xfs_caddr_t)page_address(page) + (offset & (PAGE_CACHE_SIZE-1));
+       page = bp->b_pages[offset >> PAGE_SHIFT];
+       return (xfs_caddr_t)page_address(page) + (offset & (PAGE_SIZE-1));
 }
 
 /*
@@ -1481,9 +1351,9 @@ xfs_buf_iomove(
                page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
                cpoff = xfs_buf_poff(boff + bp->b_offset);
                csize = min_t(size_t,
-                             PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
+                             PAGE_SIZE-cpoff, bp->b_count_desired-boff);
 
-               ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
+               ASSERT(((csize + cpoff) <= PAGE_SIZE));
 
                switch (mode) {
                case XBRW_ZERO:
@@ -1596,7 +1466,6 @@ xfs_free_buftarg(
        xfs_flush_buftarg(btp, 1);
        if (mp->m_flags & XFS_MOUNT_BARRIER)
                xfs_blkdev_issue_flush(btp);
-       iput(btp->bt_mapping->host);
 
        kthread_stop(btp->bt_task);
        kmem_free(btp);
@@ -1620,15 +1489,6 @@ xfs_setsize_buftarg_flags(
                return EINVAL;
        }
 
-       if (verbose &&
-           (PAGE_CACHE_SIZE / BITS_PER_LONG) > sectorsize) {
-               printk(KERN_WARNING
-                       "XFS: %u byte sectors in use on device %s.  "
-                       "This is suboptimal; %u or greater is ideal.\n",
-                       sectorsize, XFS_BUFTARG_NAME(btp),
-                       (unsigned int)PAGE_CACHE_SIZE / BITS_PER_LONG);
-       }
-
        return 0;
 }
 
@@ -1643,7 +1503,7 @@ xfs_setsize_buftarg_early(
        struct block_device     *bdev)
 {
        return xfs_setsize_buftarg_flags(btp,
-                       PAGE_CACHE_SIZE, bdev_logical_block_size(bdev), 0);
+                       PAGE_SIZE, bdev_logical_block_size(bdev), 0);
 }
 
 int
@@ -1655,40 +1515,6 @@ xfs_setsize_buftarg(
        return xfs_setsize_buftarg_flags(btp, blocksize, sectorsize, 1);
 }
 
-STATIC int
-xfs_mapping_buftarg(
-       xfs_buftarg_t           *btp,
-       struct block_device     *bdev)
-{
-       struct backing_dev_info *bdi;
-       struct inode            *inode;
-       struct address_space    *mapping;
-       static const struct address_space_operations mapping_aops = {
-               .migratepage = fail_migrate_page,
-       };
-
-       inode = new_inode(bdev->bd_inode->i_sb);
-       if (!inode) {
-               printk(KERN_WARNING
-                       "XFS: Cannot allocate mapping inode for device %s\n",
-                       XFS_BUFTARG_NAME(btp));
-               return ENOMEM;
-       }
-       inode->i_ino = get_next_ino();
-       inode->i_mode = S_IFBLK;
-       inode->i_bdev = bdev;
-       inode->i_rdev = bdev->bd_dev;
-       bdi = blk_get_backing_dev_info(bdev);
-       if (!bdi)
-               bdi = &default_backing_dev_info;
-       mapping = &inode->i_data;
-       mapping->a_ops = &mapping_aops;
-       mapping->backing_dev_info = bdi;
-       mapping_set_gfp_mask(mapping, GFP_NOFS);
-       btp->bt_mapping = mapping;
-       return 0;
-}
-
 STATIC int
 xfs_alloc_delwrite_queue(
        xfs_buftarg_t           *btp,
@@ -1717,12 +1543,14 @@ xfs_alloc_buftarg(
        btp->bt_mount = mp;
        btp->bt_dev =  bdev->bd_dev;
        btp->bt_bdev = bdev;
+       btp->bt_bdi = blk_get_backing_dev_info(bdev);
+       if (!btp->bt_bdi)
+               goto error;
+
        INIT_LIST_HEAD(&btp->bt_lru);
        spin_lock_init(&btp->bt_lru_lock);
        if (xfs_setsize_buftarg_early(btp, bdev))
                goto error;
-       if (xfs_mapping_buftarg(btp, bdev))
-               goto error;
        if (xfs_alloc_delwrite_queue(btp, fsname))
                goto error;
        btp->bt_shrinker.shrink = xfs_buftarg_shrink;
index cbe65950e5244bbf750482b0cf9f709032eeb1c0..a9a1c451264513961573fbf2879fbc68c9a68e9a 100644 (file)
@@ -61,30 +61,11 @@ typedef enum {
 #define XBF_DONT_BLOCK (1 << 16)/* do not block in current thread */
 
 /* flags used only internally */
-#define _XBF_PAGE_CACHE        (1 << 17)/* backed by pagecache */
 #define _XBF_PAGES     (1 << 18)/* backed by refcounted pages */
 #define        _XBF_RUN_QUEUES (1 << 19)/* run block device task queue */
+#define        _XBF_KMEM       (1 << 20)/* backed by heap memory */
 #define _XBF_DELWRI_Q  (1 << 21)/* buffer on delwri queue */
 
-/*
- * Special flag for supporting metadata blocks smaller than a FSB.
- *
- * In this case we can have multiple xfs_buf_t on a single page and
- * need to lock out concurrent xfs_buf_t readers as they only
- * serialise access to the buffer.
- *
- * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation
- * between reads of the page. Hence we can have one thread read the
- * page and modify it, but then race with another thread that thinks
- * the page is not up-to-date and hence reads it again.
- *
- * The result is that the first modifcation to the page is lost.
- * This sort of AGF/AGI reading race can happen when unlinking inodes
- * that require truncation and results in the AGI unlinked list
- * modifications being lost.
- */
-#define _XBF_PAGE_LOCKED       (1 << 22)
-
 typedef unsigned int xfs_buf_flags_t;
 
 #define XFS_BUF_FLAGS \
@@ -100,12 +81,10 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_LOCK,             "LOCK" },       /* should never be set */\
        { XBF_TRYLOCK,          "TRYLOCK" },    /* ditto */\
        { XBF_DONT_BLOCK,       "DONT_BLOCK" }, /* ditto */\
-       { _XBF_PAGE_CACHE,      "PAGE_CACHE" }, \
        { _XBF_PAGES,           "PAGES" }, \
        { _XBF_RUN_QUEUES,      "RUN_QUEUES" }, \
-       { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
-       { _XBF_PAGE_LOCKED,     "PAGE_LOCKED" }
-
+       { _XBF_KMEM,            "KMEM" }, \
+       { _XBF_DELWRI_Q,        "DELWRI_Q" }
 
 typedef enum {
        XBT_FORCE_SLEEP = 0,
@@ -120,7 +99,7 @@ typedef struct xfs_bufhash {
 typedef struct xfs_buftarg {
        dev_t                   bt_dev;
        struct block_device     *bt_bdev;
-       struct address_space    *bt_mapping;
+       struct backing_dev_info *bt_bdi;
        struct xfs_mount        *bt_mount;
        unsigned int            bt_bsize;
        unsigned int            bt_sshift;
@@ -139,17 +118,6 @@ typedef struct xfs_buftarg {
        unsigned int            bt_lru_nr;
 } xfs_buftarg_t;
 
-/*
- *     xfs_buf_t:  Buffer structure for pagecache-based buffers
- *
- * This buffer structure is used by the pagecache buffer management routines
- * to refer to an assembly of pages forming a logical buffer.
- *
- * The buffer structure is used on a temporary basis only, and discarded when
- * released.  The real data storage is recorded in the pagecache. Buffers are
- * hashed to the block device on which the file system resides.
- */
-
 struct xfs_buf;
 typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);
 
index a55c1b46b219b4a1ea4956008d25e5d5990289c5..52aadfbed13229b2f28202088958b12fe1a24fe5 100644 (file)
@@ -896,6 +896,7 @@ xfs_file_fallocate(
        xfs_flock64_t   bf;
        xfs_inode_t     *ip = XFS_I(inode);
        int             cmd = XFS_IOC_RESVSP;
+       int             attr_flags = XFS_ATTR_NOLOCK;
 
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
@@ -918,7 +919,10 @@ xfs_file_fallocate(
                        goto out_unlock;
        }
 
-       error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK);
+       if (file->f_flags & O_DSYNC)
+               attr_flags |= XFS_ATTR_SYNC;
+
+       error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags);
        if (error)
                goto out_unlock;
 
index 0ca0e3c024d7bac3993707dd7309b3fda9664a07..acca2c5ca3fa82618ef891e26998334640a88869 100644 (file)
@@ -624,6 +624,10 @@ xfs_ioc_space(
 
        if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
                attr_flags |= XFS_ATTR_NONBLOCK;
+
+       if (filp->f_flags & O_DSYNC)
+               attr_flags |= XFS_ATTR_SYNC;
+
        if (ioflags & IO_INVIS)
                attr_flags |= XFS_ATTR_DMI;
 
index 818c4cf2de863e5450ac75ad300a1c78bfdbca60..1ba5c451da36a094629f6130815a70a8ee047bb8 100644 (file)
@@ -1078,7 +1078,7 @@ xfs_fs_write_inode(
                        error = 0;
                        goto out_unlock;
                }
-               error = xfs_iflush(ip, 0);
+               error = xfs_iflush(ip, SYNC_TRYLOCK);
        }
 
  out_unlock:
@@ -1539,10 +1539,14 @@ xfs_fs_fill_super(
        if (error)
                goto out_free_sb;
 
-       error = xfs_mountfs(mp);
-       if (error)
-               goto out_filestream_unmount;
-
+       /*
+        * we must configure the block size in the superblock before we run the
+        * full mount process as the mount process can lookup and cache inodes.
+        * For the same reason we must also initialise the syncd and register
+        * the inode cache shrinker so that inodes can be reclaimed during
+        * operations like a quotacheck that iterate all inodes in the
+        * filesystem.
+        */
        sb->s_magic = XFS_SB_MAGIC;
        sb->s_blocksize = mp->m_sb.sb_blocksize;
        sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
@@ -1550,6 +1554,16 @@ xfs_fs_fill_super(
        sb->s_time_gran = 1;
        set_posix_acl_flag(sb);
 
+       error = xfs_syncd_init(mp);
+       if (error)
+               goto out_filestream_unmount;
+
+       xfs_inode_shrinker_register(mp);
+
+       error = xfs_mountfs(mp);
+       if (error)
+               goto out_syncd_stop;
+
        root = igrab(VFS_I(mp->m_rootip));
        if (!root) {
                error = ENOENT;
@@ -1565,14 +1579,11 @@ xfs_fs_fill_super(
                goto fail_vnrele;
        }
 
-       error = xfs_syncd_init(mp);
-       if (error)
-               goto fail_vnrele;
-
-       xfs_inode_shrinker_register(mp);
-
        return 0;
 
+ out_syncd_stop:
+       xfs_inode_shrinker_unregister(mp);
+       xfs_syncd_stop(mp);
  out_filestream_unmount:
        xfs_filestream_unmount(mp);
  out_free_sb:
@@ -1596,6 +1607,9 @@ xfs_fs_fill_super(
        }
 
  fail_unmount:
+       xfs_inode_shrinker_unregister(mp);
+       xfs_syncd_stop(mp);
+
        /*
         * Blow away any referenced inode in the filestreams cache.
         * This can and will cause log traffic as inodes go inactive
index 6c10f1d2e3d3a8e4e094c5153d90b5c8ac60973f..594cd822d84de225755006321e5b97ebfe35cf70 100644 (file)
@@ -761,8 +761,10 @@ xfs_reclaim_inode(
        struct xfs_perag        *pag,
        int                     sync_mode)
 {
-       int     error = 0;
+       int     error;
 
+restart:
+       error = 0;
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        if (!xfs_iflock_nowait(ip)) {
                if (!(sync_mode & SYNC_WAIT))
@@ -788,9 +790,31 @@ xfs_reclaim_inode(
        if (xfs_inode_clean(ip))
                goto reclaim;
 
-       /* Now we have an inode that needs flushing */
-       error = xfs_iflush(ip, sync_mode);
+       /*
+        * Now we have an inode that needs flushing.
+        *
+        * We do a nonblocking flush here even if we are doing a SYNC_WAIT
+        * reclaim as we can deadlock with inode cluster removal.
+        * xfs_ifree_cluster() can lock the inode buffer before it locks the
+        * ip->i_lock, and we are doing the exact opposite here. As a result,
+        * doing a blocking xfs_itobp() to get the cluster buffer will result
+        * in an ABBA deadlock with xfs_ifree_cluster().
+        *
+        * As xfs_ifree_cluser() must gather all inodes that are active in the
+        * cache to mark them stale, if we hit this case we don't actually want
+        * to do IO here - we want the inode marked stale so we can simply
+        * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush,
+        * just unlock the inode, back off and try again. Hopefully the next
+        * pass through will see the stale flag set on the inode.
+        */
+       error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode);
        if (sync_mode & SYNC_WAIT) {
+               if (error == EAGAIN) {
+                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+                       /* backoff longer than in xfs_ifree_cluster */
+                       delay(2);
+                       goto restart;
+               }
                xfs_iflock(ip);
                goto reclaim;
        }
index da871f5322368dffac20f1514a5966a45f26061e..742c8330994a82ff09bbc22f68695743751bc3eb 100644 (file)
@@ -2835,7 +2835,7 @@ xfs_iflush(
         * Get the buffer containing the on-disk inode.
         */
        error = xfs_itobp(mp, NULL, ip, &dip, &bp,
-                               (flags & SYNC_WAIT) ? XBF_LOCK : XBF_TRYLOCK);
+                               (flags & SYNC_TRYLOCK) ? XBF_TRYLOCK : XBF_LOCK);
        if (error || !bp) {
                xfs_ifunlock(ip);
                return error;
index fd4f398bd6f1d8d01cca49046a65991d4d696d77..46cc40131d4a43c91ec5eb1d188c46e967c5193c 100644 (file)
@@ -760,11 +760,11 @@ xfs_inode_item_push(
         * Push the inode to it's backing buffer. This will not remove the
         * inode from the AIL - a further push will be required to trigger a
         * buffer push. However, this allows all the dirty inodes to be pushed
-        * to the buffer before it is pushed to disk. THe buffer IO completion
-        * will pull th einode from the AIL, mark it clean and unlock the flush
+        * to the buffer before it is pushed to disk. The buffer IO completion
+        * will pull thinode from the AIL, mark it clean and unlock the flush
         * lock.
         */
-       (void) xfs_iflush(ip, 0);
+       (void) xfs_iflush(ip, SYNC_TRYLOCK);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 }
 
index 3bea66132334c91e83278a5c581fae7d399e1490..03b3b7f85a3b59b68a1d6ff99ba83ac38ac7094c 100644 (file)
@@ -383,7 +383,8 @@ xfs_trans_read_buf(
        bp = xfs_buf_read(target, blkno, len, flags | XBF_DONT_BLOCK);
        if (bp == NULL) {
                *bpp = NULL;
-               return 0;
+               return (flags & XBF_TRYLOCK) ?
+                                       0 : XFS_ERROR(ENOMEM);
        }
        if (XFS_BUF_GETERROR(bp) != 0) {
            XFS_BUF_SUPER_STALE(bp);
index 37d8146ee15b2022edecce33ffc896ed84c55e59..c48b4217ec47f652b3769ce912969a46a2924101 100644 (file)
@@ -2831,7 +2831,8 @@ xfs_change_file_space(
                ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       xfs_trans_set_sync(tp);
+       if (attr_flags & XFS_ATTR_SYNC)
+               xfs_trans_set_sync(tp);
 
        error = xfs_trans_commit(tp, 0);
 
index f6702927eee4735846fb678ae3057e4119dc0224..3bcd23353d6cec71d9306a61a469695ccd78e7ca 100644 (file)
@@ -18,6 +18,7 @@ int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);
 #define        XFS_ATTR_NONBLOCK       0x02    /* return EAGAIN if operation would block */
 #define XFS_ATTR_NOLOCK                0x04    /* Don't grab any conflicting locks */
 #define XFS_ATTR_NOACL         0x08    /* Don't call xfs_acl_chmod */
+#define XFS_ATTR_SYNC          0x10    /* synchronous operation required */
 
 int xfs_readlink(struct xfs_inode *ip, char *link);
 int xfs_release(struct xfs_inode *ip);
diff --git a/include/linux/bch.h b/include/linux/bch.h
new file mode 100644 (file)
index 0000000..295b4ef
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Generic binary BCH encoding/decoding library
+ *
+ * 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., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright Â© 2011 Parrot S.A.
+ *
+ * Author: Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * Description:
+ *
+ * This library provides runtime configurable encoding/decoding of binary
+ * Bose-Chaudhuri-Hocquenghem (BCH) codes.
+*/
+#ifndef _BCH_H
+#define _BCH_H
+
+#include <linux/types.h>
+
+/**
+ * struct bch_control - BCH control structure
+ * @m:          Galois field order
+ * @n:          maximum codeword size in bits (= 2^m-1)
+ * @t:          error correction capability in bits
+ * @ecc_bits:   ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
+ * @ecc_bytes:  ecc max size (m*t bits) in bytes
+ * @a_pow_tab:  Galois field GF(2^m) exponentiation lookup table
+ * @a_log_tab:  Galois field GF(2^m) log lookup table
+ * @mod8_tab:   remainder generator polynomial lookup tables
+ * @ecc_buf:    ecc parity words buffer
+ * @ecc_buf2:   ecc parity words buffer
+ * @xi_tab:     GF(2^m) base for solving degree 2 polynomial roots
+ * @syn:        syndrome buffer
+ * @cache:      log-based polynomial representation buffer
+ * @elp:        error locator polynomial
+ * @poly_2t:    temporary polynomials of degree 2t
+ */
+struct bch_control {
+       unsigned int    m;
+       unsigned int    n;
+       unsigned int    t;
+       unsigned int    ecc_bits;
+       unsigned int    ecc_bytes;
+/* private: */
+       uint16_t       *a_pow_tab;
+       uint16_t       *a_log_tab;
+       uint32_t       *mod8_tab;
+       uint32_t       *ecc_buf;
+       uint32_t       *ecc_buf2;
+       unsigned int   *xi_tab;
+       unsigned int   *syn;
+       int            *cache;
+       struct gf_poly *elp;
+       struct gf_poly *poly_2t[4];
+};
+
+struct bch_control *init_bch(int m, int t, unsigned int prim_poly);
+
+void free_bch(struct bch_control *bch);
+
+void encode_bch(struct bch_control *bch, const uint8_t *data,
+               unsigned int len, uint8_t *ecc);
+
+int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
+              const uint8_t *recv_ecc, const uint8_t *calc_ecc,
+              const unsigned int *syn, unsigned int *errloc);
+
+#endif /* _BCH_H */
index 6c507bea275f314f6bfa308b246c330f834e2ae7..6f70a6d3a16e49ccf368bc8f912b20e6b4989d1e 100644 (file)
  * @prot:       pointer to struct proto structure.
  */
 struct can_proto {
-       int              type;
-       int              protocol;
-       struct proto_ops *ops;
-       struct proto     *prot;
+       int type;
+       int protocol;
+       const struct proto_ops *ops;
+       struct proto *prot;
 };
 
 /* function prototypes for the CAN networklayer core (af_can.c) */
@@ -58,5 +58,6 @@ extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
                              void *data);
 
 extern int can_send(struct sk_buff *skb, int loop);
+extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 
 #endif /* CAN_CORE_H */
index ef44c7a0638cdaaf087a65e01476aca73d29239b..d18d673ebc78e90a617670c80ca93e0f854ed70f 100644 (file)
 
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.9"
+#define REL_VERSION "8.3.10"
 #define API_VERSION 88
 #define PRO_VERSION_MIN 86
-#define PRO_VERSION_MAX 95
+#define PRO_VERSION_MAX 96
 
 
 enum drbd_io_error_p {
@@ -96,8 +96,14 @@ enum drbd_on_no_data {
        OND_SUSPEND_IO
 };
 
+enum drbd_on_congestion {
+       OC_BLOCK,
+       OC_PULL_AHEAD,
+       OC_DISCONNECT,
+};
+
 /* KEEP the order, do not delete or insert. Only append. */
-enum drbd_ret_codes {
+enum drbd_ret_code {
        ERR_CODE_BASE           = 100,
        NO_ERROR                = 101,
        ERR_LOCAL_ADDR          = 102,
@@ -146,6 +152,9 @@ enum drbd_ret_codes {
        ERR_PERM                = 152,
        ERR_NEED_APV_93         = 153,
        ERR_STONITH_AND_PROT_A  = 154,
+       ERR_CONG_NOT_PROTO_A    = 155,
+       ERR_PIC_AFTER_DEP       = 156,
+       ERR_PIC_PEER_DEP        = 157,
 
        /* insert new ones above this line */
        AFTER_LAST_ERR_CODE
@@ -199,6 +208,10 @@ enum drbd_conns {
        C_VERIFY_T,
        C_PAUSED_SYNC_S,
        C_PAUSED_SYNC_T,
+
+       C_AHEAD,
+       C_BEHIND,
+
        C_MASK = 31
 };
 
@@ -259,7 +272,7 @@ union drbd_state {
        unsigned int i;
 };
 
-enum drbd_state_ret_codes {
+enum drbd_state_rv {
        SS_CW_NO_NEED = 4,
        SS_CW_SUCCESS = 3,
        SS_NOTHING_TO_DO = 2,
@@ -290,7 +303,7 @@ enum drbd_state_ret_codes {
 extern const char *drbd_conn_str(enum drbd_conns);
 extern const char *drbd_role_str(enum drbd_role);
 extern const char *drbd_disk_str(enum drbd_disk_state);
-extern const char *drbd_set_st_err_str(enum drbd_state_ret_codes);
+extern const char *drbd_set_st_err_str(enum drbd_state_rv);
 
 #define SHARED_SECRET_MAX 64
 
index 4ac33f34b77e478d42cd4038d1259965a7434742..bb264a5732de7257727d66caeea01c13927e4790 100644 (file)
@@ -16,7 +16,8 @@
 #define DEBUG_RANGE_CHECK 0
 
 #define DRBD_MINOR_COUNT_MIN 1
-#define DRBD_MINOR_COUNT_MAX 255
+#define DRBD_MINOR_COUNT_MAX 256
+#define DRBD_MINOR_COUNT_DEF 32
 
 #define DRBD_DIALOG_REFRESH_MIN 0
 #define DRBD_DIALOG_REFRESH_MAX 600
 #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT
 #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT
 #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR
+#define DRBD_ON_CONGESTION_DEF OC_BLOCK
 
 #define DRBD_MAX_BIO_BVECS_MIN 0
 #define DRBD_MAX_BIO_BVECS_MAX 128
 #define DRBD_C_MIN_RATE_MAX     (4 << 20)
 #define DRBD_C_MIN_RATE_DEF     4096
 
+#define DRBD_CONG_FILL_MIN     0
+#define DRBD_CONG_FILL_MAX     (10<<21) /* 10GByte in sectors */
+#define DRBD_CONG_FILL_DEF     0
+
+#define DRBD_CONG_EXTENTS_MIN  DRBD_AL_EXTENTS_MIN
+#define DRBD_CONG_EXTENTS_MAX  DRBD_AL_EXTENTS_MAX
+#define DRBD_CONG_EXTENTS_DEF  DRBD_AL_EXTENTS_DEF
+
 #undef RANGE
 #endif
index ade91107c9a5031f186257844dd8bfa03d95b572..ab6159e4fcf0c6122cf840aef801fef822b0ab46 100644 (file)
@@ -56,6 +56,9 @@ NL_PACKET(net_conf, 5,
        NL_INTEGER(     39,     T_MAY_IGNORE,   rr_conflict)
        NL_INTEGER(     40,     T_MAY_IGNORE,   ping_timeo)
        NL_INTEGER(     67,     T_MAY_IGNORE,   rcvbuf_size)
+       NL_INTEGER(     81,     T_MAY_IGNORE,   on_congestion)
+       NL_INTEGER(     82,     T_MAY_IGNORE,   cong_fill)
+       NL_INTEGER(     83,     T_MAY_IGNORE,   cong_extents)
          /* 59 addr_family was available in GIT, never released */
        NL_BIT(         60,     T_MANDATORY,    mind_af)
        NL_BIT(         27,     T_MAY_IGNORE,   want_lose)
@@ -66,7 +69,9 @@ NL_PACKET(net_conf, 5,
        NL_BIT(         70,     T_MANDATORY,    dry_run)
 )
 
-NL_PACKET(disconnect, 6, )
+NL_PACKET(disconnect, 6,
+       NL_BIT(         84,     T_MAY_IGNORE,   force)
+)
 
 NL_PACKET(resize, 7,
        NL_INT64(               29,     T_MAY_IGNORE,   resize_size)
@@ -143,9 +148,13 @@ NL_PACKET(new_c_uuid, 26,
        NL_BIT(         63,     T_MANDATORY,    clear_bm)
 )
 
+#ifdef NL_RESPONSE
+NL_RESPONSE(return_code_only, 27)
+#endif
+
 #undef NL_PACKET
 #undef NL_INTEGER
 #undef NL_INT64
 #undef NL_BIT
 #undef NL_STRING
-
+#undef NL_RESPONSE
index fcdff8410e99ddad7f1dac756bd915aefce5c494..f14a165e82dc162ef0306d6dc8d9d7266a816387 100644 (file)
@@ -7,6 +7,7 @@
 /* declare packet_type enums */
 enum packet_types {
 #define NL_PACKET(name, number, fields) P_ ## name = number,
+#define NL_RESPONSE(name, number) P_ ## name = number,
 #define NL_INTEGER(pn, pr, member)
 #define NL_INT64(pn, pr, member)
 #define NL_BIT(pn, pr, member)
index ae757bcf128035d08d4fd65540d2f5539492385b..c8fcbdd2b0e77a8f88b34711dab9703a7d160ecb 100644 (file)
@@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data);
 u32 ethtool_op_get_flags(struct net_device *dev);
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
 void ethtool_ntuple_flush(struct net_device *dev);
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
 
 /**
  * &ethtool_ops - Alter and report network device settings
index b677bd77f2d67cbabb168fe6d38fc846b01b443e..52f283c1edb294c2457fd449a26004db09953753 100644 (file)
@@ -357,6 +357,8 @@ struct inodes_stat_t {
 #define FS_TOPDIR_FL                   0x00020000 /* Top of directory hierarchies*/
 #define FS_EXTENT_FL                   0x00080000 /* Extents */
 #define FS_DIRECTIO_FL                 0x00100000 /* Use direct i/o */
+#define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
+#define FS_COW_FL                      0x02000000 /* Cow file */
 #define FS_RESERVED_FL                 0x80000000 /* reserved for ext2 lib */
 
 #define FS_FL_USER_VISIBLE             0x0003DFFF /* User visible flags */
index 056ae8a5bd9b8bb3424c431ff60bcc22c155b4da..f3a7794a18c4d6de24065f797baf4ba97c34694b 100644 (file)
@@ -664,6 +664,13 @@ struct input_keymap_entry {
 #define KEY_TOUCHPAD_ON                0x213
 #define KEY_TOUCHPAD_OFF       0x214
 
+#define KEY_CAMERA_ZOOMIN      0x215
+#define KEY_CAMERA_ZOOMOUT     0x216
+#define KEY_CAMERA_UP          0x217
+#define KEY_CAMERA_DOWN                0x218
+#define KEY_CAMERA_LEFT                0x219
+#define KEY_CAMERA_RIGHT       0x21a
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
index 5d876c9b3a3dc0343ac38605f88797df319958da..2a375a72ce3cadeb06b39e6f5ab170996c877176 100644 (file)
@@ -92,18 +92,6 @@ enum {
        IRQ_NO_BALANCING        = (1 << 13),
        IRQ_MOVE_PCNTXT         = (1 << 14),
        IRQ_NESTED_THREAD       = (1 << 15),
-
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-       IRQ_INPROGRESS          = (1 << 16),
-       IRQ_REPLAY              = (1 << 17),
-       IRQ_WAITING             = (1 << 18),
-       IRQ_DISABLED            = (1 << 19),
-       IRQ_PENDING             = (1 << 20),
-       IRQ_MASKED              = (1 << 21),
-       IRQ_MOVE_PENDING        = (1 << 22),
-       IRQ_AFFINITY_SET        = (1 << 23),
-       IRQ_WAKEUP              = (1 << 24),
-#endif
 };
 
 #define IRQF_MODIFY_MASK       \
@@ -135,7 +123,7 @@ 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
- * @state_use_accessor: status information for irq chip functions.
+ * @state_use_accessors: status information for irq chip functions.
  *                     Use accessor functions to deal with it
  * @chip:              low level interrupt hardware access
  * @handler_data:      per-IRQ data for the irq_chip methods
@@ -174,6 +162,9 @@ struct irq_data {
  *                               from suspend
  * IRDQ_MOVE_PCNTXT            - Interrupt can be moved in process
  *                               context
+ * IRQD_IRQ_DISABLED           - Disabled state of the interrupt
+ * IRQD_IRQ_MASKED             - Masked state of the interrupt
+ * IRQD_IRQ_INPROGRESS         - In progress state of the interrupt
  */
 enum {
        IRQD_TRIGGER_MASK               = 0xf,
@@ -184,6 +175,9 @@ enum {
        IRQD_LEVEL                      = (1 << 13),
        IRQD_WAKEUP_STATE               = (1 << 14),
        IRQD_MOVE_PCNTXT                = (1 << 15),
+       IRQD_IRQ_DISABLED               = (1 << 16),
+       IRQD_IRQ_MASKED                 = (1 << 17),
+       IRQD_IRQ_INPROGRESS             = (1 << 18),
 };
 
 static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
@@ -206,6 +200,11 @@ static inline bool irqd_affinity_was_set(struct irq_data *d)
        return d->state_use_accessors & IRQD_AFFINITY_SET;
 }
 
+static inline void irqd_mark_affinity_was_set(struct irq_data *d)
+{
+       d->state_use_accessors |= IRQD_AFFINITY_SET;
+}
+
 static inline u32 irqd_get_trigger_type(struct irq_data *d)
 {
        return d->state_use_accessors & IRQD_TRIGGER_MASK;
@@ -235,6 +234,36 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d)
        return d->state_use_accessors & IRQD_MOVE_PCNTXT;
 }
 
+static inline bool irqd_irq_disabled(struct irq_data *d)
+{
+       return d->state_use_accessors & IRQD_IRQ_DISABLED;
+}
+
+static inline bool irqd_irq_masked(struct irq_data *d)
+{
+       return d->state_use_accessors & IRQD_IRQ_MASKED;
+}
+
+static inline bool irqd_irq_inprogress(struct irq_data *d)
+{
+       return d->state_use_accessors & IRQD_IRQ_INPROGRESS;
+}
+
+/*
+ * Functions for chained handlers which can be enabled/disabled by the
+ * standard disable_irq/enable_irq calls. Must be called with
+ * irq_desc->lock held.
+ */
+static inline void irqd_set_chained_irq_inprogress(struct irq_data *d)
+{
+       d->state_use_accessors |= IRQD_IRQ_INPROGRESS;
+}
+
+static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
+{
+       d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS;
+}
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
@@ -271,6 +300,8 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d)
  * @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
+ * @irq_cpu_online:    configure an interrupt source for a secondary CPU
+ * @irq_cpu_offline:   un-configure an interrupt source for a secondary CPU
  * @irq_print_chip:    optional to print special chip info in show_interrupts
  * @flags:             chip specific flags
  *
@@ -278,28 +309,6 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d)
  */
 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);
-       void            (*disable)(unsigned int irq);
-
-       void            (*ack)(unsigned int irq);
-       void            (*mask)(unsigned int irq);
-       void            (*mask_ack)(unsigned int irq);
-       void            (*unmask)(unsigned int irq);
-       void            (*eoi)(unsigned int irq);
-
-       void            (*end)(unsigned int irq);
-       int             (*set_affinity)(unsigned int irq,
-                                       const struct cpumask *dest);
-       int             (*retrigger)(unsigned int irq);
-       int             (*set_type)(unsigned int irq, unsigned int flow_type);
-       int             (*set_wake)(unsigned int irq, unsigned int on);
-
-       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);
@@ -319,6 +328,9 @@ struct irq_chip {
        void            (*irq_bus_lock)(struct irq_data *data);
        void            (*irq_bus_sync_unlock)(struct irq_data *data);
 
+       void            (*irq_cpu_online)(struct irq_data *data);
+       void            (*irq_cpu_offline)(struct irq_data *data);
+
        void            (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
 
        unsigned long   flags;
@@ -335,11 +347,14 @@ struct irq_chip {
  * IRQCHIP_SET_TYPE_MASKED:    Mask before calling chip.irq_set_type()
  * IRQCHIP_EOI_IF_HANDLED:     Only issue irq_eoi() when irq was handled
  * IRQCHIP_MASK_ON_SUSPEND:    Mask non wake irqs in the suspend path
+ * IRQCHIP_ONOFFLINE_ENABLED:  Only call irq_on/off_line callbacks
+ *                             when irq enabled
  */
 enum {
        IRQCHIP_SET_TYPE_MASKED         = (1 <<  0),
        IRQCHIP_EOI_IF_HANDLED          = (1 <<  1),
        IRQCHIP_MASK_ON_SUSPEND         = (1 <<  2),
+       IRQCHIP_ONOFFLINE_ENABLED       = (1 <<  3),
 };
 
 /* This include will go away once we isolated irq_desc usage to core code */
@@ -364,25 +379,22 @@ struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
 
+extern void irq_cpu_online(void);
+extern void irq_cpu_offline(void);
+extern int __irq_set_affinity_locked(struct irq_data *data,  const struct cpumask *cpumask);
+
 #ifdef CONFIG_GENERIC_HARDIRQS
 
 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
-void move_native_irq(int irq);
-void move_masked_irq(int irq);
 void irq_move_irq(struct irq_data *data);
 void irq_move_masked_irq(struct irq_data *data);
 #else
-static inline void move_native_irq(int irq) { }
-static inline void move_masked_irq(int irq) { }
 static inline void irq_move_irq(struct irq_data *data) { }
 static inline void irq_move_masked_irq(struct irq_data *data) { }
 #endif
 
 extern int no_irq_affinity;
 
-/* Handle irq action chains: */
-extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
-
 /*
  * Built-in IRQ handlers for various IRQ types,
  * callable via desc->handle_irq()
@@ -390,6 +402,7 @@ extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
 extern void handle_level_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc);
+extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
@@ -538,89 +551,6 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
        return d->msi_desc;
 }
 
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-/* Please do not use: Use the replacement functions instead */
-static inline int set_irq_chip(unsigned int irq, struct irq_chip *chip)
-{
-       return irq_set_chip(irq, chip);
-}
-static inline int set_irq_data(unsigned int irq, void *data)
-{
-       return irq_set_handler_data(irq, data);
-}
-static inline int set_irq_chip_data(unsigned int irq, void *data)
-{
-       return irq_set_chip_data(irq, data);
-}
-static inline int set_irq_type(unsigned int irq, unsigned int type)
-{
-       return irq_set_irq_type(irq, type);
-}
-static inline int set_irq_msi(unsigned int irq, struct msi_desc *entry)
-{
-       return irq_set_msi_desc(irq, entry);
-}
-static inline struct irq_chip *get_irq_chip(unsigned int irq)
-{
-       return irq_get_chip(irq);
-}
-static inline void *get_irq_chip_data(unsigned int irq)
-{
-       return irq_get_chip_data(irq);
-}
-static inline void *get_irq_data(unsigned int irq)
-{
-       return irq_get_handler_data(irq);
-}
-static inline void *irq_data_get_irq_data(struct irq_data *d)
-{
-       return irq_data_get_irq_handler_data(d);
-}
-static inline struct msi_desc *get_irq_msi(unsigned int irq)
-{
-       return irq_get_msi_desc(irq);
-}
-static inline void set_irq_noprobe(unsigned int irq)
-{
-       irq_set_noprobe(irq);
-}
-static inline void set_irq_probe(unsigned int irq)
-{
-       irq_set_probe(irq);
-}
-static inline void set_irq_nested_thread(unsigned int irq, int nest)
-{
-       irq_set_nested_thread(irq, nest);
-}
-static inline void
-set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
-                             irq_flow_handler_t handle, const char *name)
-{
-       irq_set_chip_and_handler_name(irq, chip, handle, name);
-}
-static inline void
-set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
-                        irq_flow_handler_t handle)
-{
-       irq_set_chip_and_handler(irq, chip, handle);
-}
-static inline void
-__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
-                 const char *name)
-{
-       __irq_set_handler(irq, handle, is_chained, name);
-}
-static inline void set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
-{
-       irq_set_handler(irq, handle);
-}
-static inline void
-set_irq_chained_handler(unsigned int irq, irq_flow_handler_t handle)
-{
-       irq_set_chained_handler(irq, handle);
-}
-#endif
-
 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);
index 15e6c3905f41625dc20bcf761365b2cc8aa48620..a082905b5ebe494676591012768f050fe5d4c140 100644 (file)
@@ -35,32 +35,7 @@ struct timer_rand_state;
  * @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;
-                       unsigned int            pad_do_not_even_think_about_it;
-                       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 __percpu   *kstat_irqs;
        irq_flow_handler_t      handle_irq;
@@ -68,11 +43,7 @@ struct irq_desc {
        irq_preflow_handler_t   preflow_handler;
 #endif
        struct irqaction        *action;        /* IRQ action list */
-#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
        unsigned int            status_use_accessors;
-#else
-       unsigned int            status;         /* IRQ status */
-#endif
        unsigned int            core_internal_state__do_not_mess_with_it;
        unsigned int            depth;          /* nested irq disables */
        unsigned int            wake_depth;     /* nested wake enables */
@@ -127,27 +98,6 @@ static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
        return desc->irq_data.msi_desc;
 }
 
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-static inline struct irq_chip *get_irq_desc_chip(struct irq_desc *desc)
-{
-       return irq_desc_get_chip(desc);
-}
-static inline void *get_irq_desc_data(struct irq_desc *desc)
-{
-       return irq_desc_get_handler_data(desc);
-}
-
-static inline void *get_irq_desc_chip_data(struct irq_desc *desc)
-{
-       return irq_desc_get_chip_data(desc);
-}
-
-static inline struct msi_desc *get_irq_desc_msi(struct irq_desc *desc)
-{
-       return irq_desc_get_msi_desc(desc);
-}
-#endif
-
 /*
  * Architectures call this to let the generic IRQ layer
  * handle an interrupt. If the descriptor is attached to an
@@ -194,21 +144,13 @@ __irq_set_chip_handler_name_locked(unsigned int irq, struct irq_chip *chip,
        desc->name = name;
 }
 
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-static inline void __set_irq_handler_unlocked(int irq,
-                                             irq_flow_handler_t handler)
-{
-       __irq_set_handler_locked(irq, handler);
-}
-
 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;
+       return desc->status_use_accessors & IRQ_NO_BALANCING_MASK;
 }
-#endif
 
 static inline void
 irq_set_lockdep_class(unsigned int irq, struct lock_class_key *class)
index 56f8dea721529cd0a979ea8e466a75470c70b4f3..b318430751983cf284069b99e6f2f4fa387deb94 100644 (file)
 #define AB8500_INT_ACC_DETECT_21DB_F   37
 #define AB8500_INT_ACC_DETECT_21DB_R   38
 #define AB8500_INT_GP_SW_ADC_CONV_END  39
+#define AB8500_INT_ACC_DETECT_1DB_F    33
+#define AB8500_INT_ACC_DETECT_1DB_R    34
+#define AB8500_INT_ACC_DETECT_22DB_F   35
+#define AB8500_INT_ACC_DETECT_22DB_R   36
+#define AB8500_INT_ACC_DETECT_21DB_F   37
+#define AB8500_INT_ACC_DETECT_21DB_R   38
+#define AB8500_INT_GP_SW_ADC_CONV_END  39
+#define AB8500_INT_GPIO6R              40
+#define AB8500_INT_GPIO7R              41
+#define AB8500_INT_GPIO8R              42
+#define AB8500_INT_GPIO9R              43
+#define AB8500_INT_GPIO10R             44
+#define AB8500_INT_GPIO11R             45
+#define AB8500_INT_GPIO12R             46
+#define AB8500_INT_GPIO13R             47
+#define AB8500_INT_GPIO24R             48
+#define AB8500_INT_GPIO25R             49
+#define AB8500_INT_GPIO36R             50
+#define AB8500_INT_GPIO37R             51
+#define AB8500_INT_GPIO38R             52
+#define AB8500_INT_GPIO39R             53
+#define AB8500_INT_GPIO40R             54
+#define AB8500_INT_GPIO41R             55
+#define AB8500_INT_GPIO6F              56
+#define AB8500_INT_GPIO7F              57
+#define AB8500_INT_GPIO8F              58
+#define AB8500_INT_GPIO9F              59
+#define AB8500_INT_GPIO10F             60
+#define AB8500_INT_GPIO11F             61
+#define AB8500_INT_GPIO12F             62
+#define AB8500_INT_GPIO13F             63
+#define AB8500_INT_GPIO24F             64
+#define AB8500_INT_GPIO25F             65
+#define AB8500_INT_GPIO36F             66
+#define AB8500_INT_GPIO37F             67
+#define AB8500_INT_GPIO38F             68
+#define AB8500_INT_GPIO39F             69
+#define AB8500_INT_GPIO40F             70
+#define AB8500_INT_GPIO41F             71
 #define AB8500_INT_ADP_SOURCE_ERROR    72
 #define AB8500_INT_ADP_SINK_ERROR      73
 #define AB8500_INT_ADP_PROBE_PLUG      74
@@ -139,19 +178,27 @@ struct ab8500 {
        u8 oldmask[AB8500_NUM_IRQ_REGS];
 };
 
+struct regulator_reg_init;
 struct regulator_init_data;
+struct ab8500_gpio_platform_data;
 
 /**
  * struct ab8500_platform_data - AB8500 platform data
  * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used
  * @init: board-specific initialization after detection of ab8500
+ * @num_regulator_reg_init: number of regulator init registers
+ * @regulator_reg_init: regulator init registers
+ * @num_regulator: number of regulators
  * @regulator: machine-specific constraints for regulators
  */
 struct ab8500_platform_data {
        int irq_base;
        void (*init) (struct ab8500 *);
+       int num_regulator_reg_init;
+       struct ab8500_regulator_reg_init *regulator_reg_init;
        int num_regulator;
        struct regulator_init_data *regulator;
+       struct ab8500_gpio_platform_data *gpio;
 };
 
 extern int __devinit ab8500_init(struct ab8500 *ab8500);
diff --git a/include/linux/mfd/ab8500/gpio.h b/include/linux/mfd/ab8500/gpio.h
new file mode 100644 (file)
index 0000000..488a8c9
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright ST-Ericsson 2010.
+ *
+ * Author: Bibek Basu <bibek.basu@stericsson.com>
+ * Licensed under GPLv2.
+ */
+
+#ifndef _AB8500_GPIO_H
+#define _AB8500_GPIO_H
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+
+struct ab8500_gpio_platform_data {
+       int gpio_base;
+       u32 irq_base;
+       u8  config_reg[7];
+};
+
+#endif /* _AB8500_GPIO_H */
index 1408bf8eed5f2b811bd22aad529c951f1bcc5c1f..ad1b19aa6508eb58af14a64535dcdcd05d454eb9 100644 (file)
@@ -62,6 +62,24 @@ struct mfd_cell {
 extern int mfd_cell_enable(struct platform_device *pdev);
 extern int mfd_cell_disable(struct platform_device *pdev);
 
+/*
+ * "Clone" multiple platform devices for a single cell. This is to be used
+ * for devices that have multiple users of a cell.  For example, if an mfd
+ * driver wants the cell "foo" to be used by a GPIO driver, an MTD driver,
+ * and a platform driver, the following bit of code would be use after first
+ * calling mfd_add_devices():
+ *
+ * const char *fclones[] = { "foo-gpio", "foo-mtd" };
+ * err = mfd_clone_cells("foo", fclones, ARRAY_SIZE(fclones));
+ *
+ * Each driver (MTD, GPIO, and platform driver) would then register
+ * platform_drivers for "foo-mtd", "foo-gpio", and "foo", respectively.
+ * The cell's .enable/.disable hooks should be used to deal with hardware
+ * resource contention.
+ */
+extern int mfd_clone_cell(const char *cell, const char **clones,
+               size_t n_clones);
+
 /*
  * Given a platform device that's been created by mfd_add_devices(), fetch
  * the mfd_cell that created it.
@@ -87,13 +105,4 @@ extern int mfd_add_devices(struct device *parent, int id,
 
 extern void mfd_remove_devices(struct device *parent);
 
-/*
- * For MFD drivers with clients sharing access to resources, these create
- * multiple platform devices per cell.  Contention handling must still be
- * handled via drivers (ie, with enable/disable hooks).
- */
-extern int mfd_shared_platform_driver_register(struct platform_driver *drv,
-               const char *cellname);
-extern void mfd_shared_platform_driver_unregister(struct platform_driver *drv);
-
 #endif
index 93a9477e075fb723a5901ac9a37884ecad1a25ea..69d1010e2e5146d7cd8d0a1c71cf8c05608024e0 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <linux/i2c.h>
 
+#define MAX8997_REG_INVALID    (0xff)
+
 enum max8997_pmic_reg {
        MAX8997_REG_PMIC_ID0    = 0x00,
        MAX8997_REG_PMIC_ID1    = 0x01,
@@ -313,6 +315,7 @@ enum max8997_irq {
 #define MAX8997_REG_BUCK2DVS(x)        (MAX8997_REG_BUCK2DVS1 + (x) - 1)
 #define MAX8997_REG_BUCK5DVS(x)        (MAX8997_REG_BUCK5DVS1 + (x) - 1)
 
+#define MAX8997_NUM_GPIO       12
 struct max8997_dev {
        struct device *dev;
        struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
@@ -324,11 +327,19 @@ struct max8997_dev {
        int type;
        struct platform_device *battery; /* battery control (not fuel gauge) */
 
+       int irq;
+       int ono;
+       int irq_base;
        bool wakeup;
+       struct mutex irqlock;
+       int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
+       int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
 
        /* For hibernation */
        u8 reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
                MAX8997_HAPTIC_REG_END];
+
+       bool gpio_status[MAX8997_NUM_GPIO];
 };
 
 enum max8997_types {
@@ -336,6 +347,10 @@ enum max8997_types {
        TYPE_MAX8966,
 };
 
+extern int max8997_irq_init(struct max8997_dev *max8997);
+extern void max8997_irq_exit(struct max8997_dev *max8997);
+extern int max8997_irq_resume(struct max8997_dev *max8997);
+
 extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
 extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
                                u8 *buf);
@@ -344,4 +359,10 @@ extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
                                u8 *buf);
 extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
 
+#define MAX8997_GPIO_INT_BOTH  (0x3 << 4)
+#define MAX8997_GPIO_INT_RISE  (0x2 << 4)
+#define MAX8997_GPIO_INT_FALL  (0x1 << 4)
+
+#define MAX8997_GPIO_INT_MASK  (0x3 << 4)
+#define MAX8997_GPIO_DATA_MASK (0x1 << 2)
 #endif /*  __LINUX_MFD_MAX8997_PRIV_H */
index cb671b3451bf8666e046e817d04af6d04e482efa..60931d089422c1add45e93a8a813ebeb69d9835c 100644 (file)
@@ -78,8 +78,11 @@ struct max8997_regulator_data {
 };
 
 struct max8997_platform_data {
-       bool wakeup;
-       /* IRQ: Not implemented */
+       /* IRQ */
+       int irq_base;
+       int ono;
+       int wakeup;
+
        /* ---- PMIC ---- */
        struct max8997_regulator_data *regulators;
        int num_regulators;
diff --git a/include/linux/mfd/sh_mobile_sdhi.h b/include/linux/mfd/sh_mobile_sdhi.h
deleted file mode 100644 (file)
index c981b95..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __SH_MOBILE_SDHI_H__
-#define __SH_MOBILE_SDHI_H__
-
-#include <linux/types.h>
-
-struct sh_mobile_sdhi_info {
-       int dma_slave_tx;
-       int dma_slave_rx;
-       unsigned long tmio_flags;
-       unsigned long tmio_caps;
-       u32 tmio_ocr_mask;      /* available MMC voltages */
-       void (*set_pwr)(struct platform_device *pdev, int state);
-       int (*get_cd)(struct platform_device *pdev);
-};
-
-#endif /* __SH_MOBILE_SDHI_H__ */
diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h
new file mode 100644 (file)
index 0000000..c981b95
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __SH_MOBILE_SDHI_H__
+#define __SH_MOBILE_SDHI_H__
+
+#include <linux/types.h>
+
+struct sh_mobile_sdhi_info {
+       int dma_slave_tx;
+       int dma_slave_rx;
+       unsigned long tmio_flags;
+       unsigned long tmio_caps;
+       u32 tmio_ocr_mask;      /* available MMC voltages */
+       void (*set_pwr)(struct platform_device *pdev, int state);
+       int (*get_cd)(struct platform_device *pdev);
+};
+
+#endif /* __SH_MOBILE_SDHI_H__ */
diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h
new file mode 100644 (file)
index 0000000..19490b9
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * include/linux/mmc/tmio.h
+ *
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
+ *
+ * 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.
+ *
+ * Driver for the MMC / SD / SDIO cell found in:
+ *
+ * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
+ */
+#ifndef _LINUX_MMC_TMIO_H_
+#define _LINUX_MMC_TMIO_H_
+
+#define CTL_SD_CMD 0x00
+#define CTL_ARG_REG 0x04
+#define CTL_STOP_INTERNAL_ACTION 0x08
+#define CTL_XFER_BLK_COUNT 0xa
+#define CTL_RESPONSE 0x0c
+#define CTL_STATUS 0x1c
+#define CTL_IRQ_MASK 0x20
+#define CTL_SD_CARD_CLK_CTL 0x24
+#define CTL_SD_XFER_LEN 0x26
+#define CTL_SD_MEM_CARD_OPT 0x28
+#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
+#define CTL_SD_DATA_PORT 0x30
+#define CTL_TRANSACTION_CTL 0x34
+#define CTL_SDIO_STATUS 0x36
+#define CTL_SDIO_IRQ_MASK 0x38
+#define CTL_RESET_SD 0xe0
+#define CTL_SDIO_REGS 0x100
+#define CTL_CLK_AND_WAIT_CTL 0x138
+#define CTL_RESET_SDIO 0x1e0
+
+/* Definitions for values the CTRL_STATUS register can take. */
+#define TMIO_STAT_CMDRESPEND    0x00000001
+#define TMIO_STAT_DATAEND       0x00000004
+#define TMIO_STAT_CARD_REMOVE   0x00000008
+#define TMIO_STAT_CARD_INSERT   0x00000010
+#define TMIO_STAT_SIGSTATE      0x00000020
+#define TMIO_STAT_WRPROTECT     0x00000080
+#define TMIO_STAT_CARD_REMOVE_A 0x00000100
+#define TMIO_STAT_CARD_INSERT_A 0x00000200
+#define TMIO_STAT_SIGSTATE_A    0x00000400
+#define TMIO_STAT_CMD_IDX_ERR   0x00010000
+#define TMIO_STAT_CRCFAIL       0x00020000
+#define TMIO_STAT_STOPBIT_ERR   0x00040000
+#define TMIO_STAT_DATATIMEOUT   0x00080000
+#define TMIO_STAT_RXOVERFLOW    0x00100000
+#define TMIO_STAT_TXUNDERRUN    0x00200000
+#define TMIO_STAT_CMDTIMEOUT    0x00400000
+#define TMIO_STAT_RXRDY         0x01000000
+#define TMIO_STAT_TXRQ          0x02000000
+#define TMIO_STAT_ILL_FUNC      0x20000000
+#define TMIO_STAT_CMD_BUSY      0x40000000
+#define TMIO_STAT_ILL_ACCESS    0x80000000
+
+#define TMIO_BBS               512             /* Boot block size */
+
+#endif /* _LINUX_MMC_TMIO_H_ */
index 26529ebd59ccf3872fddca921c141184915fcf62..1bbd9f28924564d188f2a01bc2c14a3ee49f691b 100644 (file)
@@ -36,6 +36,7 @@ struct mtd_blktrans_dev {
        struct mtd_info *mtd;
        struct mutex lock;
        int devnum;
+       bool bg_stop;
        unsigned long size;
        int readonly;
        int open;
@@ -62,6 +63,7 @@ struct mtd_blktrans_ops {
                     unsigned long block, char *buffer);
        int (*discard)(struct mtd_blktrans_dev *dev,
                       unsigned long block, unsigned nr_blocks);
+       void (*background)(struct mtd_blktrans_dev *dev);
 
        /* Block layer ioctls */
        int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
@@ -85,6 +87,7 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
 extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
 extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
 extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev);
 
 
 #endif /* __MTD_TRANS_H__ */
index a9baee6864afe8cd29a38652fbdb04a345b515a9..0d823f2dd6679a27bbf39a224f37725f6e9c6f70 100644 (file)
@@ -535,6 +535,7 @@ struct cfi_fixup {
 #define CFI_MFR_CONTINUATION   0x007F
 
 #define CFI_MFR_AMD            0x0001
+#define CFI_MFR_AMIC           0x0037
 #define CFI_MFR_ATMEL          0x001F
 #define CFI_MFR_EON            0x001C
 #define CFI_MFR_FUJITSU                0x0004
diff --git a/include/linux/mtd/latch-addr-flash.h b/include/linux/mtd/latch-addr-flash.h
new file mode 100644 (file)
index 0000000..e94b8e1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Interface for NOR flash driver whose high address lines are latched
+ *
+ * Copyright Â© 2008 MontaVista Software, Inc. <source@mvista.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.
+ */
+#ifndef __LATCH_ADDR_FLASH__
+#define __LATCH_ADDR_FLASH__
+
+struct map_info;
+struct mtd_partition;
+
+struct latch_addr_flash_data {
+       unsigned int            width;
+       unsigned int            size;
+
+       int                     (*init)(void *data, int cs);
+       void                    (*done)(void *data);
+       void                    (*set_window)(unsigned long offset, void *data);
+       void                    *data;
+
+       unsigned int            nr_parts;
+       struct mtd_partition    *parts;
+};
+
+#endif
index 1f489b247a2978324d65576d43323303601a5f50..ae67ef56a8f5a4a6639d4f352283f0a7308da5a3 100644 (file)
@@ -140,6 +140,7 @@ typedef enum {
        NAND_ECC_HW,
        NAND_ECC_HW_SYNDROME,
        NAND_ECC_HW_OOB_FIRST,
+       NAND_ECC_SOFT_BCH,
 } nand_ecc_modes_t;
 
 /*
@@ -339,6 +340,7 @@ struct nand_hw_control {
  * @prepad:    padding information for syndrome based ecc generators
  * @postpad:   padding information for syndrome based ecc generators
  * @layout:    ECC layout control struct pointer
+ * @priv:      pointer to private ecc control data
  * @hwctl:     function to control hardware ecc generator. Must only
  *             be provided if an hardware ECC is available
  * @calculate: function for ecc calculation or readback from ecc hardware
@@ -362,6 +364,7 @@ struct nand_ecc_ctrl {
        int prepad;
        int postpad;
        struct nand_ecclayout   *layout;
+       void *priv;
        void (*hwctl)(struct mtd_info *mtd, int mode);
        int (*calculate)(struct mtd_info *mtd, const uint8_t *dat,
                        uint8_t *ecc_code);
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h
new file mode 100644 (file)
index 0000000..74acf53
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright Â© 2011 Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file is the header for the NAND BCH ECC implementation.
+ */
+
+#ifndef __MTD_NAND_BCH_H__
+#define __MTD_NAND_BCH_H__
+
+struct mtd_info;
+struct nand_bch_control;
+
+#if defined(CONFIG_MTD_NAND_ECC_BCH)
+
+static inline int mtd_nand_has_bch(void) { return 1; }
+
+/*
+ * Calculate BCH ecc code
+ */
+int nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                          u_char *ecc_code);
+
+/*
+ * Detect and correct bit errors
+ */
+int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,
+                         u_char *calc_ecc);
+/*
+ * Initialize BCH encoder/decoder
+ */
+struct nand_bch_control *
+nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
+             unsigned int eccbytes, struct nand_ecclayout **ecclayout);
+/*
+ * Release BCH encoder/decoder resources
+ */
+void nand_bch_free(struct nand_bch_control *nbc);
+
+#else /* !CONFIG_MTD_NAND_ECC_BCH */
+
+static inline int mtd_nand_has_bch(void) { return 0; }
+
+static inline int
+nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                      u_char *ecc_code)
+{
+       return -1;
+}
+
+static inline int
+nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
+                     unsigned char *read_ecc, unsigned char *calc_ecc)
+{
+       return -1;
+}
+
+static inline struct nand_bch_control *
+nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
+             unsigned int eccbytes, struct nand_ecclayout **ecclayout)
+{
+       return NULL;
+}
+
+static inline void nand_bch_free(struct nand_bch_control *nbc) {}
+
+#endif /* CONFIG_MTD_NAND_ECC_BCH */
+
+#endif /* __MTD_NAND_BCH_H__ */
index ae418e41d8f52171c60b4352efbaa16c72da4cfc..52b6f187bf49bfdc3038dff70f3117eb4e9a1a97 100644 (file)
@@ -198,6 +198,7 @@ struct onenand_chip {
 #define ONENAND_SKIP_UNLOCK_CHECK      (0x0100)
 #define ONENAND_PAGEBUF_ALLOC          (0x1000)
 #define ONENAND_OOBBUF_ALLOC           (0x2000)
+#define ONENAND_SKIP_INITIAL_UNLOCKING (0x4000)
 
 #define ONENAND_IS_4KB_PAGE(this)                                      \
        (this->options & ONENAND_HAS_4KB_PAGE)
index 8023e4e25133cbcebbbd97b85c33df1943d34e13..91af2e49fa3ab1a532bdc22143da19021f0248da 100644 (file)
@@ -78,7 +78,6 @@ extern        struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
                                            struct page *page,
                                            unsigned int offset,
                                            unsigned int count);
-extern void nfs_clear_request(struct nfs_page *req);
 extern void nfs_release_request(struct nfs_page *req);
 
 
index 6a210f1511fc5b10ba663c709f8d85fd6d364076..76579f964a296d058b87e97f370f9758ff475559 100644 (file)
@@ -3,8 +3,8 @@
  *
  * License Terms: GNU General Public License v2
  *
- * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
- *
+ * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
  */
 
 #ifndef __LINUX_MFD_AB8500_REGULATOR_H
@@ -17,6 +17,7 @@ enum ab8500_regulator_id {
        AB8500_LDO_AUX3,
        AB8500_LDO_INTCORE,
        AB8500_LDO_TVOUT,
+       AB8500_LDO_USB,
        AB8500_LDO_AUDIO,
        AB8500_LDO_ANAMIC1,
        AB8500_LDO_ANAMIC2,
@@ -24,4 +25,50 @@ enum ab8500_regulator_id {
        AB8500_LDO_ANA,
        AB8500_NUM_REGULATORS,
 };
+
+/* AB8500 register initialization */
+struct ab8500_regulator_reg_init {
+       int id;
+       u8 value;
+};
+
+#define INIT_REGULATOR_REGISTER(_id, _value)   \
+       {                                       \
+               .id = _id,                      \
+               .value = _value,                \
+       }
+
+/* AB8500 registers */
+enum ab8500_regulator_reg {
+       AB8500_REGUREQUESTCTRL2,
+       AB8500_REGUREQUESTCTRL3,
+       AB8500_REGUREQUESTCTRL4,
+       AB8500_REGUSYSCLKREQ1HPVALID1,
+       AB8500_REGUSYSCLKREQ1HPVALID2,
+       AB8500_REGUHWHPREQ1VALID1,
+       AB8500_REGUHWHPREQ1VALID2,
+       AB8500_REGUHWHPREQ2VALID1,
+       AB8500_REGUHWHPREQ2VALID2,
+       AB8500_REGUSWHPREQVALID1,
+       AB8500_REGUSWHPREQVALID2,
+       AB8500_REGUSYSCLKREQVALID1,
+       AB8500_REGUSYSCLKREQVALID2,
+       AB8500_REGUMISC1,
+       AB8500_VAUDIOSUPPLY,
+       AB8500_REGUCTRL1VAMIC,
+       AB8500_VPLLVANAREGU,
+       AB8500_VREFDDR,
+       AB8500_EXTSUPPLYREGU,
+       AB8500_VAUX12REGU,
+       AB8500_VRF1VAUX3REGU,
+       AB8500_VAUX1SEL,
+       AB8500_VAUX2SEL,
+       AB8500_VRF1VAUX3SEL,
+       AB8500_REGUCTRL2SPARE,
+       AB8500_REGUCTRLDISCH,
+       AB8500_REGUCTRLDISCH2,
+       AB8500_VSMPS1SEL1,
+       AB8500_NUM_REGULATOR_REGISTERS,
+};
+
 #endif
index 7954f6bd7edb1a101266d2eeeb890d0c63858260..9e87c1cb7270ff458833471b55ead7e3a440c1a0 100644 (file)
@@ -153,6 +153,8 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector);
 int regulator_is_supported_voltage(struct regulator *regulator,
                                   int min_uV, int max_uV);
 int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
+int regulator_set_voltage_time(struct regulator *regulator,
+                              int old_uV, int new_uV);
 int regulator_get_voltage(struct regulator *regulator);
 int regulator_sync_voltage(struct regulator *regulator);
 int regulator_set_current_limit(struct regulator *regulator,
index b8ed16a33c47fc9b4febb65d24db94ec6a5dc9cd..6c433b89c80d617da2902caeffa74280fdaa9efd 100644 (file)
@@ -63,7 +63,11 @@ enum regulator_status {
  *                    when running with the specified parameters.
  *
  * @enable_time: Time taken for the regulator voltage output voltage to
- *               stabalise after being enabled, in microseconds.
+ *               stabilise after being enabled, in microseconds.
+ * @set_voltage_time_sel: Time taken for the regulator voltage output voltage
+ *               to stabilise after being set to a new value, in microseconds.
+ *               The function provides the from and to voltage selector, the
+ *               function should return the worst case.
  *
  * @set_suspend_voltage: Set the voltage for the regulator when the system
  *                       is suspended.
@@ -103,8 +107,11 @@ struct regulator_ops {
        int (*set_mode) (struct regulator_dev *, unsigned int mode);
        unsigned int (*get_mode) (struct regulator_dev *);
 
-       /* Time taken to enable the regulator */
+       /* Time taken to enable or set voltage on the regulator */
        int (*enable_time) (struct regulator_dev *);
+       int (*set_voltage_time_sel) (struct regulator_dev *,
+                                    unsigned int old_selector,
+                                    unsigned int new_selector);
 
        /* report regulator status ... most other accessors report
         * control inputs, this reports results of combining inputs
index 761c745b9c24d11159c619e296c41fded18099f3..c4c4fc45f856ee7ee57b4a9234827aafa3242f61 100644 (file)
@@ -186,6 +186,7 @@ struct regulator_init_data {
 };
 
 int regulator_suspend_prepare(suspend_state_t state);
+int regulator_suspend_finish(void);
 
 #ifdef CONFIG_REGULATOR
 void regulator_has_full_constraints(void);
index 24cfa626931ee56d45d8c6e0cdfa8b0474577425..239083bfea13d642c2c11d30398cc0365071b55c 100644 (file)
@@ -122,8 +122,14 @@ struct sk_buff_head {
 
 struct sk_buff;
 
-/* To allow 64K frame to be packed as single skb without frag_list */
+/* To allow 64K frame to be packed as single skb without frag_list. Since
+ * GRO uses frags we allocate at least 16 regardless of page size.
+ */
+#if (65536/PAGE_SIZE + 2) < 16
+#define MAX_SKB_FRAGS 16
+#else
 #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)
+#endif
 
 typedef struct skb_frag_struct skb_frag_t;
 
index 0e6dc3891942e22b52457850fa246bf443749798..c0f87da78f8a44b788fd32ebcabf94d4b72e2962 100644 (file)
@@ -40,6 +40,7 @@
 
 /* events the user application reading /dev/sonypi can use */
 
+#define SONYPI_EVENT_IGNORE                     0
 #define SONYPI_EVENT_JOGDIAL_DOWN               1
 #define SONYPI_EVENT_JOGDIAL_UP                         2
 #define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED       3
index 4ed6fcd6b7263c3e38953e536f4cd07a290c61e7..9332e52ea8c270aadacb79b61446336202e1fea6 100644 (file)
@@ -95,10 +95,27 @@ extern struct vm_struct *remove_vm_area(const void *addr);
 
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
                        struct page ***pages);
+#ifdef CONFIG_MMU
 extern int map_kernel_range_noflush(unsigned long start, unsigned long size,
                                    pgprot_t prot, struct page **pages);
 extern void unmap_kernel_range_noflush(unsigned long addr, unsigned long size);
 extern void unmap_kernel_range(unsigned long addr, unsigned long size);
+#else
+static inline int
+map_kernel_range_noflush(unsigned long start, unsigned long size,
+                       pgprot_t prot, struct page **pages)
+{
+       return size >> PAGE_SHIFT;
+}
+static inline void
+unmap_kernel_range_noflush(unsigned long addr, unsigned long size)
+{
+}
+static inline void
+unmap_kernel_range(unsigned long addr, unsigned long size)
+{
+}
+#endif
 
 /* Allocate/destroy a 'vmalloc' VM area. */
 extern struct vm_struct *alloc_vm_area(size_t size);
@@ -116,11 +133,26 @@ extern struct vm_struct *vmlist;
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 
 #ifdef CONFIG_SMP
+# ifdef CONFIG_MMU
 struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
                                     const size_t *sizes, int nr_vms,
                                     size_t align);
 
 void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
+# else
+static inline struct vm_struct **
+pcpu_get_vm_areas(const unsigned long *offsets,
+               const size_t *sizes, int nr_vms,
+               size_t align)
+{
+       return NULL;
+}
+
+static inline void
+pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
+{
+}
+# endif
 #endif
 
 #endif /* _LINUX_VMALLOC_H */
index 2a46cbaef92d30dd7c890deb34a9554634eb94b5..75b95df4afe71467bb9d378f5535ab1e167772df 100644 (file)
@@ -345,7 +345,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
 
 static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 {
-       struct dst_entry *child = skb_dst(skb)->child;
+       struct dst_entry *child = dst_clone(skb_dst(skb)->child);
 
        skb_dst_drop(skb);
        return child;
index 5ba9f02731eb353921854816bd503bb04978c298..555dd198aab755c9e9ef21a751992ccf653b64c7 100644 (file)
 
 #define        ROSE_MIN_LEN                    3
 
+#define        ROSE_CALL_REQ_ADDR_LEN_OFF      3
+#define        ROSE_CALL_REQ_ADDR_LEN_VAL      0xAA    /* each address is 10 digits */
+#define        ROSE_CALL_REQ_DEST_ADDR_OFF     4
+#define        ROSE_CALL_REQ_SRC_ADDR_OFF      9
+#define        ROSE_CALL_REQ_FACILITIES_OFF    14
+
 #define        ROSE_GFI                        0x10
 #define        ROSE_Q_BIT                      0x80
 #define        ROSE_D_BIT                      0x40
@@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *);
 extern int  rose_validate_nr(struct sock *, unsigned short);
 extern void rose_write_internal(struct sock *, int);
 extern int  rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
-extern int  rose_parse_facilities(unsigned char *, struct rose_facilities_struct *);
+extern int  rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *);
 extern void rose_disconnect(struct sock *, int, int, int);
 
 /* rose_timer.c */
index cffa5dc664492f0b45a54889f91d12fa48cd324f..6ae4bc5ce8a712796774e32637f875f4e98b173e 100644 (file)
@@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay
 }
 
 #ifdef CONFIG_XFRM_MIGRATE
+static inline int xfrm_replay_clone(struct xfrm_state *x,
+                                    struct xfrm_state *orig)
+{
+       x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
+                               GFP_KERNEL);
+       if (!x->replay_esn)
+               return -ENOMEM;
+
+       x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
+       x->replay_esn->replay_window = orig->replay_esn->replay_window;
+
+       x->preplay_esn = kmemdup(x->replay_esn,
+                                xfrm_replay_state_esn_len(x->replay_esn),
+                                GFP_KERNEL);
+       if (!x->preplay_esn) {
+               kfree(x->replay_esn);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
 {
        return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
index 430a9cc045e27e69cc7ea7bcff67468be22f0c5f..e1bad1130616f1441d1aa061f048a4ea74c606e7 100644 (file)
@@ -1031,9 +1031,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
 #define snd_pcm_lib_mmap_iomem NULL
 #endif
 
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
-                              struct vm_area_struct *area);
-#define snd_pcm_lib_mmap_vmalloc       snd_pcm_lib_mmap_noncached
+#define snd_pcm_lib_mmap_vmalloc NULL
 
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
new file mode 100644 (file)
index 0000000..f445cff
--- /dev/null
@@ -0,0 +1,667 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM btrfs
+
+#if !defined(_TRACE_BTRFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_BTRFS_H
+
+#include <linux/writeback.h>
+#include <linux/tracepoint.h>
+
+struct btrfs_root;
+struct btrfs_fs_info;
+struct btrfs_inode;
+struct extent_map;
+struct btrfs_ordered_extent;
+struct btrfs_delayed_ref_node;
+struct btrfs_delayed_tree_ref;
+struct btrfs_delayed_data_ref;
+struct btrfs_delayed_ref_head;
+struct map_lookup;
+struct extent_buffer;
+
+#define show_ref_type(type)                                            \
+       __print_symbolic(type,                                          \
+               { BTRFS_TREE_BLOCK_REF_KEY,     "TREE_BLOCK_REF" },     \
+               { BTRFS_EXTENT_DATA_REF_KEY,    "EXTENT_DATA_REF" },    \
+               { BTRFS_EXTENT_REF_V0_KEY,      "EXTENT_REF_V0" },      \
+               { BTRFS_SHARED_BLOCK_REF_KEY,   "SHARED_BLOCK_REF" },   \
+               { BTRFS_SHARED_DATA_REF_KEY,    "SHARED_DATA_REF" })
+
+#define __show_root_type(obj)                                          \
+       __print_symbolic(obj,                                           \
+               { BTRFS_ROOT_TREE_OBJECTID,     "ROOT_TREE"     },      \
+               { BTRFS_EXTENT_TREE_OBJECTID,   "EXTENT_TREE"   },      \
+               { BTRFS_CHUNK_TREE_OBJECTID,    "CHUNK_TREE"    },      \
+               { BTRFS_DEV_TREE_OBJECTID,      "DEV_TREE"      },      \
+               { BTRFS_FS_TREE_OBJECTID,       "FS_TREE"       },      \
+               { BTRFS_ROOT_TREE_DIR_OBJECTID, "ROOT_TREE_DIR" },      \
+               { BTRFS_CSUM_TREE_OBJECTID,     "CSUM_TREE"     },      \
+               { BTRFS_TREE_LOG_OBJECTID,      "TREE_LOG"      },      \
+               { BTRFS_TREE_RELOC_OBJECTID,    "TREE_RELOC"    },      \
+               { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" })
+
+#define show_root_type(obj)                                            \
+       obj, ((obj >= BTRFS_DATA_RELOC_TREE_OBJECTID) ||                \
+             (obj <= BTRFS_CSUM_TREE_OBJECTID )) ? __show_root_type(obj) : "-"
+
+TRACE_EVENT(btrfs_transaction_commit,
+
+       TP_PROTO(struct btrfs_root *root),
+
+       TP_ARGS(root),
+
+       TP_STRUCT__entry(
+               __field(        u64,  generation                )
+               __field(        u64,  root_objectid             )
+       ),
+
+       TP_fast_assign(
+               __entry->generation     = root->fs_info->generation;
+               __entry->root_objectid  = root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), gen = %llu",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->generation)
+);
+
+DECLARE_EVENT_CLASS(btrfs__inode,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino                     )
+               __field(        blkcnt_t,  blocks               )
+               __field(        u64,  disk_i_size               )
+               __field(        u64,  generation                )
+               __field(        u64,  last_trans                )
+               __field(        u64,  logged_trans              )
+               __field(        u64,  root_objectid             )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->blocks = inode->i_blocks;
+               __entry->disk_i_size  = BTRFS_I(inode)->disk_i_size;
+               __entry->generation = BTRFS_I(inode)->generation;
+               __entry->last_trans = BTRFS_I(inode)->last_trans;
+               __entry->logged_trans = BTRFS_I(inode)->logged_trans;
+               __entry->root_objectid =
+                               BTRFS_I(inode)->root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), gen = %llu, ino = %lu, blocks = %llu, "
+                 "disk_i_size = %llu, last_trans = %llu, logged_trans = %llu",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->generation,
+                 (unsigned long)__entry->ino,
+                 (unsigned long long)__entry->blocks,
+                 (unsigned long long)__entry->disk_i_size,
+                 (unsigned long long)__entry->last_trans,
+                 (unsigned long long)__entry->logged_trans)
+);
+
+DEFINE_EVENT(btrfs__inode, btrfs_inode_new,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode)
+);
+
+DEFINE_EVENT(btrfs__inode, btrfs_inode_request,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode)
+);
+
+DEFINE_EVENT(btrfs__inode, btrfs_inode_evict,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode)
+);
+
+#define __show_map_type(type)                                          \
+       __print_symbolic(type,                                          \
+               { EXTENT_MAP_LAST_BYTE, "LAST_BYTE"     },              \
+               { EXTENT_MAP_HOLE,      "HOLE"          },              \
+               { EXTENT_MAP_INLINE,    "INLINE"        },              \
+               { EXTENT_MAP_DELALLOC,  "DELALLOC"      })
+
+#define show_map_type(type)                    \
+       type, (type >= EXTENT_MAP_LAST_BYTE) ? "-" :  __show_map_type(type)
+
+#define show_map_flags(flag)                                           \
+       __print_flags(flag, "|",                                        \
+               { EXTENT_FLAG_PINNED,           "PINNED"        },      \
+               { EXTENT_FLAG_COMPRESSED,       "COMPRESSED"    },      \
+               { EXTENT_FLAG_VACANCY,          "VACANCY"       },      \
+               { EXTENT_FLAG_PREALLOC,         "PREALLOC"      })
+
+TRACE_EVENT(btrfs_get_extent,
+
+       TP_PROTO(struct btrfs_root *root, struct extent_map *map),
+
+       TP_ARGS(root, map),
+
+       TP_STRUCT__entry(
+               __field(        u64,  root_objectid     )
+               __field(        u64,  start             )
+               __field(        u64,  len               )
+               __field(        u64,  orig_start        )
+               __field(        u64,  block_start       )
+               __field(        u64,  block_len         )
+               __field(        unsigned long,  flags   )
+               __field(        int,  refs              )
+               __field(        unsigned int,  compress_type    )
+       ),
+
+       TP_fast_assign(
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->start          = map->start;
+               __entry->len            = map->len;
+               __entry->orig_start     = map->orig_start;
+               __entry->block_start    = map->block_start;
+               __entry->block_len      = map->block_len;
+               __entry->flags          = map->flags;
+               __entry->refs           = atomic_read(&map->refs);
+               __entry->compress_type  = map->compress_type;
+       ),
+
+       TP_printk("root = %llu(%s), start = %llu, len = %llu, "
+                 "orig_start = %llu, block_start = %llu(%s), "
+                 "block_len = %llu, flags = %s, refs = %u, "
+                 "compress_type = %u",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->start,
+                 (unsigned long long)__entry->len,
+                 (unsigned long long)__entry->orig_start,
+                 show_map_type(__entry->block_start),
+                 (unsigned long long)__entry->block_len,
+                 show_map_flags(__entry->flags),
+                 __entry->refs, __entry->compress_type)
+);
+
+#define show_ordered_flags(flags)                                      \
+       __print_symbolic(flags,                                 \
+               { BTRFS_ORDERED_IO_DONE,        "IO_DONE"       },      \
+               { BTRFS_ORDERED_COMPLETE,       "COMPLETE"      },      \
+               { BTRFS_ORDERED_NOCOW,          "NOCOW"         },      \
+               { BTRFS_ORDERED_COMPRESSED,     "COMPRESSED"    },      \
+               { BTRFS_ORDERED_PREALLOC,       "PREALLOC"      },      \
+               { BTRFS_ORDERED_DIRECT,         "DIRECT"        })
+
+DECLARE_EVENT_CLASS(btrfs__ordered_extent,
+
+       TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered),
+
+       TP_ARGS(inode, ordered),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino             )
+               __field(        u64,  file_offset       )
+               __field(        u64,  start             )
+               __field(        u64,  len               )
+               __field(        u64,  disk_len          )
+               __field(        u64,  bytes_left        )
+               __field(        unsigned long,  flags   )
+               __field(        int,  compress_type     )
+               __field(        int,  refs              )
+               __field(        u64,  root_objectid     )
+       ),
+
+       TP_fast_assign(
+               __entry->ino            = inode->i_ino;
+               __entry->file_offset    = ordered->file_offset;
+               __entry->start          = ordered->start;
+               __entry->len            = ordered->len;
+               __entry->disk_len       = ordered->disk_len;
+               __entry->bytes_left     = ordered->bytes_left;
+               __entry->flags          = ordered->flags;
+               __entry->compress_type  = ordered->compress_type;
+               __entry->refs           = atomic_read(&ordered->refs);
+               __entry->root_objectid  =
+                               BTRFS_I(inode)->root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), ino = %llu, file_offset = %llu, "
+                 "start = %llu, len = %llu, disk_len = %llu, "
+                 "bytes_left = %llu, flags = %s, compress_type = %d, "
+                 "refs = %d",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->ino,
+                 (unsigned long long)__entry->file_offset,
+                 (unsigned long long)__entry->start,
+                 (unsigned long long)__entry->len,
+                 (unsigned long long)__entry->disk_len,
+                 (unsigned long long)__entry->bytes_left,
+                 show_ordered_flags(__entry->flags),
+                 __entry->compress_type, __entry->refs)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_add,
+
+       TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered),
+
+       TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_remove,
+
+       TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered),
+
+       TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_start,
+
+       TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered),
+
+       TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
+
+       TP_PROTO(struct inode *inode, struct btrfs_ordered_extent *ordered),
+
+       TP_ARGS(inode, ordered)
+);
+
+DECLARE_EVENT_CLASS(btrfs__writepage,
+
+       TP_PROTO(struct page *page, struct inode *inode,
+                struct writeback_control *wbc),
+
+       TP_ARGS(page, inode, wbc),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino                     )
+               __field(        pgoff_t,  index                 )
+               __field(        long,   nr_to_write             )
+               __field(        long,   pages_skipped           )
+               __field(        loff_t, range_start             )
+               __field(        loff_t, range_end               )
+               __field(        char,   nonblocking             )
+               __field(        char,   for_kupdate             )
+               __field(        char,   for_reclaim             )
+               __field(        char,   range_cyclic            )
+               __field(        pgoff_t,  writeback_index       )
+               __field(        u64,    root_objectid           )
+       ),
+
+       TP_fast_assign(
+               __entry->ino            = inode->i_ino;
+               __entry->index          = page->index;
+               __entry->nr_to_write    = wbc->nr_to_write;
+               __entry->pages_skipped  = wbc->pages_skipped;
+               __entry->range_start    = wbc->range_start;
+               __entry->range_end      = wbc->range_end;
+               __entry->nonblocking    = wbc->nonblocking;
+               __entry->for_kupdate    = wbc->for_kupdate;
+               __entry->for_reclaim    = wbc->for_reclaim;
+               __entry->range_cyclic   = wbc->range_cyclic;
+               __entry->writeback_index = inode->i_mapping->writeback_index;
+               __entry->root_objectid  =
+                                BTRFS_I(inode)->root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, "
+                 "nr_to_write = %ld, pages_skipped = %ld, range_start = %llu, "
+                 "range_end = %llu, nonblocking = %d, for_kupdate = %d, "
+                 "for_reclaim = %d, range_cyclic = %d, writeback_index = %lu",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long)__entry->ino, __entry->index,
+                 __entry->nr_to_write, __entry->pages_skipped,
+                 __entry->range_start, __entry->range_end,
+                 __entry->nonblocking, __entry->for_kupdate,
+                 __entry->for_reclaim, __entry->range_cyclic,
+                 (unsigned long)__entry->writeback_index)
+);
+
+DEFINE_EVENT(btrfs__writepage, __extent_writepage,
+
+       TP_PROTO(struct page *page, struct inode *inode,
+                struct writeback_control *wbc),
+
+       TP_ARGS(page, inode, wbc)
+);
+
+TRACE_EVENT(btrfs_writepage_end_io_hook,
+
+       TP_PROTO(struct page *page, u64 start, u64 end, int uptodate),
+
+       TP_ARGS(page, start, end, uptodate),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,   ino            )
+               __field(        pgoff_t, index          )
+               __field(        u64,     start          )
+               __field(        u64,     end            )
+               __field(        int,     uptodate       )
+               __field(        u64,    root_objectid   )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = page->mapping->host->i_ino;
+               __entry->index  = page->index;
+               __entry->start  = start;
+               __entry->end    = end;
+               __entry->uptodate = uptodate;
+               __entry->root_objectid  =
+                        BTRFS_I(page->mapping->host)->root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, start = %llu, "
+                 "end = %llu, uptodate = %d",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long)__entry->ino, (unsigned long)__entry->index,
+                 (unsigned long long)__entry->start,
+                 (unsigned long long)__entry->end, __entry->uptodate)
+);
+
+TRACE_EVENT(btrfs_sync_file,
+
+       TP_PROTO(struct file *file, int datasync),
+
+       TP_ARGS(file, datasync),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino             )
+               __field(        ino_t,  parent          )
+               __field(        int,    datasync        )
+               __field(        u64,    root_objectid   )
+       ),
+
+       TP_fast_assign(
+               struct dentry *dentry = file->f_path.dentry;
+               struct inode *inode = dentry->d_inode;
+
+               __entry->ino            = inode->i_ino;
+               __entry->parent         = dentry->d_parent->d_inode->i_ino;
+               __entry->datasync       = datasync;
+               __entry->root_objectid  =
+                                BTRFS_I(inode)->root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), ino = %ld, parent = %ld, datasync = %d",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long)__entry->ino, (unsigned long)__entry->parent,
+                 __entry->datasync)
+);
+
+TRACE_EVENT(btrfs_sync_fs,
+
+       TP_PROTO(int wait),
+
+       TP_ARGS(wait),
+
+       TP_STRUCT__entry(
+               __field(        int,  wait              )
+       ),
+
+       TP_fast_assign(
+               __entry->wait   = wait;
+       ),
+
+       TP_printk("wait = %d", __entry->wait)
+);
+
+#define show_ref_action(action)                                                \
+       __print_symbolic(action,                                        \
+               { BTRFS_ADD_DELAYED_REF,    "ADD_DELAYED_REF" },        \
+               { BTRFS_DROP_DELAYED_REF,   "DROP_DELAYED_REF" },       \
+               { BTRFS_ADD_DELAYED_EXTENT, "ADD_DELAYED_EXTENT" },     \
+               { BTRFS_UPDATE_DELAYED_HEAD, "UPDATE_DELAYED_HEAD" })
+                       
+
+TRACE_EVENT(btrfs_delayed_tree_ref,
+
+       TP_PROTO(struct btrfs_delayed_ref_node *ref,
+                struct btrfs_delayed_tree_ref *full_ref,
+                int action),
+
+       TP_ARGS(ref, full_ref, action),
+
+       TP_STRUCT__entry(
+               __field(        u64,  bytenr            )
+               __field(        u64,  num_bytes         )
+               __field(        int,  action            ) 
+               __field(        u64,  parent            )
+               __field(        u64,  ref_root          )
+               __field(        int,  level             )
+               __field(        int,  type              )
+       ),
+
+       TP_fast_assign(
+               __entry->bytenr         = ref->bytenr;
+               __entry->num_bytes      = ref->num_bytes;
+               __entry->action         = action;
+               __entry->parent         = full_ref->parent;
+               __entry->ref_root       = full_ref->root;
+               __entry->level          = full_ref->level;
+               __entry->type           = ref->type;
+       ),
+
+       TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
+                 "parent = %llu(%s), ref_root = %llu(%s), level = %d, "
+                 "type = %s",
+                 (unsigned long long)__entry->bytenr,
+                 (unsigned long long)__entry->num_bytes,
+                 show_ref_action(__entry->action),
+                 show_root_type(__entry->parent),
+                 show_root_type(__entry->ref_root),
+                 __entry->level, show_ref_type(__entry->type))
+);
+
+TRACE_EVENT(btrfs_delayed_data_ref,
+
+       TP_PROTO(struct btrfs_delayed_ref_node *ref,
+                struct btrfs_delayed_data_ref *full_ref,
+                int action),
+
+       TP_ARGS(ref, full_ref, action),
+
+       TP_STRUCT__entry(
+               __field(        u64,  bytenr            )
+               __field(        u64,  num_bytes         )
+               __field(        int,  action            ) 
+               __field(        u64,  parent            )
+               __field(        u64,  ref_root          )
+               __field(        u64,  owner             )
+               __field(        u64,  offset            )
+               __field(        int,  type              )
+       ),
+
+       TP_fast_assign(
+               __entry->bytenr         = ref->bytenr;
+               __entry->num_bytes      = ref->num_bytes;
+               __entry->action         = action;
+               __entry->parent         = full_ref->parent;
+               __entry->ref_root       = full_ref->root;
+               __entry->owner          = full_ref->objectid;
+               __entry->offset         = full_ref->offset;
+               __entry->type           = ref->type;
+       ),
+
+       TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
+                 "parent = %llu(%s), ref_root = %llu(%s), owner = %llu, "
+                 "offset = %llu, type = %s",
+                 (unsigned long long)__entry->bytenr,
+                 (unsigned long long)__entry->num_bytes,
+                 show_ref_action(__entry->action),
+                 show_root_type(__entry->parent),
+                 show_root_type(__entry->ref_root),
+                 (unsigned long long)__entry->owner,
+                 (unsigned long long)__entry->offset,
+                 show_ref_type(__entry->type))
+);
+
+TRACE_EVENT(btrfs_delayed_ref_head,
+
+       TP_PROTO(struct btrfs_delayed_ref_node *ref,
+                struct btrfs_delayed_ref_head *head_ref,
+                int action),
+
+       TP_ARGS(ref, head_ref, action),
+
+       TP_STRUCT__entry(
+               __field(        u64,  bytenr            )
+               __field(        u64,  num_bytes         )
+               __field(        int,  action            ) 
+               __field(        int,  is_data           )
+       ),
+
+       TP_fast_assign(
+               __entry->bytenr         = ref->bytenr;
+               __entry->num_bytes      = ref->num_bytes;
+               __entry->action         = action;
+               __entry->is_data        = head_ref->is_data;
+       ),
+
+       TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, is_data = %d",
+                 (unsigned long long)__entry->bytenr,
+                 (unsigned long long)__entry->num_bytes,
+                 show_ref_action(__entry->action),
+                 __entry->is_data)
+);
+
+#define show_chunk_type(type)                                  \
+       __print_flags(type, "|",                                \
+               { BTRFS_BLOCK_GROUP_DATA,       "DATA"  },      \
+               { BTRFS_BLOCK_GROUP_SYSTEM,     "SYSTEM"},      \
+               { BTRFS_BLOCK_GROUP_METADATA,   "METADATA"},    \
+               { BTRFS_BLOCK_GROUP_RAID0,      "RAID0" },      \
+               { BTRFS_BLOCK_GROUP_RAID1,      "RAID1" },      \
+               { BTRFS_BLOCK_GROUP_DUP,        "DUP"   },      \
+               { BTRFS_BLOCK_GROUP_RAID10,     "RAID10"})
+
+DECLARE_EVENT_CLASS(btrfs__chunk,
+
+       TP_PROTO(struct btrfs_root *root, struct map_lookup *map,
+                u64 offset, u64 size),
+
+       TP_ARGS(root, map, offset, size),
+
+       TP_STRUCT__entry(
+               __field(        int,  num_stripes               )
+               __field(        u64,  type                      )
+               __field(        int,  sub_stripes               )
+               __field(        u64,  offset                    )
+               __field(        u64,  size                      )
+               __field(        u64,  root_objectid             )
+       ),
+
+       TP_fast_assign(
+               __entry->num_stripes    = map->num_stripes;
+               __entry->type           = map->type;
+               __entry->sub_stripes    = map->sub_stripes;
+               __entry->offset         = offset;
+               __entry->size           = size;
+               __entry->root_objectid  = root->root_key.objectid;
+       ),
+
+       TP_printk("root = %llu(%s), offset = %llu, size = %llu, "
+                 "num_stripes = %d, sub_stripes = %d, type = %s",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->offset,
+                 (unsigned long long)__entry->size,
+                 __entry->num_stripes, __entry->sub_stripes,
+                 show_chunk_type(__entry->type))
+);
+
+DEFINE_EVENT(btrfs__chunk,  btrfs_chunk_alloc,
+
+       TP_PROTO(struct btrfs_root *root, struct map_lookup *map,
+                u64 offset, u64 size),
+
+       TP_ARGS(root, map, offset, size)
+);
+
+DEFINE_EVENT(btrfs__chunk,  btrfs_chunk_free,
+
+       TP_PROTO(struct btrfs_root *root, struct map_lookup *map,
+                u64 offset, u64 size),
+
+       TP_ARGS(root, map, offset, size)
+);
+
+TRACE_EVENT(btrfs_cow_block,
+
+       TP_PROTO(struct btrfs_root *root, struct extent_buffer *buf,
+                struct extent_buffer *cow),
+
+       TP_ARGS(root, buf, cow),
+
+       TP_STRUCT__entry(
+               __field(        u64,  root_objectid             )
+               __field(        u64,  buf_start                 )
+               __field(        int,  refs                      )
+               __field(        u64,  cow_start                 )
+               __field(        int,  buf_level                 )
+               __field(        int,  cow_level                 )
+       ),
+
+       TP_fast_assign(
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->buf_start      = buf->start;
+               __entry->refs           = atomic_read(&buf->refs);
+               __entry->cow_start      = cow->start;
+               __entry->buf_level      = btrfs_header_level(buf);
+               __entry->cow_level      = btrfs_header_level(cow);
+       ),
+
+       TP_printk("root = %llu(%s), refs = %d, orig_buf = %llu "
+                 "(orig_level = %d), cow_buf = %llu (cow_level = %d)",
+                 show_root_type(__entry->root_objectid),
+                 __entry->refs,
+                 (unsigned long long)__entry->buf_start,
+                 __entry->buf_level,
+                 (unsigned long long)__entry->cow_start,
+                 __entry->cow_level)
+);
+
+DECLARE_EVENT_CLASS(btrfs__reserved_extent,
+
+       TP_PROTO(struct btrfs_root *root, u64 start, u64 len),
+
+       TP_ARGS(root, start, len),
+
+       TP_STRUCT__entry(
+               __field(        u64,  root_objectid             )
+               __field(        u64,  start                     )
+               __field(        u64,  len                       )
+       ),
+
+       TP_fast_assign(
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->start          = start;
+               __entry->len            = len;
+       ),
+
+       TP_printk("root = %llu(%s), start = %llu, len = %llu",
+                 show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->start,
+                 (unsigned long long)__entry->len)
+);
+
+DEFINE_EVENT(btrfs__reserved_extent,  btrfs_reserved_extent_alloc,
+
+       TP_PROTO(struct btrfs_root *root, u64 start, u64 len),
+
+       TP_ARGS(root, start, len)
+);
+
+DEFINE_EVENT(btrfs__reserved_extent,  btrfs_reserved_extent_free,
+
+       TP_PROTO(struct btrfs_root *root, u64 start, u64 len),
+
+       TP_ARGS(root, start, len)
+);
+
+#endif /* _TRACE_BTRFS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 8fd1b891ec0c71c7a7ad8052f46da47709d2f029..5c0d28921ba8c66a5d22bbcd1a40c4acdd54a4a4 100644 (file)
@@ -317,6 +317,7 @@ retry:
 
 /**
  *     ipc_check_perms -       check security and permissions for an IPC
+ *     @ns: IPC namespace
  *     @ipcp: ipc permission set
  *     @ops: the actual security routine to call
  *     @params: its parameters
@@ -607,6 +608,7 @@ void ipc_rcu_putref(void *ptr)
 
 /**
  *     ipcperms        -       check IPC permissions
+ *     @ns: IPC namespace
  *     @ipcp: IPC permission set
  *     @flag: desired permission set.
  *
@@ -769,7 +771,7 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
 
 /**
  * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
- * @ids:  the ipc namespace
+ * @ns:  the ipc namespace
  * @ids:  the table of ids where to look for the ipc
  * @id:   the id of the ipc to retrieve
  * @cmd:  the cmd to check
index 00f2c037267aa622780fd9f12dd555096116586e..a69c333f78e429314a3ca72dc8813ffa5c224555 100644 (file)
@@ -10,10 +10,6 @@ menu "IRQ subsystem"
 config GENERIC_HARDIRQS
        def_bool y
 
-# Select this to disable the deprecated stuff
-config GENERIC_HARDIRQS_NO_DEPRECATED
-       bool
-
 config GENERIC_HARDIRQS_NO_COMPAT
        bool
 
@@ -51,6 +47,10 @@ config HARDIRQS_SW_RESEND
 config IRQ_PREFLOW_FASTEOI
        bool
 
+# Edge style eoi based handler (cell)
+config IRQ_EDGE_EOI_HANDLER
+       bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
index 394784c57060257e77666fdb9173697cf1a35092..342d8f44e4010d13cb03f21b89a57d9dc955497e 100644 (file)
@@ -70,10 +70,8 @@ unsigned long probe_irq_on(void)
                raw_spin_lock_irq(&desc->lock);
                if (!desc->action && irq_settings_can_probe(desc)) {
                        desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
-                       if (irq_startup(desc)) {
-                               irq_compat_set_pending(desc);
+                       if (irq_startup(desc))
                                desc->istate |= IRQS_PENDING;
-                       }
                }
                raw_spin_unlock_irq(&desc->lock);
        }
index c9c0601f0615a1eaef8e3c425c61662395987c8e..1dafc8652bd893aceef6194cfbd6e03134d21e91 100644 (file)
@@ -34,9 +34,14 @@ int irq_set_chip(unsigned int irq, struct irq_chip *chip)
        if (!chip)
                chip = &no_irq_chip;
 
-       irq_chip_set_defaults(chip);
        desc->irq_data.chip = chip;
        irq_put_desc_unlock(desc, flags);
+       /*
+        * For !CONFIG_SPARSE_IRQ make the irq show up in
+        * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is
+        * already marked, and this call is harmless.
+        */
+       irq_reserve_irq(irq);
        return 0;
 }
 EXPORT_SYMBOL(irq_set_chip);
@@ -134,26 +139,22 @@ EXPORT_SYMBOL_GPL(irq_get_irq_data);
 
 static void irq_state_clr_disabled(struct irq_desc *desc)
 {
-       desc->istate &= ~IRQS_DISABLED;
-       irq_compat_clr_disabled(desc);
+       irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED);
 }
 
 static void irq_state_set_disabled(struct irq_desc *desc)
 {
-       desc->istate |= IRQS_DISABLED;
-       irq_compat_set_disabled(desc);
+       irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
 }
 
 static void irq_state_clr_masked(struct irq_desc *desc)
 {
-       desc->istate &= ~IRQS_MASKED;
-       irq_compat_clr_masked(desc);
+       irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED);
 }
 
 static void irq_state_set_masked(struct irq_desc *desc)
 {
-       desc->istate |= IRQS_MASKED;
-       irq_compat_set_masked(desc);
+       irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
 }
 
 int irq_startup(struct irq_desc *desc)
@@ -203,126 +204,6 @@ void irq_disable(struct irq_desc *desc)
        }
 }
 
-#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)
-{
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
-       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;
-       if (!chip->end)
-               chip->end = dummy_irq_chip.end;
-       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)
 {
        if (desc->irq_data.chip->irq_mask_ack)
@@ -372,11 +253,10 @@ void handle_nested_irq(unsigned int irq)
        kstat_incr_irqs_this_cpu(irq, desc);
 
        action = desc->action;
-       if (unlikely(!action || (desc->istate & IRQS_DISABLED)))
+       if (unlikely(!action || irqd_irq_disabled(&desc->irq_data)))
                goto out_unlock;
 
-       irq_compat_set_progress(desc);
-       desc->istate |= IRQS_INPROGRESS;
+       irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
        raw_spin_unlock_irq(&desc->lock);
 
        action_ret = action->thread_fn(action->irq, action->dev_id);
@@ -384,8 +264,7 @@ void handle_nested_irq(unsigned int irq)
                note_interrupt(irq, desc, action_ret);
 
        raw_spin_lock_irq(&desc->lock);
-       desc->istate &= ~IRQS_INPROGRESS;
-       irq_compat_clr_progress(desc);
+       irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
 
 out_unlock:
        raw_spin_unlock_irq(&desc->lock);
@@ -416,14 +295,14 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
 
-       if (unlikely(desc->istate & IRQS_INPROGRESS))
+       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
                if (!irq_check_poll(desc))
                        goto out_unlock;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
        kstat_incr_irqs_this_cpu(irq, desc);
 
-       if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED)))
+       if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data)))
                goto out_unlock;
 
        handle_irq_event(desc);
@@ -448,7 +327,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
        mask_ack_irq(desc);
 
-       if (unlikely(desc->istate & IRQS_INPROGRESS))
+       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
                if (!irq_check_poll(desc))
                        goto out_unlock;
 
@@ -459,12 +338,12 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
         * If its disabled or no action available
         * keep it masked and get out of here
         */
-       if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED)))
+       if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data)))
                goto out_unlock;
 
        handle_irq_event(desc);
 
-       if (!(desc->istate & (IRQS_DISABLED | IRQS_ONESHOT)))
+       if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT))
                unmask_irq(desc);
 out_unlock:
        raw_spin_unlock(&desc->lock);
@@ -496,7 +375,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
 
-       if (unlikely(desc->istate & IRQS_INPROGRESS))
+       if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
                if (!irq_check_poll(desc))
                        goto out;
 
@@ -507,8 +386,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
         * If its disabled or no action available
         * then mask it and get out of here:
         */
-       if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) {
-               irq_compat_set_pending(desc);
+       if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
                desc->istate |= IRQS_PENDING;
                mask_irq(desc);
                goto out;
@@ -558,10 +436,9 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
         * we shouldn't process the IRQ. Mark it pending, handle
         * the necessary masking and go out
         */
-       if (unlikely((desc->istate & (IRQS_DISABLED | IRQS_INPROGRESS) ||
-                     !desc->action))) {
+       if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
+                    irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
                if (!irq_check_poll(desc)) {
-                       irq_compat_set_pending(desc);
                        desc->istate |= IRQS_PENDING;
                        mask_ack_irq(desc);
                        goto out_unlock;
@@ -584,20 +461,65 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                 * Renable it, if it was not disabled in meantime.
                 */
                if (unlikely(desc->istate & IRQS_PENDING)) {
-                       if (!(desc->istate & IRQS_DISABLED) &&
-                           (desc->istate & IRQS_MASKED))
+                       if (!irqd_irq_disabled(&desc->irq_data) &&
+                           irqd_irq_masked(&desc->irq_data))
                                unmask_irq(desc);
                }
 
                handle_irq_event(desc);
 
        } while ((desc->istate & IRQS_PENDING) &&
-                !(desc->istate & IRQS_DISABLED));
+                !irqd_irq_disabled(&desc->irq_data));
 
 out_unlock:
        raw_spin_unlock(&desc->lock);
 }
 
+#ifdef CONFIG_IRQ_EDGE_EOI_HANDLER
+/**
+ *     handle_edge_eoi_irq - edge eoi type IRQ handler
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *
+ * Similar as the above handle_edge_irq, but using eoi and w/o the
+ * mask/unmask logic.
+ */
+void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       raw_spin_lock(&desc->lock);
+
+       desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+       /*
+        * If we're currently running this IRQ, or its disabled,
+        * we shouldn't process the IRQ. Mark it pending, handle
+        * the necessary masking and go out
+        */
+       if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
+                    irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
+               if (!irq_check_poll(desc)) {
+                       desc->istate |= IRQS_PENDING;
+                       goto out_eoi;
+               }
+       }
+       kstat_incr_irqs_this_cpu(irq, desc);
+
+       do {
+               if (unlikely(!desc->action))
+                       goto out_eoi;
+
+               handle_irq_event(desc);
+
+       } while ((desc->istate & IRQS_PENDING) &&
+                !irqd_irq_disabled(&desc->irq_data));
+
+out_eoi:
+       chip->irq_eoi(&desc->irq_data);
+       raw_spin_unlock(&desc->lock);
+}
+#endif
+
 /**
  *     handle_percpu_irq - Per CPU local irq handler
  *     @irq:   the interrupt number
@@ -642,8 +564,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
        if (handle == handle_bad_irq) {
                if (desc->irq_data.chip != &no_irq_chip)
                        mask_ack_irq(desc);
-               irq_compat_set_disabled(desc);
-               desc->istate |= IRQS_DISABLED;
+               irq_state_set_disabled(desc);
                desc->depth = 1;
        }
        desc->handle_irq = handle;
@@ -684,8 +605,70 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
                irqd_set(&desc->irq_data, IRQD_PER_CPU);
        if (irq_settings_can_move_pcntxt(desc))
                irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT);
+       if (irq_settings_is_level(desc))
+               irqd_set(&desc->irq_data, IRQD_LEVEL);
 
        irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc));
 
        irq_put_desc_unlock(desc, flags);
 }
+
+/**
+ *     irq_cpu_online - Invoke all irq_cpu_online functions.
+ *
+ *     Iterate through all irqs and invoke the chip.irq_cpu_online()
+ *     for each.
+ */
+void irq_cpu_online(void)
+{
+       struct irq_desc *desc;
+       struct irq_chip *chip;
+       unsigned long flags;
+       unsigned int irq;
+
+       for_each_active_irq(irq) {
+               desc = irq_to_desc(irq);
+               if (!desc)
+                       continue;
+
+               raw_spin_lock_irqsave(&desc->lock, flags);
+
+               chip = irq_data_get_irq_chip(&desc->irq_data);
+               if (chip && chip->irq_cpu_online &&
+                   (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
+                    !irqd_irq_disabled(&desc->irq_data)))
+                       chip->irq_cpu_online(&desc->irq_data);
+
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
+       }
+}
+
+/**
+ *     irq_cpu_offline - Invoke all irq_cpu_offline functions.
+ *
+ *     Iterate through all irqs and invoke the chip.irq_cpu_offline()
+ *     for each.
+ */
+void irq_cpu_offline(void)
+{
+       struct irq_desc *desc;
+       struct irq_chip *chip;
+       unsigned long flags;
+       unsigned int irq;
+
+       for_each_active_irq(irq) {
+               desc = irq_to_desc(irq);
+               if (!desc)
+                       continue;
+
+               raw_spin_lock_irqsave(&desc->lock, flags);
+
+               chip = irq_data_get_irq_chip(&desc->irq_data);
+               if (chip && chip->irq_cpu_offline &&
+                   (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
+                    !irqd_irq_disabled(&desc->irq_data)))
+                       chip->irq_cpu_offline(&desc->irq_data);
+
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
+       }
+}
diff --git a/kernel/irq/compat.h b/kernel/irq/compat.h
deleted file mode 100644 (file)
index 6bbaf66..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Compat layer for transition period
- */
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-static inline void irq_compat_set_progress(struct irq_desc *desc)
-{
-       desc->status |= IRQ_INPROGRESS;
-}
-
-static inline void irq_compat_clr_progress(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_INPROGRESS;
-}
-static inline void irq_compat_set_disabled(struct irq_desc *desc)
-{
-       desc->status |= IRQ_DISABLED;
-}
-static inline void irq_compat_clr_disabled(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_DISABLED;
-}
-static inline void irq_compat_set_pending(struct irq_desc *desc)
-{
-       desc->status |= IRQ_PENDING;
-}
-
-static inline void irq_compat_clr_pending(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_PENDING;
-}
-static inline void irq_compat_set_masked(struct irq_desc *desc)
-{
-       desc->status |= IRQ_MASKED;
-}
-
-static inline void irq_compat_clr_masked(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_MASKED;
-}
-static inline void irq_compat_set_move_pending(struct irq_desc *desc)
-{
-       desc->status |= IRQ_MOVE_PENDING;
-}
-
-static inline void irq_compat_clr_move_pending(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_MOVE_PENDING;
-}
-static inline void irq_compat_set_affinity(struct irq_desc *desc)
-{
-       desc->status |= IRQ_AFFINITY_SET;
-}
-
-static inline void irq_compat_clr_affinity(struct irq_desc *desc)
-{
-       desc->status &= ~IRQ_AFFINITY_SET;
-}
-#else
-static inline void irq_compat_set_progress(struct irq_desc *desc) { }
-static inline void irq_compat_clr_progress(struct irq_desc *desc) { }
-static inline void irq_compat_set_disabled(struct irq_desc *desc) { }
-static inline void irq_compat_clr_disabled(struct irq_desc *desc) { }
-static inline void irq_compat_set_pending(struct irq_desc *desc) { }
-static inline void irq_compat_clr_pending(struct irq_desc *desc) { }
-static inline void irq_compat_set_masked(struct irq_desc *desc) { }
-static inline void irq_compat_clr_masked(struct irq_desc *desc) { }
-static inline void irq_compat_set_move_pending(struct irq_desc *desc) { }
-static inline void irq_compat_clr_move_pending(struct irq_desc *desc) { }
-static inline void irq_compat_set_affinity(struct irq_desc *desc) { }
-static inline void irq_compat_clr_affinity(struct irq_desc *desc) { }
-#endif
-
index d1a33b7fa61d8554e9a1cdf7188640802e47122d..306cba37e9a57280b869b3317852efe48b34e78f 100644 (file)
@@ -4,8 +4,10 @@
 
 #include <linux/kallsyms.h>
 
-#define P(f) if (desc->status & f) printk("%14s set\n", #f)
+#define P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
 #define PS(f) if (desc->istate & f) printk("%14s set\n", #f)
+/* FIXME */
+#define PD(f) do { } while (0)
 
 static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
 {
@@ -28,13 +30,15 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
        P(IRQ_NOAUTOEN);
 
        PS(IRQS_AUTODETECT);
-       PS(IRQS_INPROGRESS);
        PS(IRQS_REPLAY);
        PS(IRQS_WAITING);
-       PS(IRQS_DISABLED);
        PS(IRQS_PENDING);
-       PS(IRQS_MASKED);
+
+       PD(IRQS_INPROGRESS);
+       PD(IRQS_DISABLED);
+       PD(IRQS_MASKED);
 }
 
 #undef P
 #undef PS
+#undef PD
index 20dc5474947e5fafbefe4cd2eb5f3ac241403711..b5fcd96c7102253acc93b1a7239d5a172f927d8f 100644 (file)
@@ -31,13 +31,6 @@ 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
  */
@@ -48,7 +41,6 @@ struct irq_chip no_irq_chip = {
        .irq_enable     = noop,
        .irq_disable    = noop,
        .irq_ack        = ack_bad,
-       END_INIT
 };
 
 /*
@@ -64,5 +56,4 @@ struct irq_chip dummy_irq_chip = {
        .irq_ack        = noop,
        .irq_mask       = noop,
        .irq_unmask     = noop,
-       END_INIT
 };
index 517561fc73178b2f08dd7e12d32b4bf59d610517..90cb55f6d7ebe4496b339f5202f0a31926854963 100644 (file)
@@ -175,28 +175,13 @@ irqreturn_t handle_irq_event(struct irq_desc *desc)
        struct irqaction *action = desc->action;
        irqreturn_t ret;
 
-       irq_compat_clr_pending(desc);
        desc->istate &= ~IRQS_PENDING;
-       irq_compat_set_progress(desc);
-       desc->istate |= IRQS_INPROGRESS;
+       irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
        raw_spin_unlock(&desc->lock);
 
        ret = handle_irq_event_percpu(desc, action);
 
        raw_spin_lock(&desc->lock);
-       desc->istate &= ~IRQS_INPROGRESS;
-       irq_compat_clr_progress(desc);
+       irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
        return ret;
 }
-
-/**
- * handle_IRQ_event - irq action chain handler
- * @irq:       the interrupt number
- * @action:    the interrupt action chain for this irq
- *
- * Handles the action chain of an irq event
- */
-irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
-{
-       return handle_irq_event_percpu(irq_to_desc(irq), action);
-}
index 6c6ec9a490274e7c313f78eb202aa1c5af84f9b7..6546431447d766396b371595f6d46df41c883c9a 100644 (file)
 
 #define istate core_internal_state__do_not_mess_with_it
 
-#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
-# define status status_use_accessors
-#endif
-
 extern int noirqdebug;
 
 /*
@@ -44,38 +40,28 @@ enum {
  * IRQS_SPURIOUS_DISABLED      - was disabled due to spurious interrupt
  *                               detection
  * IRQS_POLL_INPROGRESS                - polling in progress
- * IRQS_INPROGRESS             - Interrupt in progress
  * IRQS_ONESHOT                        - irq is not unmasked in primary handler
  * IRQS_REPLAY                 - irq is replayed
  * IRQS_WAITING                        - irq is waiting
- * IRQS_DISABLED               - irq is disabled
  * IRQS_PENDING                        - irq is pending and replayed later
- * IRQS_MASKED                 - irq is masked
  * IRQS_SUSPENDED              - irq is suspended
  */
 enum {
        IRQS_AUTODETECT         = 0x00000001,
        IRQS_SPURIOUS_DISABLED  = 0x00000002,
        IRQS_POLL_INPROGRESS    = 0x00000008,
-       IRQS_INPROGRESS         = 0x00000010,
        IRQS_ONESHOT            = 0x00000020,
        IRQS_REPLAY             = 0x00000040,
        IRQS_WAITING            = 0x00000080,
-       IRQS_DISABLED           = 0x00000100,
        IRQS_PENDING            = 0x00000200,
-       IRQS_MASKED             = 0x00000400,
        IRQS_SUSPENDED          = 0x00000800,
 };
 
-#include "compat.h"
 #include "debug.h"
 #include "settings.h"
 
 #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);
-
 extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                unsigned long flags);
 extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
@@ -162,13 +148,11 @@ irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)
 static inline void irqd_set_move_pending(struct irq_data *d)
 {
        d->state_use_accessors |= IRQD_SETAFFINITY_PENDING;
-       irq_compat_set_move_pending(irq_data_to_desc(d));
 }
 
 static inline void irqd_clr_move_pending(struct irq_data *d)
 {
        d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING;
-       irq_compat_clr_move_pending(irq_data_to_desc(d));
 }
 
 static inline void irqd_clear(struct irq_data *d, unsigned int mask)
index 6fb014f172f7397a7edeec525d53a9b649dfcf25..2c039c9b9383a045b6d08b30b8c2a70a0e7ecf78 100644 (file)
@@ -80,7 +80,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
        desc->irq_data.handler_data = NULL;
        desc->irq_data.msi_desc = NULL;
        irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
-       desc->istate = IRQS_DISABLED;
+       irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
        desc->handle_irq = handle_bad_irq;
        desc->depth = 1;
        desc->irq_count = 0;
@@ -238,7 +238,6 @@ int __init early_irq_init(void)
 
 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
        [0 ... NR_IRQS-1] = {
-               .istate         = IRQS_DISABLED,
                .handle_irq     = handle_bad_irq,
                .depth          = 1,
                .lock           = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
index 0a2aa73e536c729a6dff5dfd7ea2afbf669c02bb..12a80fdae11cc7c0d4d76b34d4cae37c2343d1dd 100644 (file)
@@ -41,7 +41,7 @@ early_param("threadirqs", setup_forced_irqthreads);
 void synchronize_irq(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
-       unsigned int state;
+       bool inprogress;
 
        if (!desc)
                return;
@@ -53,16 +53,16 @@ void synchronize_irq(unsigned int irq)
                 * Wait until we're out of the critical section.  This might
                 * give the wrong answer due to the lack of memory barriers.
                 */
-               while (desc->istate & IRQS_INPROGRESS)
+               while (irqd_irq_inprogress(&desc->irq_data))
                        cpu_relax();
 
                /* Ok, that indicated we're done: double-check carefully. */
                raw_spin_lock_irqsave(&desc->lock, flags);
-               state = desc->istate;
+               inprogress = irqd_irq_inprogress(&desc->irq_data);
                raw_spin_unlock_irqrestore(&desc->lock, flags);
 
                /* Oops, that failed? */
-       } while (state & IRQS_INPROGRESS);
+       } while (inprogress);
 
        /*
         * We made sure that no hardirq handler is running. Now verify
@@ -112,13 +112,13 @@ void irq_set_thread_affinity(struct irq_desc *desc)
 }
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
-static inline bool irq_can_move_pcntxt(struct irq_desc *desc)
+static inline bool irq_can_move_pcntxt(struct irq_data *data)
 {
-       return irq_settings_can_move_pcntxt(desc);
+       return irqd_can_move_in_process_context(data);
 }
-static inline bool irq_move_pending(struct irq_desc *desc)
+static inline bool irq_move_pending(struct irq_data *data)
 {
-       return irqd_is_setaffinity_pending(&desc->irq_data);
+       return irqd_is_setaffinity_pending(data);
 }
 static inline void
 irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask)
@@ -131,43 +131,34 @@ irq_get_pending(struct cpumask *mask, struct irq_desc *desc)
        cpumask_copy(mask, desc->pending_mask);
 }
 #else
-static inline bool irq_can_move_pcntxt(struct irq_desc *desc) { return true; }
-static inline bool irq_move_pending(struct irq_desc *desc) { return false; }
+static inline bool irq_can_move_pcntxt(struct irq_data *data) { return true; }
+static inline bool irq_move_pending(struct irq_data *data) { return false; }
 static inline void
 irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { }
 static inline void
 irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { }
 #endif
 
-/**
- *     irq_set_affinity - Set the irq affinity of a given irq
- *     @irq:           Interrupt to set affinity
- *     @cpumask:       cpumask
- *
- */
-int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
+int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_chip *chip = desc->irq_data.chip;
-       unsigned long flags;
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       struct irq_desc *desc = irq_data_to_desc(data);
        int ret = 0;
 
-       if (!chip->irq_set_affinity)
+       if (!chip || !chip->irq_set_affinity)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&desc->lock, flags);
-
-       if (irq_can_move_pcntxt(desc)) {
-               ret = chip->irq_set_affinity(&desc->irq_data, mask, false);
+       if (irq_can_move_pcntxt(data)) {
+               ret = chip->irq_set_affinity(data, mask, false);
                switch (ret) {
                case IRQ_SET_MASK_OK:
-                       cpumask_copy(desc->irq_data.affinity, mask);
+                       cpumask_copy(data->affinity, mask);
                case IRQ_SET_MASK_OK_NOCOPY:
                        irq_set_thread_affinity(desc);
                        ret = 0;
                }
        } else {
-               irqd_set_move_pending(&desc->irq_data);
+               irqd_set_move_pending(data);
                irq_copy_pending(desc, mask);
        }
 
@@ -175,8 +166,28 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
                kref_get(&desc->affinity_notify->kref);
                schedule_work(&desc->affinity_notify->work);
        }
-       irq_compat_set_affinity(desc);
-       irqd_set(&desc->irq_data, IRQD_AFFINITY_SET);
+       irqd_set(data, IRQD_AFFINITY_SET);
+
+       return ret;
+}
+
+/**
+ *     irq_set_affinity - Set the irq affinity of a given irq
+ *     @irq:           Interrupt to set affinity
+ *     @mask:          cpumask
+ *
+ */
+int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+       unsigned long flags;
+       int ret;
+
+       if (!desc)
+               return -EINVAL;
+
+       raw_spin_lock_irqsave(&desc->lock, flags);
+       ret =  __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
        return ret;
 }
@@ -206,7 +217,7 @@ static void irq_affinity_notify(struct work_struct *work)
                goto out;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       if (irq_move_pending(desc))
+       if (irq_move_pending(&desc->irq_data))
                irq_get_pending(cpumask, desc);
        else
                cpumask_copy(cpumask, desc->irq_data.affinity);
@@ -285,10 +296,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
                if (cpumask_intersects(desc->irq_data.affinity,
                                       cpu_online_mask))
                        set = desc->irq_data.affinity;
-               else {
-                       irq_compat_clr_affinity(desc);
+               else
                        irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET);
-               }
        }
 
        cpumask_and(mask, cpu_online_mask, set);
@@ -551,9 +560,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
        flags &= IRQ_TYPE_SENSE_MASK;
 
        if (chip->flags & IRQCHIP_SET_TYPE_MASKED) {
-               if (!(desc->istate & IRQS_MASKED))
+               if (!irqd_irq_masked(&desc->irq_data))
                        mask_irq(desc);
-               if (!(desc->istate & IRQS_DISABLED))
+               if (!irqd_irq_disabled(&desc->irq_data))
                        unmask = 1;
        }
 
@@ -575,8 +584,6 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                        irqd_set(&desc->irq_data, IRQD_LEVEL);
                }
 
-               if (chip != desc->irq_data.chip)
-                       irq_chip_set_defaults(desc->irq_data.chip);
                ret = 0;
                break;
        default:
@@ -651,7 +658,7 @@ again:
         * irq_wake_thread(). See the comment there which explains the
         * serialization.
         */
-       if (unlikely(desc->istate & IRQS_INPROGRESS)) {
+       if (unlikely(irqd_irq_inprogress(&desc->irq_data))) {
                raw_spin_unlock_irq(&desc->lock);
                chip_bus_sync_unlock(desc);
                cpu_relax();
@@ -668,12 +675,10 @@ again:
 
        desc->threads_oneshot &= ~action->thread_mask;
 
-       if (!desc->threads_oneshot && !(desc->istate & IRQS_DISABLED) &&
-           (desc->istate & IRQS_MASKED)) {
-               irq_compat_clr_masked(desc);
-               desc->istate &= ~IRQS_MASKED;
-               desc->irq_data.chip->irq_unmask(&desc->irq_data);
-       }
+       if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
+           irqd_irq_masked(&desc->irq_data))
+               unmask_irq(desc);
+
 out_unlock:
        raw_spin_unlock_irq(&desc->lock);
        chip_bus_sync_unlock(desc);
@@ -767,7 +772,7 @@ static int irq_thread(void *data)
                atomic_inc(&desc->threads_active);
 
                raw_spin_lock_irq(&desc->lock);
-               if (unlikely(desc->istate & IRQS_DISABLED)) {
+               if (unlikely(irqd_irq_disabled(&desc->irq_data))) {
                        /*
                         * CHECKME: We might need a dedicated
                         * IRQ_THREAD_PENDING flag here, which
@@ -775,7 +780,6 @@ static int irq_thread(void *data)
                         * but AFAICT IRQS_PENDING should be fine as it
                         * retriggers the interrupt itself --- tglx
                         */
-                       irq_compat_set_pending(desc);
                        desc->istate |= IRQS_PENDING;
                        raw_spin_unlock_irq(&desc->lock);
                } else {
@@ -971,8 +975,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
        new->thread_mask = 1 << ffz(thread_mask);
 
        if (!shared) {
-               irq_chip_set_defaults(desc->irq_data.chip);
-
                init_waitqueue_head(&desc->wait_for_threads);
 
                /* Setup the type (level, edge polarity) if configured: */
@@ -985,8 +987,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                }
 
                desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
-                                 IRQS_INPROGRESS | IRQS_ONESHOT | \
-                                 IRQS_WAITING);
+                                 IRQS_ONESHOT | IRQS_WAITING);
+               irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
 
                if (new->flags & IRQF_PERCPU) {
                        irqd_set(&desc->irq_data, IRQD_PER_CPU);
index ec4806d4778b2143c03f94c1d067f56647928e06..bc6194698dfd48edf986d5380d1d9e487ba17c4a 100644 (file)
@@ -53,20 +53,14 @@ void irq_move_masked_irq(struct irq_data *idata)
        cpumask_clear(desc->pending_mask);
 }
 
-void move_masked_irq(int irq)
-{
-       irq_move_masked_irq(irq_get_irq_data(irq));
-}
-
 void irq_move_irq(struct irq_data *idata)
 {
-       struct irq_desc *desc = irq_data_to_desc(idata);
        bool masked;
 
        if (likely(!irqd_is_setaffinity_pending(idata)))
                return;
 
-       if (unlikely(desc->istate & IRQS_DISABLED))
+       if (unlikely(irqd_irq_disabled(idata)))
                return;
 
        /*
@@ -74,15 +68,10 @@ void irq_move_irq(struct irq_data *idata)
         * threaded interrupt with ONESHOT set, we can end up with an
         * interrupt storm.
         */
-       masked = desc->istate & IRQS_MASKED;
+       masked = irqd_irq_masked(idata);
        if (!masked)
                idata->chip->irq_mask(idata);
        irq_move_masked_irq(idata);
        if (!masked)
                idata->chip->irq_unmask(idata);
 }
-
-void move_native_irq(int irq)
-{
-       irq_move_irq(irq_get_irq_data(irq));
-}
index 626d092eed9a0d8b191f561b558c1478c7e45df6..dd201bd35103e221fc14debc1d09419529bf6f3d 100644 (file)
@@ -364,6 +364,10 @@ int __weak arch_show_interrupts(struct seq_file *p, int prec)
        return 0;
 }
 
+#ifndef ACTUAL_NR_IRQS
+# define ACTUAL_NR_IRQS nr_irqs
+#endif
+
 int show_interrupts(struct seq_file *p, void *v)
 {
        static int prec;
@@ -373,10 +377,10 @@ int show_interrupts(struct seq_file *p, void *v)
        struct irqaction *action;
        struct irq_desc *desc;
 
-       if (i > nr_irqs)
+       if (i > ACTUAL_NR_IRQS)
                return 0;
 
-       if (i == nr_irqs)
+       if (i == ACTUAL_NR_IRQS)
                return arch_show_interrupts(p, prec);
 
        /* print header and calculate the width of the first column */
index ad683a99b1ec434681892a4a37bf9bcb67cc9763..14dd5761e8c96e1508c72499e12c93edeb45a7ab 100644 (file)
@@ -65,7 +65,6 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
        if (desc->istate & IRQS_REPLAY)
                return;
        if (desc->istate & IRQS_PENDING) {
-               irq_compat_clr_pending(desc);
                desc->istate &= ~IRQS_PENDING;
                desc->istate |= IRQS_REPLAY;
 
index 0227ad3582726f8a35ed593b8ac01187c3c3a7d3..0d91730b6330b9b59594fd2486d5a493627d7fb3 100644 (file)
@@ -15,17 +15,8 @@ enum {
        _IRQF_MODIFY_MASK       = IRQF_MODIFY_MASK,
 };
 
-#define IRQ_INPROGRESS         GOT_YOU_MORON
-#define IRQ_REPLAY             GOT_YOU_MORON
-#define IRQ_WAITING            GOT_YOU_MORON
-#define IRQ_DISABLED           GOT_YOU_MORON
-#define IRQ_PENDING            GOT_YOU_MORON
-#define IRQ_MASKED             GOT_YOU_MORON
-#define IRQ_WAKEUP             GOT_YOU_MORON
-#define IRQ_MOVE_PENDING       GOT_YOU_MORON
 #define IRQ_PER_CPU            GOT_YOU_MORON
 #define IRQ_NO_BALANCING       GOT_YOU_MORON
-#define IRQ_AFFINITY_SET       GOT_YOU_MORON
 #define IRQ_LEVEL              GOT_YOU_MORON
 #define IRQ_NOPROBE            GOT_YOU_MORON
 #define IRQ_NOREQUEST          GOT_YOU_MORON
@@ -37,102 +28,98 @@ enum {
 static inline void
 irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set)
 {
-       desc->status &= ~(clr & _IRQF_MODIFY_MASK);
-       desc->status |= (set & _IRQF_MODIFY_MASK);
+       desc->status_use_accessors &= ~(clr & _IRQF_MODIFY_MASK);
+       desc->status_use_accessors |= (set & _IRQF_MODIFY_MASK);
 }
 
 static inline bool irq_settings_is_per_cpu(struct irq_desc *desc)
 {
-       return desc->status & _IRQ_PER_CPU;
+       return desc->status_use_accessors & _IRQ_PER_CPU;
 }
 
 static inline void irq_settings_set_per_cpu(struct irq_desc *desc)
 {
-       desc->status |= _IRQ_PER_CPU;
+       desc->status_use_accessors |= _IRQ_PER_CPU;
 }
 
 static inline void irq_settings_set_no_balancing(struct irq_desc *desc)
 {
-       desc->status |= _IRQ_NO_BALANCING;
+       desc->status_use_accessors |= _IRQ_NO_BALANCING;
 }
 
 static inline bool irq_settings_has_no_balance_set(struct irq_desc *desc)
 {
-       return desc->status & _IRQ_NO_BALANCING;
+       return desc->status_use_accessors & _IRQ_NO_BALANCING;
 }
 
 static inline u32 irq_settings_get_trigger_mask(struct irq_desc *desc)
 {
-       return desc->status & IRQ_TYPE_SENSE_MASK;
+       return desc->status_use_accessors & IRQ_TYPE_SENSE_MASK;
 }
 
 static inline void
 irq_settings_set_trigger_mask(struct irq_desc *desc, u32 mask)
 {
-       desc->status &= ~IRQ_TYPE_SENSE_MASK;
-       desc->status |= mask & IRQ_TYPE_SENSE_MASK;
+       desc->status_use_accessors &= ~IRQ_TYPE_SENSE_MASK;
+       desc->status_use_accessors |= mask & IRQ_TYPE_SENSE_MASK;
 }
 
 static inline bool irq_settings_is_level(struct irq_desc *desc)
 {
-       return desc->status & _IRQ_LEVEL;
+       return desc->status_use_accessors & _IRQ_LEVEL;
 }
 
 static inline void irq_settings_clr_level(struct irq_desc *desc)
 {
-       desc->status &= ~_IRQ_LEVEL;
+       desc->status_use_accessors &= ~_IRQ_LEVEL;
 }
 
 static inline void irq_settings_set_level(struct irq_desc *desc)
 {
-       desc->status |= _IRQ_LEVEL;
+       desc->status_use_accessors |= _IRQ_LEVEL;
 }
 
 static inline bool irq_settings_can_request(struct irq_desc *desc)
 {
-       return !(desc->status & _IRQ_NOREQUEST);
+       return !(desc->status_use_accessors & _IRQ_NOREQUEST);
 }
 
 static inline void irq_settings_clr_norequest(struct irq_desc *desc)
 {
-       desc->status &= ~_IRQ_NOREQUEST;
+       desc->status_use_accessors &= ~_IRQ_NOREQUEST;
 }
 
 static inline void irq_settings_set_norequest(struct irq_desc *desc)
 {
-       desc->status |= _IRQ_NOREQUEST;
+       desc->status_use_accessors |= _IRQ_NOREQUEST;
 }
 
 static inline bool irq_settings_can_probe(struct irq_desc *desc)
 {
-       return !(desc->status & _IRQ_NOPROBE);
+       return !(desc->status_use_accessors & _IRQ_NOPROBE);
 }
 
 static inline void irq_settings_clr_noprobe(struct irq_desc *desc)
 {
-       desc->status &= ~_IRQ_NOPROBE;
+       desc->status_use_accessors &= ~_IRQ_NOPROBE;
 }
 
 static inline void irq_settings_set_noprobe(struct irq_desc *desc)
 {
-       desc->status |= _IRQ_NOPROBE;
+       desc->status_use_accessors |= _IRQ_NOPROBE;
 }
 
 static inline bool irq_settings_can_move_pcntxt(struct irq_desc *desc)
 {
-       return desc->status & _IRQ_MOVE_PCNTXT;
+       return desc->status_use_accessors & _IRQ_MOVE_PCNTXT;
 }
 
 static inline bool irq_settings_can_autoenable(struct irq_desc *desc)
 {
-       return !(desc->status & _IRQ_NOAUTOEN);
+       return !(desc->status_use_accessors & _IRQ_NOAUTOEN);
 }
 
 static inline bool irq_settings_is_nested_thread(struct irq_desc *desc)
 {
-       return desc->status & _IRQ_NESTED_THREAD;
+       return desc->status_use_accessors & _IRQ_NESTED_THREAD;
 }
-
-/* Nothing should touch desc->status from now on */
-#undef status
-#define status         USE_THE_PROPER_WRAPPERS_YOU_MORON
index dd586ebf9c8c277216c1aa42ac2e63dcabc314c1..dfbd550401b28f29a4db69807fae318c8ec7341a 100644 (file)
@@ -45,12 +45,12 @@ bool irq_wait_for_poll(struct irq_desc *desc)
 #ifdef CONFIG_SMP
        do {
                raw_spin_unlock(&desc->lock);
-               while (desc->istate & IRQS_INPROGRESS)
+               while (irqd_irq_inprogress(&desc->irq_data))
                        cpu_relax();
                raw_spin_lock(&desc->lock);
-       } while (desc->istate & IRQS_INPROGRESS);
+       } while (irqd_irq_inprogress(&desc->irq_data));
        /* Might have been disabled in meantime */
-       return !(desc->istate & IRQS_DISABLED) && desc->action;
+       return !irqd_irq_disabled(&desc->irq_data) && desc->action;
 #else
        return false;
 #endif
@@ -75,7 +75,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
         * Do not poll disabled interrupts unless the spurious
         * disabled poller asks explicitely.
         */
-       if ((desc->istate & IRQS_DISABLED) && !force)
+       if (irqd_irq_disabled(&desc->irq_data) && !force)
                goto out;
 
        /*
@@ -88,12 +88,11 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
                goto out;
 
        /* Already running on another processor */
-       if (desc->istate & IRQS_INPROGRESS) {
+       if (irqd_irq_inprogress(&desc->irq_data)) {
                /*
                 * Already running: If it is shared get the other
                 * CPU to go looking for our mystery interrupt too
                 */
-               irq_compat_set_pending(desc);
                desc->istate |= IRQS_PENDING;
                goto out;
        }
index 324eff5468ad6c1a07ee0d43d6d4dffc301de9ac..1186cf7fac772ddfe6943078d246f8987356e59c 100644 (file)
@@ -2437,7 +2437,7 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
        /* Not even root can pretend to send signals from the kernel.
         * Nor can they impersonate a kill()/tgkill(), which adds source info.
         */
-       if (info.si_code != SI_QUEUE) {
+       if (info.si_code >= 0 || info.si_code == SI_TKILL) {
                /* We used to allow any < 0 si_code */
                WARN_ON_ONCE(info.si_code < 0);
                return -EPERM;
@@ -2457,7 +2457,7 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
        /* Not even root can pretend to send signals from the kernel.
         * Nor can they impersonate a kill()/tgkill(), which adds source info.
         */
-       if (info->si_code != SI_QUEUE) {
+       if (info->si_code >= 0 || info->si_code == SI_TKILL) {
                /* We used to allow any < 0 si_code */
                WARN_ON_ONCE(info->si_code < 0);
                return -EPERM;
index 23fa7a359db74008cbbb7d17599edcd480d76a97..9c10e38fc609b86605549eba4ce02b1b1cb09de1 100644 (file)
@@ -157,6 +157,45 @@ config REED_SOLOMON_ENC16
 config REED_SOLOMON_DEC16
        boolean
 
+#
+# BCH support is selected if needed
+#
+config BCH
+       tristate
+
+config BCH_CONST_PARAMS
+       boolean
+       help
+         Drivers may select this option to force specific constant
+         values for parameters 'm' (Galois field order) and 't'
+         (error correction capability). Those specific values must
+         be set by declaring default values for symbols BCH_CONST_M
+         and BCH_CONST_T.
+         Doing so will enable extra compiler optimizations,
+         improving encoding and decoding performance up to 2x for
+         usual (m,t) values (typically such that m*t < 200).
+         When this option is selected, the BCH library supports
+         only a single (m,t) configuration. This is mainly useful
+         for NAND flash board drivers requiring known, fixed BCH
+         parameters.
+
+config BCH_CONST_M
+       int
+       range 5 15
+       help
+         Constant value for Galois field order 'm'. If 'k' is the
+         number of data bits to protect, 'm' should be chosen such
+         that (k + m*t) <= 2**m - 1.
+         Drivers should declare a default value for this symbol if
+         they select option BCH_CONST_PARAMS.
+
+config BCH_CONST_T
+       int
+       help
+         Constant value for error correction capability in bits 't'.
+         Drivers should declare a default value for this symbol if
+         they select option BCH_CONST_PARAMS.
+
 #
 # Textsearch support is select'ed if needed
 #
index d7872b5c4c1c375d92b5dd7468636a132932ca8f..ef0f285711566f87a964e6f4c1908776f5f60e29 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_BCH) += bch.o
 obj-$(CONFIG_LZO_COMPRESS) += lzo/
 obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
 obj-$(CONFIG_XZ_DEC) += xz/
diff --git a/lib/bch.c b/lib/bch.c
new file mode 100644 (file)
index 0000000..bc89dfe
--- /dev/null
+++ b/lib/bch.c
@@ -0,0 +1,1368 @@
+/*
+ * Generic binary BCH encoding/decoding library
+ *
+ * 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., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright Â© 2011 Parrot S.A.
+ *
+ * Author: Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * Description:
+ *
+ * This library provides runtime configurable encoding/decoding of binary
+ * Bose-Chaudhuri-Hocquenghem (BCH) codes.
+ *
+ * Call init_bch to get a pointer to a newly allocated bch_control structure for
+ * the given m (Galois field order), t (error correction capability) and
+ * (optional) primitive polynomial parameters.
+ *
+ * Call encode_bch to compute and store ecc parity bytes to a given buffer.
+ * Call decode_bch to detect and locate errors in received data.
+ *
+ * On systems supporting hw BCH features, intermediate results may be provided
+ * to decode_bch in order to skip certain steps. See decode_bch() documentation
+ * for details.
+ *
+ * Option CONFIG_BCH_CONST_PARAMS can be used to force fixed values of
+ * parameters m and t; thus allowing extra compiler optimizations and providing
+ * better (up to 2x) encoding performance. Using this option makes sense when
+ * (m,t) are fixed and known in advance, e.g. when using BCH error correction
+ * on a particular NAND flash device.
+ *
+ * Algorithmic details:
+ *
+ * Encoding is performed by processing 32 input bits in parallel, using 4
+ * remainder lookup tables.
+ *
+ * The final stage of decoding involves the following internal steps:
+ * a. Syndrome computation
+ * b. Error locator polynomial computation using Berlekamp-Massey algorithm
+ * c. Error locator root finding (by far the most expensive step)
+ *
+ * In this implementation, step c is not performed using the usual Chien search.
+ * Instead, an alternative approach described in [1] is used. It consists in
+ * factoring the error locator polynomial using the Berlekamp Trace algorithm
+ * (BTA) down to a certain degree (4), after which ad hoc low-degree polynomial
+ * solving techniques [2] are used. The resulting algorithm, called BTZ, yields
+ * much better performance than Chien search for usual (m,t) values (typically
+ * m >= 13, t < 32, see [1]).
+ *
+ * [1] B. Biswas, V. Herbert. Efficient root finding of polynomials over fields
+ * of characteristic 2, in: Western European Workshop on Research in Cryptology
+ * - WEWoRC 2009, Graz, Austria, LNCS, Springer, July 2009, to appear.
+ * [2] [Zin96] V.A. Zinoviev. On the solution of equations of degree 10 over
+ * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include <linux/bch.h>
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+#define GF_M(_p)               (CONFIG_BCH_CONST_M)
+#define GF_T(_p)               (CONFIG_BCH_CONST_T)
+#define GF_N(_p)               ((1 << (CONFIG_BCH_CONST_M))-1)
+#else
+#define GF_M(_p)               ((_p)->m)
+#define GF_T(_p)               ((_p)->t)
+#define GF_N(_p)               ((_p)->n)
+#endif
+
+#define BCH_ECC_WORDS(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
+#define BCH_ECC_BYTES(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
+
+#ifndef dbg
+#define dbg(_fmt, args...)     do {} while (0)
+#endif
+
+/*
+ * represent a polynomial over GF(2^m)
+ */
+struct gf_poly {
+       unsigned int deg;    /* polynomial degree */
+       unsigned int c[0];   /* polynomial terms */
+};
+
+/* given its degree, compute a polynomial size in bytes */
+#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
+
+/* polynomial of degree 1 */
+struct gf_poly_deg1 {
+       struct gf_poly poly;
+       unsigned int   c[2];
+};
+
+/*
+ * same as encode_bch(), but process input data one byte at a time
+ */
+static void encode_bch_unaligned(struct bch_control *bch,
+                                const unsigned char *data, unsigned int len,
+                                uint32_t *ecc)
+{
+       int i;
+       const uint32_t *p;
+       const int l = BCH_ECC_WORDS(bch)-1;
+
+       while (len--) {
+               p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
+
+               for (i = 0; i < l; i++)
+                       ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
+
+               ecc[l] = (ecc[l] << 8)^(*p);
+       }
+}
+
+/*
+ * convert ecc bytes to aligned, zero-padded 32-bit ecc words
+ */
+static void load_ecc8(struct bch_control *bch, uint32_t *dst,
+                     const uint8_t *src)
+{
+       uint8_t pad[4] = {0, 0, 0, 0};
+       unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+       for (i = 0; i < nwords; i++, src += 4)
+               dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
+
+       memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
+       dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
+}
+
+/*
+ * convert 32-bit ecc words to ecc bytes
+ */
+static void store_ecc8(struct bch_control *bch, uint8_t *dst,
+                      const uint32_t *src)
+{
+       uint8_t pad[4];
+       unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+       for (i = 0; i < nwords; i++) {
+               *dst++ = (src[i] >> 24);
+               *dst++ = (src[i] >> 16) & 0xff;
+               *dst++ = (src[i] >>  8) & 0xff;
+               *dst++ = (src[i] >>  0) & 0xff;
+       }
+       pad[0] = (src[nwords] >> 24);
+       pad[1] = (src[nwords] >> 16) & 0xff;
+       pad[2] = (src[nwords] >>  8) & 0xff;
+       pad[3] = (src[nwords] >>  0) & 0xff;
+       memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
+}
+
+/**
+ * encode_bch - calculate BCH ecc parity of data
+ * @bch:   BCH control structure
+ * @data:  data to encode
+ * @len:   data length in bytes
+ * @ecc:   ecc parity data, must be initialized by caller
+ *
+ * The @ecc parity array is used both as input and output parameter, in order to
+ * allow incremental computations. It should be of the size indicated by member
+ * @ecc_bytes of @bch, and should be initialized to 0 before the first call.
+ *
+ * The exact number of computed ecc parity bits is given by member @ecc_bits of
+ * @bch; it may be less than m*t for large values of t.
+ */
+void encode_bch(struct bch_control *bch, const uint8_t *data,
+               unsigned int len, uint8_t *ecc)
+{
+       const unsigned int l = BCH_ECC_WORDS(bch)-1;
+       unsigned int i, mlen;
+       unsigned long m;
+       uint32_t w, r[l+1];
+       const uint32_t * const tab0 = bch->mod8_tab;
+       const uint32_t * const tab1 = tab0 + 256*(l+1);
+       const uint32_t * const tab2 = tab1 + 256*(l+1);
+       const uint32_t * const tab3 = tab2 + 256*(l+1);
+       const uint32_t *pdata, *p0, *p1, *p2, *p3;
+
+       if (ecc) {
+               /* load ecc parity bytes into internal 32-bit buffer */
+               load_ecc8(bch, bch->ecc_buf, ecc);
+       } else {
+               memset(bch->ecc_buf, 0, sizeof(r));
+       }
+
+       /* process first unaligned data bytes */
+       m = ((unsigned long)data) & 3;
+       if (m) {
+               mlen = (len < (4-m)) ? len : 4-m;
+               encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
+               data += mlen;
+               len  -= mlen;
+       }
+
+       /* process 32-bit aligned data words */
+       pdata = (uint32_t *)data;
+       mlen  = len/4;
+       data += 4*mlen;
+       len  -= 4*mlen;
+       memcpy(r, bch->ecc_buf, sizeof(r));
+
+       /*
+        * split each 32-bit word into 4 polynomials of weight 8 as follows:
+        *
+        * 31 ...24  23 ...16  15 ... 8  7 ... 0
+        * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt
+        *                               tttttttt  mod g = r0 (precomputed)
+        *                     zzzzzzzz  00000000  mod g = r1 (precomputed)
+        *           yyyyyyyy  00000000  00000000  mod g = r2 (precomputed)
+        * xxxxxxxx  00000000  00000000  00000000  mod g = r3 (precomputed)
+        * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt  mod g = r0^r1^r2^r3
+        */
+       while (mlen--) {
+               /* input data is read in big-endian format */
+               w = r[0]^cpu_to_be32(*pdata++);
+               p0 = tab0 + (l+1)*((w >>  0) & 0xff);
+               p1 = tab1 + (l+1)*((w >>  8) & 0xff);
+               p2 = tab2 + (l+1)*((w >> 16) & 0xff);
+               p3 = tab3 + (l+1)*((w >> 24) & 0xff);
+
+               for (i = 0; i < l; i++)
+                       r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
+
+               r[l] = p0[l]^p1[l]^p2[l]^p3[l];
+       }
+       memcpy(bch->ecc_buf, r, sizeof(r));
+
+       /* process last unaligned bytes */
+       if (len)
+               encode_bch_unaligned(bch, data, len, bch->ecc_buf);
+
+       /* store ecc parity bytes into original parity buffer */
+       if (ecc)
+               store_ecc8(bch, ecc, bch->ecc_buf);
+}
+EXPORT_SYMBOL_GPL(encode_bch);
+
+static inline int modulo(struct bch_control *bch, unsigned int v)
+{
+       const unsigned int n = GF_N(bch);
+       while (v >= n) {
+               v -= n;
+               v = (v & n) + (v >> GF_M(bch));
+       }
+       return v;
+}
+
+/*
+ * shorter and faster modulo function, only works when v < 2N.
+ */
+static inline int mod_s(struct bch_control *bch, unsigned int v)
+{
+       const unsigned int n = GF_N(bch);
+       return (v < n) ? v : v-n;
+}
+
+static inline int deg(unsigned int poly)
+{
+       /* polynomial degree is the most-significant bit index */
+       return fls(poly)-1;
+}
+
+static inline int parity(unsigned int x)
+{
+       /*
+        * public domain code snippet, lifted from
+        * http://www-graphics.stanford.edu/~seander/bithacks.html
+        */
+       x ^= x >> 1;
+       x ^= x >> 2;
+       x = (x & 0x11111111U) * 0x11111111U;
+       return (x >> 28) & 1;
+}
+
+/* Galois field basic operations: multiply, divide, inverse, etc. */
+
+static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
+                                 unsigned int b)
+{
+       return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+                                              bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
+{
+       return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
+}
+
+static inline unsigned int gf_div(struct bch_control *bch, unsigned int a,
+                                 unsigned int b)
+{
+       return a ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+                                       GF_N(bch)-bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_inv(struct bch_control *bch, unsigned int a)
+{
+       return bch->a_pow_tab[GF_N(bch)-bch->a_log_tab[a]];
+}
+
+static inline unsigned int a_pow(struct bch_control *bch, int i)
+{
+       return bch->a_pow_tab[modulo(bch, i)];
+}
+
+static inline int a_log(struct bch_control *bch, unsigned int x)
+{
+       return bch->a_log_tab[x];
+}
+
+static inline int a_ilog(struct bch_control *bch, unsigned int x)
+{
+       return mod_s(bch, GF_N(bch)-bch->a_log_tab[x]);
+}
+
+/*
+ * compute 2t syndromes of ecc polynomial, i.e. ecc(a^j) for j=1..2t
+ */
+static void compute_syndromes(struct bch_control *bch, uint32_t *ecc,
+                             unsigned int *syn)
+{
+       int i, j, s;
+       unsigned int m;
+       uint32_t poly;
+       const int t = GF_T(bch);
+
+       s = bch->ecc_bits;
+
+       /* make sure extra bits in last ecc word are cleared */
+       m = ((unsigned int)s) & 31;
+       if (m)
+               ecc[s/32] &= ~((1u << (32-m))-1);
+       memset(syn, 0, 2*t*sizeof(*syn));
+
+       /* compute v(a^j) for j=1 .. 2t-1 */
+       do {
+               poly = *ecc++;
+               s -= 32;
+               while (poly) {
+                       i = deg(poly);
+                       for (j = 0; j < 2*t; j += 2)
+                               syn[j] ^= a_pow(bch, (j+1)*(i+s));
+
+                       poly ^= (1 << i);
+               }
+       } while (s > 0);
+
+       /* v(a^(2j)) = v(a^j)^2 */
+       for (j = 0; j < t; j++)
+               syn[2*j+1] = gf_sqr(bch, syn[j]);
+}
+
+static void gf_poly_copy(struct gf_poly *dst, struct gf_poly *src)
+{
+       memcpy(dst, src, GF_POLY_SZ(src->deg));
+}
+
+static int compute_error_locator_polynomial(struct bch_control *bch,
+                                           const unsigned int *syn)
+{
+       const unsigned int t = GF_T(bch);
+       const unsigned int n = GF_N(bch);
+       unsigned int i, j, tmp, l, pd = 1, d = syn[0];
+       struct gf_poly *elp = bch->elp;
+       struct gf_poly *pelp = bch->poly_2t[0];
+       struct gf_poly *elp_copy = bch->poly_2t[1];
+       int k, pp = -1;
+
+       memset(pelp, 0, GF_POLY_SZ(2*t));
+       memset(elp, 0, GF_POLY_SZ(2*t));
+
+       pelp->deg = 0;
+       pelp->c[0] = 1;
+       elp->deg = 0;
+       elp->c[0] = 1;
+
+       /* use simplified binary Berlekamp-Massey algorithm */
+       for (i = 0; (i < t) && (elp->deg <= t); i++) {
+               if (d) {
+                       k = 2*i-pp;
+                       gf_poly_copy(elp_copy, elp);
+                       /* e[i+1](X) = e[i](X)+di*dp^-1*X^2(i-p)*e[p](X) */
+                       tmp = a_log(bch, d)+n-a_log(bch, pd);
+                       for (j = 0; j <= pelp->deg; j++) {
+                               if (pelp->c[j]) {
+                                       l = a_log(bch, pelp->c[j]);
+                                       elp->c[j+k] ^= a_pow(bch, tmp+l);
+                               }
+                       }
+                       /* compute l[i+1] = max(l[i]->c[l[p]+2*(i-p]) */
+                       tmp = pelp->deg+k;
+                       if (tmp > elp->deg) {
+                               elp->deg = tmp;
+                               gf_poly_copy(pelp, elp_copy);
+                               pd = d;
+                               pp = 2*i;
+                       }
+               }
+               /* di+1 = S(2i+3)+elp[i+1].1*S(2i+2)+...+elp[i+1].lS(2i+3-l) */
+               if (i < t-1) {
+                       d = syn[2*i+2];
+                       for (j = 1; j <= elp->deg; j++)
+                               d ^= gf_mul(bch, elp->c[j], syn[2*i+2-j]);
+               }
+       }
+       dbg("elp=%s\n", gf_poly_str(elp));
+       return (elp->deg > t) ? -1 : (int)elp->deg;
+}
+
+/*
+ * solve a m x m linear system in GF(2) with an expected number of solutions,
+ * and return the number of found solutions
+ */
+static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
+                              unsigned int *sol, int nsol)
+{
+       const int m = GF_M(bch);
+       unsigned int tmp, mask;
+       int rem, c, r, p, k, param[m];
+
+       k = 0;
+       mask = 1 << m;
+
+       /* Gaussian elimination */
+       for (c = 0; c < m; c++) {
+               rem = 0;
+               p = c-k;
+               /* find suitable row for elimination */
+               for (r = p; r < m; r++) {
+                       if (rows[r] & mask) {
+                               if (r != p) {
+                                       tmp = rows[r];
+                                       rows[r] = rows[p];
+                                       rows[p] = tmp;
+                               }
+                               rem = r+1;
+                               break;
+                       }
+               }
+               if (rem) {
+                       /* perform elimination on remaining rows */
+                       tmp = rows[p];
+                       for (r = rem; r < m; r++) {
+                               if (rows[r] & mask)
+                                       rows[r] ^= tmp;
+                       }
+               } else {
+                       /* elimination not needed, store defective row index */
+                       param[k++] = c;
+               }
+               mask >>= 1;
+       }
+       /* rewrite system, inserting fake parameter rows */
+       if (k > 0) {
+               p = k;
+               for (r = m-1; r >= 0; r--) {
+                       if ((r > m-1-k) && rows[r])
+                               /* system has no solution */
+                               return 0;
+
+                       rows[r] = (p && (r == param[p-1])) ?
+                               p--, 1u << (m-r) : rows[r-p];
+               }
+       }
+
+       if (nsol != (1 << k))
+               /* unexpected number of solutions */
+               return 0;
+
+       for (p = 0; p < nsol; p++) {
+               /* set parameters for p-th solution */
+               for (c = 0; c < k; c++)
+                       rows[param[c]] = (rows[param[c]] & ~1)|((p >> c) & 1);
+
+               /* compute unique solution */
+               tmp = 0;
+               for (r = m-1; r >= 0; r--) {
+                       mask = rows[r] & (tmp|1);
+                       tmp |= parity(mask) << (m-r);
+               }
+               sol[p] = tmp >> 1;
+       }
+       return nsol;
+}
+
+/*
+ * this function builds and solves a linear system for finding roots of a degree
+ * 4 affine monic polynomial X^4+aX^2+bX+c over GF(2^m).
+ */
+static int find_affine4_roots(struct bch_control *bch, unsigned int a,
+                             unsigned int b, unsigned int c,
+                             unsigned int *roots)
+{
+       int i, j, k;
+       const int m = GF_M(bch);
+       unsigned int mask = 0xff, t, rows[16] = {0,};
+
+       j = a_log(bch, b);
+       k = a_log(bch, a);
+       rows[0] = c;
+
+       /* buid linear system to solve X^4+aX^2+bX+c = 0 */
+       for (i = 0; i < m; i++) {
+               rows[i+1] = bch->a_pow_tab[4*i]^
+                       (a ? bch->a_pow_tab[mod_s(bch, k)] : 0)^
+                       (b ? bch->a_pow_tab[mod_s(bch, j)] : 0);
+               j++;
+               k += 2;
+       }
+       /*
+        * transpose 16x16 matrix before passing it to linear solver
+        * warning: this code assumes m < 16
+        */
+       for (j = 8; j != 0; j >>= 1, mask ^= (mask << j)) {
+               for (k = 0; k < 16; k = (k+j+1) & ~j) {
+                       t = ((rows[k] >> j)^rows[k+j]) & mask;
+                       rows[k] ^= (t << j);
+                       rows[k+j] ^= t;
+               }
+       }
+       return solve_linear_system(bch, rows, roots, 4);
+}
+
+/*
+ * compute root r of a degree 1 polynomial over GF(2^m) (returned as log(1/r))
+ */
+static int find_poly_deg1_roots(struct bch_control *bch, struct gf_poly *poly,
+                               unsigned int *roots)
+{
+       int n = 0;
+
+       if (poly->c[0])
+               /* poly[X] = bX+c with c!=0, root=c/b */
+               roots[n++] = mod_s(bch, GF_N(bch)-bch->a_log_tab[poly->c[0]]+
+                                  bch->a_log_tab[poly->c[1]]);
+       return n;
+}
+
+/*
+ * compute roots of a degree 2 polynomial over GF(2^m)
+ */
+static int find_poly_deg2_roots(struct bch_control *bch, struct gf_poly *poly,
+                               unsigned int *roots)
+{
+       int n = 0, i, l0, l1, l2;
+       unsigned int u, v, r;
+
+       if (poly->c[0] && poly->c[1]) {
+
+               l0 = bch->a_log_tab[poly->c[0]];
+               l1 = bch->a_log_tab[poly->c[1]];
+               l2 = bch->a_log_tab[poly->c[2]];
+
+               /* using z=a/bX, transform aX^2+bX+c into z^2+z+u (u=ac/b^2) */
+               u = a_pow(bch, l0+l2+2*(GF_N(bch)-l1));
+               /*
+                * let u = sum(li.a^i) i=0..m-1; then compute r = sum(li.xi):
+                * r^2+r = sum(li.(xi^2+xi)) = sum(li.(a^i+Tr(a^i).a^k)) =
+                * u + sum(li.Tr(a^i).a^k) = u+a^k.Tr(sum(li.a^i)) = u+a^k.Tr(u)
+                * i.e. r and r+1 are roots iff Tr(u)=0
+                */
+               r = 0;
+               v = u;
+               while (v) {
+                       i = deg(v);
+                       r ^= bch->xi_tab[i];
+                       v ^= (1 << i);
+               }
+               /* verify root */
+               if ((gf_sqr(bch, r)^r) == u) {
+                       /* reverse z=a/bX transformation and compute log(1/r) */
+                       roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+                                           bch->a_log_tab[r]+l2);
+                       roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+                                           bch->a_log_tab[r^1]+l2);
+               }
+       }
+       return n;
+}
+
+/*
+ * compute roots of a degree 3 polynomial over GF(2^m)
+ */
+static int find_poly_deg3_roots(struct bch_control *bch, struct gf_poly *poly,
+                               unsigned int *roots)
+{
+       int i, n = 0;
+       unsigned int a, b, c, a2, b2, c2, e3, tmp[4];
+
+       if (poly->c[0]) {
+               /* transform polynomial into monic X^3 + a2X^2 + b2X + c2 */
+               e3 = poly->c[3];
+               c2 = gf_div(bch, poly->c[0], e3);
+               b2 = gf_div(bch, poly->c[1], e3);
+               a2 = gf_div(bch, poly->c[2], e3);
+
+               /* (X+a2)(X^3+a2X^2+b2X+c2) = X^4+aX^2+bX+c (affine) */
+               c = gf_mul(bch, a2, c2);           /* c = a2c2      */
+               b = gf_mul(bch, a2, b2)^c2;        /* b = a2b2 + c2 */
+               a = gf_sqr(bch, a2)^b2;            /* a = a2^2 + b2 */
+
+               /* find the 4 roots of this affine polynomial */
+               if (find_affine4_roots(bch, a, b, c, tmp) == 4) {
+                       /* remove a2 from final list of roots */
+                       for (i = 0; i < 4; i++) {
+                               if (tmp[i] != a2)
+                                       roots[n++] = a_ilog(bch, tmp[i]);
+                       }
+               }
+       }
+       return n;
+}
+
+/*
+ * compute roots of a degree 4 polynomial over GF(2^m)
+ */
+static int find_poly_deg4_roots(struct bch_control *bch, struct gf_poly *poly,
+                               unsigned int *roots)
+{
+       int i, l, n = 0;
+       unsigned int a, b, c, d, e = 0, f, a2, b2, c2, e4;
+
+       if (poly->c[0] == 0)
+               return 0;
+
+       /* transform polynomial into monic X^4 + aX^3 + bX^2 + cX + d */
+       e4 = poly->c[4];
+       d = gf_div(bch, poly->c[0], e4);
+       c = gf_div(bch, poly->c[1], e4);
+       b = gf_div(bch, poly->c[2], e4);
+       a = gf_div(bch, poly->c[3], e4);
+
+       /* use Y=1/X transformation to get an affine polynomial */
+       if (a) {
+               /* first, eliminate cX by using z=X+e with ae^2+c=0 */
+               if (c) {
+                       /* compute e such that e^2 = c/a */
+                       f = gf_div(bch, c, a);
+                       l = a_log(bch, f);
+                       l += (l & 1) ? GF_N(bch) : 0;
+                       e = a_pow(bch, l/2);
+                       /*
+                        * use transformation z=X+e:
+                        * z^4+e^4 + a(z^3+ez^2+e^2z+e^3) + b(z^2+e^2) +cz+ce+d
+                        * z^4 + az^3 + (ae+b)z^2 + (ae^2+c)z+e^4+be^2+ae^3+ce+d
+                        * z^4 + az^3 + (ae+b)z^2 + e^4+be^2+d
+                        * z^4 + az^3 +     b'z^2 + d'
+                        */
+                       d = a_pow(bch, 2*l)^gf_mul(bch, b, f)^d;
+                       b = gf_mul(bch, a, e)^b;
+               }
+               /* now, use Y=1/X to get Y^4 + b/dY^2 + a/dY + 1/d */
+               if (d == 0)
+                       /* assume all roots have multiplicity 1 */
+                       return 0;
+
+               c2 = gf_inv(bch, d);
+               b2 = gf_div(bch, a, d);
+               a2 = gf_div(bch, b, d);
+       } else {
+               /* polynomial is already affine */
+               c2 = d;
+               b2 = c;
+               a2 = b;
+       }
+       /* find the 4 roots of this affine polynomial */
+       if (find_affine4_roots(bch, a2, b2, c2, roots) == 4) {
+               for (i = 0; i < 4; i++) {
+                       /* post-process roots (reverse transformations) */
+                       f = a ? gf_inv(bch, roots[i]) : roots[i];
+                       roots[i] = a_ilog(bch, f^e);
+               }
+               n = 4;
+       }
+       return n;
+}
+
+/*
+ * build monic, log-based representation of a polynomial
+ */
+static void gf_poly_logrep(struct bch_control *bch,
+                          const struct gf_poly *a, int *rep)
+{
+       int i, d = a->deg, l = GF_N(bch)-a_log(bch, a->c[a->deg]);
+
+       /* represent 0 values with -1; warning, rep[d] is not set to 1 */
+       for (i = 0; i < d; i++)
+               rep[i] = a->c[i] ? mod_s(bch, a_log(bch, a->c[i])+l) : -1;
+}
+
+/*
+ * compute polynomial Euclidean division remainder in GF(2^m)[X]
+ */
+static void gf_poly_mod(struct bch_control *bch, struct gf_poly *a,
+                       const struct gf_poly *b, int *rep)
+{
+       int la, p, m;
+       unsigned int i, j, *c = a->c;
+       const unsigned int d = b->deg;
+
+       if (a->deg < d)
+               return;
+
+       /* reuse or compute log representation of denominator */
+       if (!rep) {
+               rep = bch->cache;
+               gf_poly_logrep(bch, b, rep);
+       }
+
+       for (j = a->deg; j >= d; j--) {
+               if (c[j]) {
+                       la = a_log(bch, c[j]);
+                       p = j-d;
+                       for (i = 0; i < d; i++, p++) {
+                               m = rep[i];
+                               if (m >= 0)
+                                       c[p] ^= bch->a_pow_tab[mod_s(bch,
+                                                                    m+la)];
+                       }
+               }
+       }
+       a->deg = d-1;
+       while (!c[a->deg] && a->deg)
+               a->deg--;
+}
+
+/*
+ * compute polynomial Euclidean division quotient in GF(2^m)[X]
+ */
+static void gf_poly_div(struct bch_control *bch, struct gf_poly *a,
+                       const struct gf_poly *b, struct gf_poly *q)
+{
+       if (a->deg >= b->deg) {
+               q->deg = a->deg-b->deg;
+               /* compute a mod b (modifies a) */
+               gf_poly_mod(bch, a, b, NULL);
+               /* quotient is stored in upper part of polynomial a */
+               memcpy(q->c, &a->c[b->deg], (1+q->deg)*sizeof(unsigned int));
+       } else {
+               q->deg = 0;
+               q->c[0] = 0;
+       }
+}
+
+/*
+ * compute polynomial GCD (Greatest Common Divisor) in GF(2^m)[X]
+ */
+static struct gf_poly *gf_poly_gcd(struct bch_control *bch, struct gf_poly *a,
+                                  struct gf_poly *b)
+{
+       struct gf_poly *tmp;
+
+       dbg("gcd(%s,%s)=", gf_poly_str(a), gf_poly_str(b));
+
+       if (a->deg < b->deg) {
+               tmp = b;
+               b = a;
+               a = tmp;
+       }
+
+       while (b->deg > 0) {
+               gf_poly_mod(bch, a, b, NULL);
+               tmp = b;
+               b = a;
+               a = tmp;
+       }
+
+       dbg("%s\n", gf_poly_str(a));
+
+       return a;
+}
+
+/*
+ * Given a polynomial f and an integer k, compute Tr(a^kX) mod f
+ * This is used in Berlekamp Trace algorithm for splitting polynomials
+ */
+static void compute_trace_bk_mod(struct bch_control *bch, int k,
+                                const struct gf_poly *f, struct gf_poly *z,
+                                struct gf_poly *out)
+{
+       const int m = GF_M(bch);
+       int i, j;
+
+       /* z contains z^2j mod f */
+       z->deg = 1;
+       z->c[0] = 0;
+       z->c[1] = bch->a_pow_tab[k];
+
+       out->deg = 0;
+       memset(out, 0, GF_POLY_SZ(f->deg));
+
+       /* compute f log representation only once */
+       gf_poly_logrep(bch, f, bch->cache);
+
+       for (i = 0; i < m; i++) {
+               /* add a^(k*2^i)(z^(2^i) mod f) and compute (z^(2^i) mod f)^2 */
+               for (j = z->deg; j >= 0; j--) {
+                       out->c[j] ^= z->c[j];
+                       z->c[2*j] = gf_sqr(bch, z->c[j]);
+                       z->c[2*j+1] = 0;
+               }
+               if (z->deg > out->deg)
+                       out->deg = z->deg;
+
+               if (i < m-1) {
+                       z->deg *= 2;
+                       /* z^(2(i+1)) mod f = (z^(2^i) mod f)^2 mod f */
+                       gf_poly_mod(bch, z, f, bch->cache);
+               }
+       }
+       while (!out->c[out->deg] && out->deg)
+               out->deg--;
+
+       dbg("Tr(a^%d.X) mod f = %s\n", k, gf_poly_str(out));
+}
+
+/*
+ * factor a polynomial using Berlekamp Trace algorithm (BTA)
+ */
+static void factor_polynomial(struct bch_control *bch, int k, struct gf_poly *f,
+                             struct gf_poly **g, struct gf_poly **h)
+{
+       struct gf_poly *f2 = bch->poly_2t[0];
+       struct gf_poly *q  = bch->poly_2t[1];
+       struct gf_poly *tk = bch->poly_2t[2];
+       struct gf_poly *z  = bch->poly_2t[3];
+       struct gf_poly *gcd;
+
+       dbg("factoring %s...\n", gf_poly_str(f));
+
+       *g = f;
+       *h = NULL;
+
+       /* tk = Tr(a^k.X) mod f */
+       compute_trace_bk_mod(bch, k, f, z, tk);
+
+       if (tk->deg > 0) {
+               /* compute g = gcd(f, tk) (destructive operation) */
+               gf_poly_copy(f2, f);
+               gcd = gf_poly_gcd(bch, f2, tk);
+               if (gcd->deg < f->deg) {
+                       /* compute h=f/gcd(f,tk); this will modify f and q */
+                       gf_poly_div(bch, f, gcd, q);
+                       /* store g and h in-place (clobbering f) */
+                       *h = &((struct gf_poly_deg1 *)f)[gcd->deg].poly;
+                       gf_poly_copy(*g, gcd);
+                       gf_poly_copy(*h, q);
+               }
+       }
+}
+
+/*
+ * find roots of a polynomial, using BTZ algorithm; see the beginning of this
+ * file for details
+ */
+static int find_poly_roots(struct bch_control *bch, unsigned int k,
+                          struct gf_poly *poly, unsigned int *roots)
+{
+       int cnt;
+       struct gf_poly *f1, *f2;
+
+       switch (poly->deg) {
+               /* handle low degree polynomials with ad hoc techniques */
+       case 1:
+               cnt = find_poly_deg1_roots(bch, poly, roots);
+               break;
+       case 2:
+               cnt = find_poly_deg2_roots(bch, poly, roots);
+               break;
+       case 3:
+               cnt = find_poly_deg3_roots(bch, poly, roots);
+               break;
+       case 4:
+               cnt = find_poly_deg4_roots(bch, poly, roots);
+               break;
+       default:
+               /* factor polynomial using Berlekamp Trace Algorithm (BTA) */
+               cnt = 0;
+               if (poly->deg && (k <= GF_M(bch))) {
+                       factor_polynomial(bch, k, poly, &f1, &f2);
+                       if (f1)
+                               cnt += find_poly_roots(bch, k+1, f1, roots);
+                       if (f2)
+                               cnt += find_poly_roots(bch, k+1, f2, roots+cnt);
+               }
+               break;
+       }
+       return cnt;
+}
+
+#if defined(USE_CHIEN_SEARCH)
+/*
+ * exhaustive root search (Chien) implementation - not used, included only for
+ * reference/comparison tests
+ */
+static int chien_search(struct bch_control *bch, unsigned int len,
+                       struct gf_poly *p, unsigned int *roots)
+{
+       int m;
+       unsigned int i, j, syn, syn0, count = 0;
+       const unsigned int k = 8*len+bch->ecc_bits;
+
+       /* use a log-based representation of polynomial */
+       gf_poly_logrep(bch, p, bch->cache);
+       bch->cache[p->deg] = 0;
+       syn0 = gf_div(bch, p->c[0], p->c[p->deg]);
+
+       for (i = GF_N(bch)-k+1; i <= GF_N(bch); i++) {
+               /* compute elp(a^i) */
+               for (j = 1, syn = syn0; j <= p->deg; j++) {
+                       m = bch->cache[j];
+                       if (m >= 0)
+                               syn ^= a_pow(bch, m+j*i);
+               }
+               if (syn == 0) {
+                       roots[count++] = GF_N(bch)-i;
+                       if (count == p->deg)
+                               break;
+               }
+       }
+       return (count == p->deg) ? count : 0;
+}
+#define find_poly_roots(_p, _k, _elp, _loc) chien_search(_p, len, _elp, _loc)
+#endif /* USE_CHIEN_SEARCH */
+
+/**
+ * decode_bch - decode received codeword and find bit error locations
+ * @bch:      BCH control structure
+ * @data:     received data, ignored if @calc_ecc is provided
+ * @len:      data length in bytes, must always be provided
+ * @recv_ecc: received ecc, if NULL then assume it was XORed in @calc_ecc
+ * @calc_ecc: calculated ecc, if NULL then calc_ecc is computed from @data
+ * @syn:      hw computed syndrome data (if NULL, syndrome is calculated)
+ * @errloc:   output array of error locations
+ *
+ * Returns:
+ *  The number of errors found, or -EBADMSG if decoding failed, or -EINVAL if
+ *  invalid parameters were provided
+ *
+ * Depending on the available hw BCH support and the need to compute @calc_ecc
+ * separately (using encode_bch()), this function should be called with one of
+ * the following parameter configurations -
+ *
+ * by providing @data and @recv_ecc only:
+ *   decode_bch(@bch, @data, @len, @recv_ecc, NULL, NULL, @errloc)
+ *
+ * by providing @recv_ecc and @calc_ecc:
+ *   decode_bch(@bch, NULL, @len, @recv_ecc, @calc_ecc, NULL, @errloc)
+ *
+ * by providing ecc = recv_ecc XOR calc_ecc:
+ *   decode_bch(@bch, NULL, @len, NULL, ecc, NULL, @errloc)
+ *
+ * by providing syndrome results @syn:
+ *   decode_bch(@bch, NULL, @len, NULL, NULL, @syn, @errloc)
+ *
+ * Once decode_bch() has successfully returned with a positive value, error
+ * locations returned in array @errloc should be interpreted as follows -
+ *
+ * if (errloc[n] >= 8*len), then n-th error is located in ecc (no need for
+ * data correction)
+ *
+ * if (errloc[n] < 8*len), then n-th error is located in data and can be
+ * corrected with statement data[errloc[n]/8] ^= 1 << (errloc[n] % 8);
+ *
+ * Note that this function does not perform any data correction by itself, it
+ * merely indicates error locations.
+ */
+int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
+              const uint8_t *recv_ecc, const uint8_t *calc_ecc,
+              const unsigned int *syn, unsigned int *errloc)
+{
+       const unsigned int ecc_words = BCH_ECC_WORDS(bch);
+       unsigned int nbits;
+       int i, err, nroots;
+       uint32_t sum;
+
+       /* sanity check: make sure data length can be handled */
+       if (8*len > (bch->n-bch->ecc_bits))
+               return -EINVAL;
+
+       /* if caller does not provide syndromes, compute them */
+       if (!syn) {
+               if (!calc_ecc) {
+                       /* compute received data ecc into an internal buffer */
+                       if (!data || !recv_ecc)
+                               return -EINVAL;
+                       encode_bch(bch, data, len, NULL);
+               } else {
+                       /* load provided calculated ecc */
+                       load_ecc8(bch, bch->ecc_buf, calc_ecc);
+               }
+               /* load received ecc or assume it was XORed in calc_ecc */
+               if (recv_ecc) {
+                       load_ecc8(bch, bch->ecc_buf2, recv_ecc);
+                       /* XOR received and calculated ecc */
+                       for (i = 0, sum = 0; i < (int)ecc_words; i++) {
+                               bch->ecc_buf[i] ^= bch->ecc_buf2[i];
+                               sum |= bch->ecc_buf[i];
+                       }
+                       if (!sum)
+                               /* no error found */
+                               return 0;
+               }
+               compute_syndromes(bch, bch->ecc_buf, bch->syn);
+               syn = bch->syn;
+       }
+
+       err = compute_error_locator_polynomial(bch, syn);
+       if (err > 0) {
+               nroots = find_poly_roots(bch, 1, bch->elp, errloc);
+               if (err != nroots)
+                       err = -1;
+       }
+       if (err > 0) {
+               /* post-process raw error locations for easier correction */
+               nbits = (len*8)+bch->ecc_bits;
+               for (i = 0; i < err; i++) {
+                       if (errloc[i] >= nbits) {
+                               err = -1;
+                               break;
+                       }
+                       errloc[i] = nbits-1-errloc[i];
+                       errloc[i] = (errloc[i] & ~7)|(7-(errloc[i] & 7));
+               }
+       }
+       return (err >= 0) ? err : -EBADMSG;
+}
+EXPORT_SYMBOL_GPL(decode_bch);
+
+/*
+ * generate Galois field lookup tables
+ */
+static int build_gf_tables(struct bch_control *bch, unsigned int poly)
+{
+       unsigned int i, x = 1;
+       const unsigned int k = 1 << deg(poly);
+
+       /* primitive polynomial must be of degree m */
+       if (k != (1u << GF_M(bch)))
+               return -1;
+
+       for (i = 0; i < GF_N(bch); i++) {
+               bch->a_pow_tab[i] = x;
+               bch->a_log_tab[x] = i;
+               if (i && (x == 1))
+                       /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+                       return -1;
+               x <<= 1;
+               if (x & k)
+                       x ^= poly;
+       }
+       bch->a_pow_tab[GF_N(bch)] = 1;
+       bch->a_log_tab[0] = 0;
+
+       return 0;
+}
+
+/*
+ * compute generator polynomial remainder tables for fast encoding
+ */
+static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
+{
+       int i, j, b, d;
+       uint32_t data, hi, lo, *tab;
+       const int l = BCH_ECC_WORDS(bch);
+       const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
+       const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
+
+       memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
+
+       for (i = 0; i < 256; i++) {
+               /* p(X)=i is a small polynomial of weight <= 8 */
+               for (b = 0; b < 4; b++) {
+                       /* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */
+                       tab = bch->mod8_tab + (b*256+i)*l;
+                       data = i << (8*b);
+                       while (data) {
+                               d = deg(data);
+                               /* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */
+                               data ^= g[0] >> (31-d);
+                               for (j = 0; j < ecclen; j++) {
+                                       hi = (d < 31) ? g[j] << (d+1) : 0;
+                                       lo = (j+1 < plen) ?
+                                               g[j+1] >> (31-d) : 0;
+                                       tab[j] ^= hi|lo;
+                               }
+                       }
+               }
+       }
+}
+
+/*
+ * build a base for factoring degree 2 polynomials
+ */
+static int build_deg2_base(struct bch_control *bch)
+{
+       const int m = GF_M(bch);
+       int i, j, r;
+       unsigned int sum, x, y, remaining, ak = 0, xi[m];
+
+       /* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
+       for (i = 0; i < m; i++) {
+               for (j = 0, sum = 0; j < m; j++)
+                       sum ^= a_pow(bch, i*(1 << j));
+
+               if (sum) {
+                       ak = bch->a_pow_tab[i];
+                       break;
+               }
+       }
+       /* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */
+       remaining = m;
+       memset(xi, 0, sizeof(xi));
+
+       for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
+               y = gf_sqr(bch, x)^x;
+               for (i = 0; i < 2; i++) {
+                       r = a_log(bch, y);
+                       if (y && (r < m) && !xi[r]) {
+                               bch->xi_tab[r] = x;
+                               xi[r] = 1;
+                               remaining--;
+                               dbg("x%d = %x\n", r, x);
+                               break;
+                       }
+                       y ^= ak;
+               }
+       }
+       /* should not happen but check anyway */
+       return remaining ? -1 : 0;
+}
+
+static void *bch_alloc(size_t size, int *err)
+{
+       void *ptr;
+
+       ptr = kmalloc(size, GFP_KERNEL);
+       if (ptr == NULL)
+               *err = 1;
+       return ptr;
+}
+
+/*
+ * compute generator polynomial for given (m,t) parameters.
+ */
+static uint32_t *compute_generator_polynomial(struct bch_control *bch)
+{
+       const unsigned int m = GF_M(bch);
+       const unsigned int t = GF_T(bch);
+       int n, err = 0;
+       unsigned int i, j, nbits, r, word, *roots;
+       struct gf_poly *g;
+       uint32_t *genpoly;
+
+       g = bch_alloc(GF_POLY_SZ(m*t), &err);
+       roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
+       genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
+
+       if (err) {
+               kfree(genpoly);
+               genpoly = NULL;
+               goto finish;
+       }
+
+       /* enumerate all roots of g(X) */
+       memset(roots , 0, (bch->n+1)*sizeof(*roots));
+       for (i = 0; i < t; i++) {
+               for (j = 0, r = 2*i+1; j < m; j++) {
+                       roots[r] = 1;
+                       r = mod_s(bch, 2*r);
+               }
+       }
+       /* build generator polynomial g(X) */
+       g->deg = 0;
+       g->c[0] = 1;
+       for (i = 0; i < GF_N(bch); i++) {
+               if (roots[i]) {
+                       /* multiply g(X) by (X+root) */
+                       r = bch->a_pow_tab[i];
+                       g->c[g->deg+1] = 1;
+                       for (j = g->deg; j > 0; j--)
+                               g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
+
+                       g->c[0] = gf_mul(bch, g->c[0], r);
+                       g->deg++;
+               }
+       }
+       /* store left-justified binary representation of g(X) */
+       n = g->deg+1;
+       i = 0;
+
+       while (n > 0) {
+               nbits = (n > 32) ? 32 : n;
+               for (j = 0, word = 0; j < nbits; j++) {
+                       if (g->c[n-1-j])
+                               word |= 1u << (31-j);
+               }
+               genpoly[i++] = word;
+               n -= nbits;
+       }
+       bch->ecc_bits = g->deg;
+
+finish:
+       kfree(g);
+       kfree(roots);
+
+       return genpoly;
+}
+
+/**
+ * init_bch - initialize a BCH encoder/decoder
+ * @m:          Galois field order, should be in the range 5-15
+ * @t:          maximum error correction capability, in bits
+ * @prim_poly:  user-provided primitive polynomial (or 0 to use default)
+ *
+ * Returns:
+ *  a newly allocated BCH control structure if successful, NULL otherwise
+ *
+ * This initialization can take some time, as lookup tables are built for fast
+ * encoding/decoding; make sure not to call this function from a time critical
+ * path. Usually, init_bch() should be called on module/driver init and
+ * free_bch() should be called to release memory on exit.
+ *
+ * You may provide your own primitive polynomial of degree @m in argument
+ * @prim_poly, or let init_bch() use its default polynomial.
+ *
+ * Once init_bch() has successfully returned a pointer to a newly allocated
+ * BCH control structure, ecc length in bytes is given by member @ecc_bytes of
+ * the structure.
+ */
+struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
+{
+       int err = 0;
+       unsigned int i, words;
+       uint32_t *genpoly;
+       struct bch_control *bch = NULL;
+
+       const int min_m = 5;
+       const int max_m = 15;
+
+       /* default primitive polynomials */
+       static const unsigned int prim_poly_tab[] = {
+               0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
+               0x402b, 0x8003,
+       };
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+       if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
+               printk(KERN_ERR "bch encoder/decoder was configured to support "
+                      "parameters m=%d, t=%d only!\n",
+                      CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
+               goto fail;
+       }
+#endif
+       if ((m < min_m) || (m > max_m))
+               /*
+                * values of m greater than 15 are not currently supported;
+                * supporting m > 15 would require changing table base type
+                * (uint16_t) and a small patch in matrix transposition
+                */
+               goto fail;
+
+       /* sanity checks */
+       if ((t < 1) || (m*t >= ((1 << m)-1)))
+               /* invalid t value */
+               goto fail;
+
+       /* select a primitive polynomial for generating GF(2^m) */
+       if (prim_poly == 0)
+               prim_poly = prim_poly_tab[m-min_m];
+
+       bch = kzalloc(sizeof(*bch), GFP_KERNEL);
+       if (bch == NULL)
+               goto fail;
+
+       bch->m = m;
+       bch->t = t;
+       bch->n = (1 << m)-1;
+       words  = DIV_ROUND_UP(m*t, 32);
+       bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
+       bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
+       bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
+       bch->mod8_tab  = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
+       bch->ecc_buf   = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
+       bch->ecc_buf2  = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
+       bch->xi_tab    = bch_alloc(m*sizeof(*bch->xi_tab), &err);
+       bch->syn       = bch_alloc(2*t*sizeof(*bch->syn), &err);
+       bch->cache     = bch_alloc(2*t*sizeof(*bch->cache), &err);
+       bch->elp       = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
+
+       for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+               bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
+
+       if (err)
+               goto fail;
+
+       err = build_gf_tables(bch, prim_poly);
+       if (err)
+               goto fail;
+
+       /* use generator polynomial for computing encoding tables */
+       genpoly = compute_generator_polynomial(bch);
+       if (genpoly == NULL)
+               goto fail;
+
+       build_mod8_tables(bch, genpoly);
+       kfree(genpoly);
+
+       err = build_deg2_base(bch);
+       if (err)
+               goto fail;
+
+       return bch;
+
+fail:
+       free_bch(bch);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(init_bch);
+
+/**
+ *  free_bch - free the BCH control structure
+ *  @bch:    BCH control structure to release
+ */
+void free_bch(struct bch_control *bch)
+{
+       unsigned int i;
+
+       if (bch) {
+               kfree(bch->a_pow_tab);
+               kfree(bch->a_log_tab);
+               kfree(bch->mod8_tab);
+               kfree(bch->ecc_buf);
+               kfree(bch->ecc_buf2);
+               kfree(bch->xi_tab);
+               kfree(bch->syn);
+               kfree(bch->cache);
+               kfree(bch->elp);
+
+               for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+                       kfree(bch->poly_2t[i]);
+
+               kfree(bch);
+       }
+}
+EXPORT_SYMBOL_GPL(free_bch);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
+MODULE_DESCRIPTION("Binary BCH encoder/decoder");
index 51a5c23704afa29663863d308d682f0eb56c3a73..9da8cab1b1b0abceae9569a794447f3ddb0c1134 100644 (file)
@@ -3715,7 +3715,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
 }
 
 /**
- * @access_remote_vm - access another process' address space
+ * access_remote_vm - access another process' address space
  * @mm:                the mm_struct of the target address space
  * @addr:      start address to access
  * @buf:       source or destination buffer
index cb86e7d5e7f5591c8508fba1f98a150e1e968e50..c4c542c736a962774f0770eef0d50c419b19a2cb 100644 (file)
@@ -1971,21 +1971,10 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 }
 EXPORT_SYMBOL(filemap_fault);
 
-/*
- * Access another process' address space.
- * - source/target buffer must be kernel space
- */
-int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+               unsigned long addr, void *buf, int len, int write)
 {
        struct vm_area_struct *vma;
-       struct mm_struct *mm;
-
-       if (addr + len < addr)
-               return 0;
-
-       mm = get_task_mm(tsk);
-       if (!mm)
-               return 0;
 
        down_read(&mm->mmap_sem);
 
@@ -2010,6 +1999,43 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
        }
 
        up_read(&mm->mmap_sem);
+
+       return len;
+}
+
+/**
+ * @access_remote_vm - access another process' address space
+ * @mm:                the mm_struct of the target address space
+ * @addr:      start address to access
+ * @buf:       source or destination buffer
+ * @len:       number of bytes to transfer
+ * @write:     whether the access is a write
+ *
+ * The caller must hold a reference on @mm.
+ */
+int access_remote_vm(struct mm_struct *mm, unsigned long addr,
+               void *buf, int len, int write)
+{
+       return __access_remote_vm(NULL, mm, addr, buf, len, write);
+}
+
+/*
+ * Access another process' address space.
+ * - source/target buffer must be kernel space
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct mm_struct *mm;
+
+       if (addr + len < addr)
+               return 0;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       len = __access_remote_vm(tsk, mm, addr, buf, len, write);
+
        mmput(mm);
        return len;
 }
index 3f930018aa60dc075bc49f7283c57b2b3b6f0035..55d4d113fbd37fe4edb7531dc61102fc8f7c1bcc 100644 (file)
@@ -1008,8 +1008,7 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr)
        }
 
        if (in_first_chunk) {
-               if ((unsigned long)addr < VMALLOC_START ||
-                   (unsigned long)addr >= VMALLOC_END)
+               if (!is_vmalloc_addr(addr))
                        return __pa(addr);
                else
                        return page_to_phys(vmalloc_to_page(addr));
index dce8f0009a12dc75d3e51327216186c430b3c27d..718b60366dfe59303e11699c42903462dd21abf5 100644 (file)
@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 {
        struct net_bridge_port *p;
        int err = 0;
+       bool changed_addr;
 
        /* Don't allow bridging non-ethernet like devices */
        if ((dev->flags & IFF_LOOPBACK) ||
@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
        list_add_rcu(&p->list, &br->port_list);
 
        spin_lock_bh(&br->lock);
-       br_stp_recalculate_bridge_id(br);
+       changed_addr = br_stp_recalculate_bridge_id(br);
        br_features_recompute(br);
 
        if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
@@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        br_ifinfo_notify(RTM_NEWLINK, p);
 
+       if (changed_addr)
+               call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+
        dev_set_mtu(br->dev, br_min_mtu(br));
 
        kobject_uevent(&p->kobj, KOBJ_ADD);
index 19e2f46ed0860442c0851acef7ae1cad8655e0a8..387013d337456a8112c7cfa89ce971eb000a5605 100644 (file)
@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
 extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val);
 extern void br_stp_enable_port(struct net_bridge_port *p);
 extern void br_stp_disable_port(struct net_bridge_port *p);
-extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
+extern bool br_stp_recalculate_bridge_id(struct net_bridge *br);
 extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
 extern void br_stp_set_bridge_priority(struct net_bridge *br,
                                       u16 newprio);
index 79372d4a40551f92b2841b2c8008dcf29c89b38a..5593f5aec942eba5a8ef4767b976140d2fa28a51 100644 (file)
@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
 static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1];
 
 /* called under bridge lock */
-void br_stp_recalculate_bridge_id(struct net_bridge *br)
+bool br_stp_recalculate_bridge_id(struct net_bridge *br)
 {
        const unsigned char *br_mac_zero =
                        (const unsigned char *)br_mac_zero_aligned;
@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
 
        }
 
-       if (compare_ether_addr(br->bridge_id.addr, addr))
-               br_stp_change_bridge_id(br, addr);
+       if (compare_ether_addr(br->bridge_id.addr, addr) == 0)
+               return false;   /* no change */
+
+       br_stp_change_bridge_id(br, addr);
+       return true;
 }
 
 /* called under bridge lock */
index 702be5a2c956fd3e14ed8b7caadf3a3a9a07fbf1..733d66f1b05a566a670a1c74d3831cece4eb69a7 100644 (file)
@@ -95,7 +95,7 @@ struct s_pstats   can_pstats;      /* receive list statistics */
  * af_can socket functions
  */
 
-static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct sock *sk = sock->sk;
 
@@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                return -ENOIOCTLCMD;
        }
 }
+EXPORT_SYMBOL(can_ioctl);
 
 static void can_sock_destruct(struct sock *sk)
 {
@@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp)
                printk(KERN_ERR "can: protocol %d already registered\n",
                       proto);
                err = -EBUSY;
-       } else {
+       } else
                proto_tab[proto] = cp;
 
-               /* use generic ioctl function if not defined by module */
-               if (!cp->ops->ioctl)
-                       cp->ops->ioctl = can_ioctl;
-       }
        spin_unlock(&proto_tab_lock);
 
        if (err < 0)
index 092dc88a7c64c63856f91a32d4c5511471476eaa..871a0ad510257e6a6d45409edfe6e6bdcbf7ddc5 100644 (file)
@@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock,
        return size;
 }
 
-static struct proto_ops bcm_ops __read_mostly = {
+static const struct proto_ops bcm_ops = {
        .family        = PF_CAN,
        .release       = bcm_release,
        .bind          = sock_no_bind,
@@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = {
        .accept        = sock_no_accept,
        .getname       = sock_no_getname,
        .poll          = datagram_poll,
-       .ioctl         = NULL,          /* use can_ioctl() from af_can.c */
+       .ioctl         = can_ioctl,     /* use can_ioctl() from af_can.c */
        .listen        = sock_no_listen,
        .shutdown      = sock_no_shutdown,
        .setsockopt    = sock_no_setsockopt,
index 883e9d74fddf6439b483f822b327371b78bb9670..649acfa7c70a98ceb5fd3f131544f02e3cf838c8 100644 (file)
@@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
        return size;
 }
 
-static struct proto_ops raw_ops __read_mostly = {
+static const struct proto_ops raw_ops = {
        .family        = PF_CAN,
        .release       = raw_release,
        .bind          = raw_bind,
@@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = {
        .accept        = sock_no_accept,
        .getname       = raw_getname,
        .poll          = datagram_poll,
-       .ioctl         = NULL,          /* use can_ioctl() from af_can.c */
+       .ioctl         = can_ioctl,     /* use can_ioctl() from af_can.c */
        .listen        = sock_no_listen,
        .shutdown      = sock_no_shutdown,
        .setsockopt    = raw_setsockopt,
index f453370131a0df665ae8361661a9cb1d6a849cce..563ddc28139d8ab4b3b3b264bfd892b34b9f40e6 100644 (file)
@@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev)
 
        ASSERT_RTNL();
 
-       /*
-        *      Is it even present?
-        */
        if (!netif_device_present(dev))
                return -ENODEV;
 
@@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev)
        if (ret)
                return ret;
 
-       /*
-        *      Call device private open method
-        */
        set_bit(__LINK_STATE_START, &dev->state);
 
        if (ops->ndo_validate_addr)
@@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev)
        if (!ret && ops->ndo_open)
                ret = ops->ndo_open(dev);
 
-       /*
-        *      If it went open OK then:
-        */
-
        if (ret)
                clear_bit(__LINK_STATE_START, &dev->state);
        else {
-               /*
-                *      Set the flags.
-                */
                dev->flags |= IFF_UP;
-
-               /*
-                *      Enable NET_DMA
-                */
                net_dmaengine_get();
-
-               /*
-                *      Initialize multicasting status
-                */
                dev_set_rx_mode(dev);
-
-               /*
-                *      Wakeup transmit queue engine
-                */
                dev_activate(dev);
        }
 
@@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev)
 {
        int ret;
 
-       /*
-        *      Is it already up?
-        */
        if (dev->flags & IFF_UP)
                return 0;
 
-       /*
-        *      Open device
-        */
        ret = __dev_open(dev);
        if (ret < 0)
                return ret;
 
-       /*
-        *      ... and announce new interface.
-        */
        rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
        call_netdevice_notifiers(NETDEV_UP, dev);
 
@@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head)
        might_sleep();
 
        list_for_each_entry(dev, head, unreg_list) {
-               /*
-                *      Tell people we are going down, so that they can
-                *      prepare to death, when device is still operating.
-                */
                call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
 
                clear_bit(__LINK_STATE_START, &dev->state);
@@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head)
                if (ops->ndo_stop)
                        ops->ndo_stop(dev);
 
-               /*
-                *      Device is now down.
-                */
-
                dev->flags &= ~IFF_UP;
-
-               /*
-                *      Shutdown NET_DMA
-                */
                net_dmaengine_put();
        }
 
@@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head)
 
        __dev_close_many(head);
 
-       /*
-        * Tell people we are down
-        */
        list_for_each_entry(dev, head, unreg_list) {
                rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
                call_netdevice_notifiers(NETDEV_DOWN, dev);
@@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro);
 
 static int dev_boot_phase = 1;
 
-/*
- *     Device change register/unregister. These are not inline or static
- *     as we export them to the world.
- */
-
 /**
  *     register_netdevice_notifier - register a network notifier block
  *     @nb: notifier
@@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
        ASSERT_RTNL();
        return raw_notifier_call_chain(&netdev_chain, val, dev);
 }
+EXPORT_SYMBOL(call_netdevice_notifiers);
 
 /* When > 0 there are consumers of rx skb time stamps */
 static atomic_t netstamp_needed = ATOMIC_INIT(0);
index 24bd57493c0d602d38259b6111a6780611ca46fd..74ead9eca126cd99121f3bb581e5bb7359c0406e 100644 (file)
@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev)
 }
 EXPORT_SYMBOL(ethtool_op_get_flags);
 
+/* Check if device can enable (or disable) particular feature coded in "data"
+ * argument. Flags "supported" describe features that can be toggled by device.
+ * If feature can not be toggled, it state (enabled or disabled) must match
+ * hardcoded device features state, otherwise flags are marked as invalid.
+ */
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
+{
+       u32 features = dev->features & flags_dup_features;
+       /* "data" can contain only flags_dup_features bits,
+        * see __ethtool_set_flags */
+
+       return (features & ~supported) != (data & ~supported);
+}
+EXPORT_SYMBOL(ethtool_invalid_flags);
+
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
 {
-       if (data & ~supported)
+       if (ethtool_invalid_flags(dev, data, supported))
                return -EINVAL;
 
        dev->features = ((dev->features & ~flags_dup_features) |
index 90a3ff605591d8f84d1cad72bae9f7bc7c172d8e..b92c86f6e9b3e92d44e127f9df39b21b55fb2868 100644 (file)
@@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
                        err = fib_props[fa->fa_type].error;
                        if (err) {
 #ifdef CONFIG_IP_FIB_TRIE_STATS
-                               t->stats.semantic_match_miss++;
+                               t->stats.semantic_match_passed++;
 #endif
-                               return 1;
+                               return err;
                        }
                        if (fi->fib_flags & RTNH_F_DEAD)
                                continue;
index 1906fa35860c88a0919cd434268cbbcd679a3c39..28a736f3442f456c1abd7b7d56eb2e9c4ffdb493 100644 (file)
@@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
                                } else {
                                        dopt->ts_needtime = 0;
 
-                                       if (soffset + 8 <= optlen) {
+                                       if (soffset + 7 <= optlen) {
                                                __be32 addr;
 
-                                               memcpy(&addr, sptr+soffset-1, 4);
-                                               if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) {
+                                               memcpy(&addr, dptr+soffset-1, 4);
+                                               if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) {
                                                        dopt->ts_needtime = 1;
                                                        soffset += 8;
                                                }
index e837ffd3edc3dd0f9b2d9d03d82489b1464146c2..2d3c72e5bbbf054b16f88d50b606d22673f1e5b5 100644 (file)
@@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
                if (IS_ERR(rt)) {
                        err = PTR_ERR(rt);
+                       rt = NULL;
                        goto done;
                }
        }
index 7ff0343e05c72e330f213cec2a7ef248e5a8a76a..29e48593bf22c3e356bed011bdfbc9b9c2ad9baa 100644 (file)
@@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb)
        skb_pull(skb, (u8 *)encap - skb->data);
        skb_reset_network_header(skb);
        skb->protocol = htons(ETH_P_IPV6);
-       skb->ip_summed = 0;
+       skb->ip_summed = CHECKSUM_NONE;
        skb->pkt_type = PACKET_HOST;
 
        skb_tunnel_rx(skb, reg_dev);
index 5b743bdd89ba26a3a30b1110de67cea27636f047..36477538cea8eba501f000253b433d673b8d579f 100644 (file)
@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
        n = 1;
 
        name_len = fp[n++];
+
+       IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
+
        memcpy(name, fp+n, name_len); n+=name_len;
        name[name_len] = '\0';
 
        attr_len = fp[n++];
+
+       IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
+
        memcpy(attr, fp+n, attr_len); n+=attr_len;
        attr[attr_len] = '\0';
 
index 7c567b8aa89a9e938dc442487b70d5e099bc2ade..2bb2beb6a373d8b58ff9d112cae385e32093c94e 100644 (file)
@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket *     ap,
              while(isspace(start[length - 1]))
                length--;
 
+             DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
+                    -EINVAL, CTRL_ERROR, "Invalid nickname.\n");
+
              /* Copy the name for later reuse */
              memcpy(ap->rname, start + 5, length - 5);
              ap->rname[length - 5] = '\0';
index 5ee0c62046a03d0d17c4abe78782fd7e7f07c9c5..a80aef6e3d1fb7080a0f94d285d7a1736327624a 100644 (file)
@@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
        struct sock *make;
        struct rose_sock *make_rose;
        struct rose_facilities_struct facilities;
-       int n, len;
+       int n;
 
        skb->sk = NULL;         /* Initially we don't know who it's for */
 
@@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
         */
        memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
 
-       len  = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
-       len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
-       if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {
+       if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
+                                  skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
+                                  &facilities)) {
                rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);
                return 0;
        }
index ae4a9d99aec70da821722a4e204ee6eacf1df872..344456206b70bfbfdfdac7a342687687db4cb0c8 100644 (file)
@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param)
        unsigned int lci_i, lci_o;
 
        while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
+               if (skb->len < ROSE_MIN_LEN) {
+                       kfree_skb(skb);
+                       continue;
+               }
                lci_i     = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
                frametype = skb->data[2];
-               dest      = (rose_address *)(skb->data + 4);
+               if (frametype == ROSE_CALL_REQUEST &&
+                   (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||
+                    skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=
+                    ROSE_CALL_REQ_ADDR_LEN_VAL)) {
+                       kfree_skb(skb);
+                       continue;
+               }
+               dest      = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);
                lci_o     = ROSE_DEFAULT_MAXVC + 1 - lci_i;
 
                skb_reset_transport_header(skb);
index 88a77e90e7e86835587aabdb17f6805377f8df82..08dcd2f29cdc72b70713054de2c33b502458ff6a 100644 (file)
@@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        unsigned int lci, new_lci;
        unsigned char cause, diagnostic;
        struct net_device *dev;
-       int len, res = 0;
+       int res = 0;
        char buf[11];
 
 #if 0
@@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
                return res;
 #endif
 
+       if (skb->len < ROSE_MIN_LEN)
+               return res;
        frametype = skb->data[2];
        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
-       src_addr  = (rose_address *)(skb->data + 9);
-       dest_addr = (rose_address *)(skb->data + 4);
+       if (frametype == ROSE_CALL_REQUEST &&
+           (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||
+            skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=
+            ROSE_CALL_REQ_ADDR_LEN_VAL))
+               return res;
+       src_addr  = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF);
+       dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);
 
        spin_lock_bh(&rose_neigh_list_lock);
        spin_lock_bh(&rose_route_list_lock);
@@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
                goto out;
        }
 
-       len  = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
-       len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
-
        memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
 
-       if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {
+       if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
+                                  skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
+                                  &facilities)) {
                rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
                goto out;
        }
index 1734abba26a29bf1a9d156747b97d0d8c5f1fe84..f6c71caa94b9d8b7fe2d7873264929218af2a97c 100644 (file)
@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype)
                *dptr++ = ROSE_GFI | lci1;
                *dptr++ = lci2;
                *dptr++ = frametype;
-               *dptr++ = 0xAA;
+               *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL;
                memcpy(dptr, &rose->dest_addr,  ROSE_ADDR_LEN);
                dptr   += ROSE_ADDR_LEN;
                memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN);
@@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
        do {
                switch (*p & 0xC0) {
                case 0x00:
+                       if (len < 2)
+                               return -1;
                        p   += 2;
                        n   += 2;
                        len -= 2;
                        break;
 
                case 0x40:
+                       if (len < 3)
+                               return -1;
                        if (*p == FAC_NATIONAL_RAND)
                                facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
                        p   += 3;
@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
                        break;
 
                case 0x80:
+                       if (len < 4)
+                               return -1;
                        p   += 4;
                        n   += 4;
                        len -= 4;
                        break;
 
                case 0xC0:
+                       if (len < 2)
+                               return -1;
                        l = p[1];
+                       if (len < 2 + l)
+                               return -1;
                        if (*p == FAC_NATIONAL_DEST_DIGI) {
                                if (!fac_national_digis_received) {
+                                       if (l < AX25_ADDR_LEN)
+                                               return -1;
                                        memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN);
                                        facilities->source_ndigis = 1;
                                }
                        }
                        else if (*p == FAC_NATIONAL_SRC_DIGI) {
                                if (!fac_national_digis_received) {
+                                       if (l < AX25_ADDR_LEN)
+                                               return -1;
                                        memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN);
                                        facilities->dest_ndigis = 1;
                                }
                        }
                        else if (*p == FAC_NATIONAL_FAIL_CALL) {
+                               if (l < AX25_ADDR_LEN)
+                                       return -1;
                                memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN);
                        }
                        else if (*p == FAC_NATIONAL_FAIL_ADD) {
+                               if (l < 1 + ROSE_ADDR_LEN)
+                                       return -1;
                                memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN);
                        }
                        else if (*p == FAC_NATIONAL_DIGIS) {
+                               if (l % AX25_ADDR_LEN)
+                                       return -1;
                                fac_national_digis_received = 1;
                                facilities->source_ndigis = 0;
                                facilities->dest_ndigis   = 0;
                                for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
-                                       if (pt[6] & AX25_HBIT)
+                                       if (pt[6] & AX25_HBIT) {
+                                               if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
+                                                       return -1;
                                                memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
-                                       else
+                                       } else {
+                                               if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
+                                                       return -1;
                                                memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
+                                       }
                                }
                        }
                        p   += l + 2;
@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
        do {
                switch (*p & 0xC0) {
                case 0x00:
+                       if (len < 2)
+                               return -1;
                        p   += 2;
                        n   += 2;
                        len -= 2;
                        break;
 
                case 0x40:
+                       if (len < 3)
+                               return -1;
                        p   += 3;
                        n   += 3;
                        len -= 3;
                        break;
 
                case 0x80:
+                       if (len < 4)
+                               return -1;
                        p   += 4;
                        n   += 4;
                        len -= 4;
                        break;
 
                case 0xC0:
+                       if (len < 2)
+                               return -1;
                        l = p[1];
+
+                       /* Prevent overflows*/
+                       if (l < 10 || l > 20)
+                               return -1;
+
                        if (*p == FAC_CCITT_DEST_NSAP) {
                                memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
                                memcpy(callsign, p + 12,   l - 10);
@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
        return n;
 }
 
-int rose_parse_facilities(unsigned char *p,
+int rose_parse_facilities(unsigned char *p, unsigned packet_len,
        struct rose_facilities_struct *facilities)
 {
        int facilities_len, len;
 
        facilities_len = *p++;
 
-       if (facilities_len == 0)
+       if (facilities_len == 0 || (unsigned)facilities_len > packet_len)
                return 0;
 
-       while (facilities_len > 0) {
-               if (*p == 0x00) {
-                       facilities_len--;
-                       p++;
-
-                       switch (*p) {
-                       case FAC_NATIONAL:              /* National */
-                               len = rose_parse_national(p + 1, facilities, facilities_len - 1);
-                               facilities_len -= len + 1;
-                               p += len + 1;
-                               break;
-
-                       case FAC_CCITT:         /* CCITT */
-                               len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
-                               facilities_len -= len + 1;
-                               p += len + 1;
-                               break;
-
-                       default:
-                               printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
-                               facilities_len--;
-                               p++;
-                               break;
-                       }
-               } else
-                       break;  /* Error in facilities format */
+       while (facilities_len >= 3 && *p == 0x00) {
+               facilities_len--;
+               p++;
+
+               switch (*p) {
+               case FAC_NATIONAL:              /* National */
+                       len = rose_parse_national(p + 1, facilities, facilities_len - 1);
+                       break;
+
+               case FAC_CCITT:         /* CCITT */
+                       len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
+                       break;
+
+               default:
+                       printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
+                       len = 1;
+                       break;
+               }
+
+               if (len < 0)
+                       return 0;
+               if (WARN_ON(len >= facilities_len))
+                       return 0;
+               facilities_len -= len + 1;
+               p += len + 1;
        }
 
-       return 1;
+       return facilities_len == 0;
 }
 
 static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
index ffb687671da0545866739ad4c6e69c5155976beb..6b43ee7221d5a830b8b0acea4375f9341aacfc90 100644 (file)
@@ -860,8 +860,10 @@ static void rpc_release_resources_task(struct rpc_task *task)
 {
        if (task->tk_rqstp)
                xprt_release(task);
-       if (task->tk_msg.rpc_cred)
+       if (task->tk_msg.rpc_cred) {
                put_rpccred(task->tk_msg.rpc_cred);
+               task->tk_msg.rpc_cred = NULL;
+       }
        rpc_task_release_client(task);
 }
 
index 872065ca7f8c8ade85d3d5edd90682bab8a23e3b..a026b0ef2443ce3150417059691434a4926ba108 100644 (file)
@@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
                        goto drop_unlock;
                }
 
-               if (x->props.replay_window && x->repl->check(x, skb, seq)) {
+               if (x->repl->check(x, skb, seq)) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
                        goto drop_unlock;
                }
@@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
                XFRM_SKB_CB(skb)->seq.input.low = seq;
                XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
 
+               skb_dst_force(skb);
+
                nexthdr = x->type->input(x, skb);
 
                if (nexthdr == -EINPROGRESS)
index 1aba03f449cc889098fc33710692e0c1b1518c3c..47bacd8c025094e24b0200bab9a7c1d438093aa1 100644 (file)
@@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 
                spin_unlock_bh(&x->lock);
 
+               skb_dst_force(skb);
+
                err = x->type->output(x, skb);
                if (err == -EINPROGRESS)
                        goto out_exit;
@@ -94,7 +96,7 @@ resume:
                        err = -EHOSTUNREACH;
                        goto error_nolock;
                }
-               skb_dst_set(skb, dst_clone(dst));
+               skb_dst_set(skb, dst);
                x = dst->xfrm;
        } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
index 2f5be5b15740507fac23201330899faf949055a0..f218385950ca06a3a8b6830c51c29ac370ca2ea0 100644 (file)
@@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x,
        u32 diff;
        u32 seq = ntohl(net_seq);
 
+       if (!x->props.replay_window)
+               return 0;
+
        if (unlikely(seq == 0))
                goto err;
 
@@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x,
 {
        unsigned int bitnr, nr;
        struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+       u32 pos;
        u32 seq = ntohl(net_seq);
        u32 diff =  replay_esn->seq - seq;
-       u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
+       if (!replay_esn->replay_window)
+               return 0;
+
+       pos = (replay_esn->seq - 1) % replay_esn->replay_window;
 
        if (unlikely(seq == 0))
                goto err;
@@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x,
        unsigned int bitnr, nr;
        u32 diff;
        struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+       u32 pos;
        u32 seq = ntohl(net_seq);
-       u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
        u32 wsize = replay_esn->replay_window;
        u32 top = replay_esn->seq;
        u32 bottom = top - wsize + 1;
 
+       if (!wsize)
+               return 0;
+
+       pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
        if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
                     (replay_esn->seq < replay_esn->replay_window - 1)))
                goto err;
index f83a3d1da81b90ec382918e4b5b193a150b99211..dd78536d40dee8e6c6bbaa876ada9d82a00994e7 100644 (file)
@@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
                        goto error;
        }
 
+       if (orig->replay_esn) {
+               err = xfrm_replay_clone(x, orig);
+               if (err)
+                       goto error;
+       }
+
        memcpy(&x->mark, &orig->mark, sizeof(x->mark));
 
        err = xfrm_init_state(x);
index fc152d28753c41df6bd7e26becee2b1657a3ace8..3d15d3e1b2c49b7c124cd08d42ed5a1a77849c57 100644 (file)
@@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
        if (!rt)
                return 0;
 
+       if (p->id.proto != IPPROTO_ESP)
+               return -EINVAL;
+
        if (p->replay_window != 0)
                return -EINVAL;
 
@@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
        return 0;
 }
 
+static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn,
+                                        struct nlattr *rp)
+{
+       struct xfrm_replay_state_esn *up;
+
+       if (!replay_esn || !rp)
+               return 0;
+
+       up = nla_data(rp);
+
+       if (xfrm_replay_state_esn_len(replay_esn) !=
+                       xfrm_replay_state_esn_len(up))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
                                       struct xfrm_replay_state_esn **preplay_esn,
                                       struct nlattr *rta)
@@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (x->km.state != XFRM_STATE_VALID)
                goto out;
 
+       err = xfrm_replay_verify_len(x->replay_esn, rp);
+       if (err)
+               goto out;
+
        spin_lock_bh(&x->lock);
        xfrm_update_ae_params(x, attrs);
        spin_unlock_bh(&x->lock);
index 3e7544d2a07bb617e4d7a4eaee6cf6dcb0dd6c63..ea7c01f4a2bf8388f27beda3e8c33d25baf7914f 100644 (file)
@@ -213,7 +213,7 @@ static u16 map_class(u16 pol_value)
                        return i;
        }
 
-       return pol_value;
+       return SECCLASS_NULL;
 }
 
 static void map_decision(u16 tclass, struct av_decision *avd,
index 3e65da21a08c0398f78f5aa32da004dbe08a1c6d..a0080aa45ae968dfbcd9607fa39f7b587acc7c33 100644 (file)
@@ -848,6 +848,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
                return -ENOMEM;
        mfile->file = file;
        mfile->disconnected_f_op = NULL;
+       INIT_LIST_HEAD(&mfile->shutdown_list);
        spin_lock(&card->files_lock);
        if (card->shutdown) {
                spin_unlock(&card->files_lock);
@@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
        list_for_each_entry(mfile, &card->files_list, list) {
                if (mfile->file == file) {
                        list_del(&mfile->list);
+                       spin_lock(&shutdown_lock);
+                       list_del(&mfile->shutdown_list);
+                       spin_unlock(&shutdown_lock);
                        if (mfile->disconnected_f_op)
                                fops_put(mfile->disconnected_f_op);
                        found = mfile;
index ae42b6509ce4cabeda3d9beeeaea39f814be5d35..fe5c8036bebaf3d9850ce2bfe60cd8b63f551f9d 100644 (file)
@@ -3201,15 +3201,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
 EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
 #endif /* SNDRV_PCM_INFO_MMAP */
 
-/* mmap callback with pgprot_noncached */
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
-                              struct vm_area_struct *area)
-{
-       area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
-       return snd_pcm_default_mmap(substream, area);
-}
-EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
-
 /*
  * mmap DMA buffer
  */
index b7617bee6388f13be8fa4bf842c6c88990faef90..0199a317c5a9a5d2d180ad9f5ab03a6b048a0066 100644 (file)
@@ -271,7 +271,7 @@ struct synth_operations
        void (*reset) (int dev);
        void (*hw_control) (int dev, unsigned char *event);
        int (*load_patch) (int dev, int format, const char __user *addr,
-            int offs, int count, int pmgr_flag);
+            int count, int pmgr_flag);
        void (*aftertouch) (int dev, int voice, int pressure);
        void (*controller) (int dev, int voice, int ctrl_num, int value);
        void (*panning) (int dev, int voice, int value);
index 3c09374ea5bf179e0bada2481c280fa7496e8faf..2292c230d7e6fb33d0894e9b8fff16d4e2d4e552 100644 (file)
@@ -476,7 +476,7 @@ EXPORT_SYMBOL(midi_synth_hw_control);
 
 int
 midi_synth_load_patch(int dev, int format, const char __user *addr,
-                     int offs, int count, int pmgr_flag)
+                     int count, int pmgr_flag)
 {
        int             orig_dev = synth_devs[dev]->midi_dev;
 
@@ -491,33 +491,29 @@ midi_synth_load_patch(int dev, int format, const char __user *addr,
        if (!prefix_cmd(orig_dev, 0xf0))
                return 0;
 
+       /* Invalid patch format */
        if (format != SYSEX_PATCH)
-       {
-/*               printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
                  return -EINVAL;
-       }
+
+       /* Patch header too short */
        if (count < hdr_size)
-       {
-/*             printk("MIDI Error: Patch header too short\n");*/
                return -EINVAL;
-       }
+
        count -= hdr_size;
 
        /*
-        * Copy the header from user space but ignore the first bytes which have
-        * been transferred already.
+        * Copy the header from user space
         */
 
-       if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
+       if (copy_from_user(&sysex, addr, hdr_size))
                return -EFAULT;
-       if (count < sysex.len)
-       {
-/*             printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
+
+       /* Sysex record too short */
+       if ((unsigned)count < (unsigned)sysex.len)
                sysex.len = count;
-       }
-       left = sysex.len;
-       src_offs = 0;
+
+       left = sysex.len;
+       src_offs = 0;
 
        for (i = 0; i < left && !signal_pending(current); i++)
        {
index 6bc9d00bc77c474f00d7886b9f4ed9243cef1cb0..b64ddd6c4abc045706b0fa81d24864962dc78ee2 100644 (file)
@@ -8,7 +8,7 @@ int midi_synth_open (int dev, int mode);
 void midi_synth_close (int dev);
 void midi_synth_hw_control (int dev, unsigned char *event);
 int midi_synth_load_patch (int dev, int format, const char __user * addr,
-                int offs, int count, int pmgr_flag);
+                int count, int pmgr_flag);
 void midi_synth_panning (int dev, int channel, int pressure);
 void midi_synth_aftertouch (int dev, int channel, int pressure);
 void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
index 938c48c43585ea88fa0be036b0765e24f3221ff0..407cd677950bccb68059fdcd1abec6da914b7a38 100644 (file)
@@ -820,7 +820,7 @@ static void opl3_hw_control(int dev, unsigned char *event)
 }
 
 static int opl3_load_patch(int dev, int format, const char __user *addr,
-               int offs, int count, int pmgr_flag)
+               int count, int pmgr_flag)
 {
        struct sbi_instrument ins;
 
@@ -830,11 +830,7 @@ static int opl3_load_patch(int dev, int format, const char __user *addr,
                return -EINVAL;
        }
 
-       /*
-        * What the fuck is going on here?  We leave junk in the beginning
-        * of ins and then check the field pretty close to that beginning?
-        */
-       if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs))
+       if (copy_from_user(&ins, addr, sizeof(ins)))
                return -EFAULT;
 
        if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
@@ -849,6 +845,10 @@ static int opl3_load_patch(int dev, int format, const char __user *addr,
 
 static void opl3_panning(int dev, int voice, int value)
 {
+
+       if (voice < 0 || voice >= devc->nr_voice)
+               return;
+
        devc->voc[voice].panning = value;
 }
 
@@ -1066,8 +1066,15 @@ static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info
 
 static void opl3_setup_voice(int dev, int voice, int chn)
 {
-       struct channel_info *info =
-       &synth_devs[dev]->chn_info[chn];
+       struct channel_info *info;
+
+       if (voice < 0 || voice >= devc->nr_voice)
+               return;
+
+       if (chn < 0 || chn > 15)
+               return;
+
+       info = &synth_devs[dev]->chn_info[chn];
 
        opl3_set_instr(dev, voice, info->pgm_num);
 
index 5ea1098ac427a5546bdf9f211587bbe8030d1821..30bcfe470f8310fa7fa72cc1ddcf7ab4ba6a794c 100644 (file)
@@ -241,7 +241,7 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun
                                return -ENXIO;
 
                        fmt = (*(short *) &event_rec[0]) & 0xffff;
-                       err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0);
+                       err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0);
                        if (err < 0)
                                return err;
 
index 0ac1f98d91a1f2196fb9cd4aa93b4c79c2d57aad..f53a31e939c15bd1f6f33066a2480bfe6fd49589 100644 (file)
  *  for any purpose including commercial applications.
  */
 
-/* >0: print Hw params, timer vars. >1: print stream write/copy sizes  */
-#define REALLY_VERBOSE_LOGGING 0
-
-#if REALLY_VERBOSE_LOGGING
-#define VPRINTK1 snd_printd
-#else
-#define VPRINTK1(...)
-#endif
-
-#if REALLY_VERBOSE_LOGGING > 1
-#define VPRINTK2 snd_printd
-#else
-#define VPRINTK2(...)
-#endif
-
 #include "hpi_internal.h"
 #include "hpimsginit.h"
 #include "hpioctl.h"
 #include <sound/tlv.h>
 #include <sound/hwdep.h>
 
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
 MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
 
+#if defined CONFIG_SND_DEBUG_VERBOSE
+/**
+ * snd_printddd - very verbose debug printk
+ * @format: format string
+ *
+ * Works like snd_printk() for debugging purposes.
+ * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
+ * Must set snd module debug parameter to 3 to enable at runtime.
+ */
+#define snd_printddd(format, args...) \
+       __snd_printk(3, __FILE__, __LINE__, format, ##args)
+#else
+#define snd_printddd(format, args...)  do { } while (0)
+#endif
+
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
@@ -289,7 +288,6 @@ static u16 handle_error(u16 err, int line, char *filename)
 #define hpi_handle_error(x)  handle_error(x, __LINE__, __FILE__)
 
 /***************************** GENERAL PCM ****************/
-#if REALLY_VERBOSE_LOGGING
 static void print_hwparams(struct snd_pcm_hw_params *p)
 {
        snd_printd("HWPARAMS \n");
@@ -304,9 +302,6 @@ static void print_hwparams(struct snd_pcm_hw_params *p)
        snd_printd("periods %d \n", params_periods(p));
        snd_printd("buffer_size %d \n", params_buffer_size(p));
 }
-#else
-#define print_hwparams(x)
-#endif
 
 static snd_pcm_format_t hpi_to_alsa_formats[] = {
        -1,                     /* INVALID */
@@ -381,13 +376,13 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
                                "No local sampleclock, err %d\n", err);
                }
 
-               for (idx = 0; idx < 100; idx++) {
-                       if (hpi_sample_clock_query_local_rate(
-                               h_control, idx, &sample_rate)) {
-                               if (!idx)
-                                       snd_printk(KERN_ERR
-                                               "Local rate query failed\n");
-
+               for (idx = -1; idx < 100; idx++) {
+                       if (idx == -1) {
+                               if (hpi_sample_clock_get_sample_rate(h_control,
+                                                               &sample_rate))
+                                       continue;
+                       } else if (hpi_sample_clock_query_local_rate(h_control,
+                                                       idx, &sample_rate)) {
                                break;
                        }
 
@@ -440,8 +435,6 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
                }
        }
 
-       /* printk(KERN_INFO "Supported rates %X %d %d\n",
-          rates, rate_min, rate_max); */
        pcmhw->rates = rates;
        pcmhw->rate_min = rate_min;
        pcmhw->rate_max = rate_max;
@@ -466,7 +459,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
        if (err)
                return err;
 
-       VPRINTK1(KERN_INFO "format %d, %d chans, %d_hz\n",
+       snd_printdd("format %d, %d chans, %d_hz\n",
                                format, params_channels(params),
                                params_rate(params));
 
@@ -489,13 +482,12 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
                err = hpi_stream_host_buffer_attach(dpcm->h_stream,
                        params_buffer_bytes(params),  runtime->dma_addr);
                if (err == 0) {
-                       VPRINTK1(KERN_INFO
+                       snd_printdd(
                                "stream_host_buffer_attach succeeded %u %lu\n",
                                params_buffer_bytes(params),
                                (unsigned long)runtime->dma_addr);
                } else {
-                       snd_printd(KERN_INFO
-                                       "stream_host_buffer_attach error %d\n",
+                       snd_printd("stream_host_buffer_attach error %d\n",
                                        err);
                        return -ENOMEM;
                }
@@ -504,7 +496,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
                                                &dpcm->hpi_buffer_attached,
                                                NULL, NULL, NULL);
 
-               VPRINTK1(KERN_INFO "stream_host_buffer_attach status 0x%x\n",
+               snd_printdd("stream_host_buffer_attach status 0x%x\n",
                                dpcm->hpi_buffer_attached);
        }
        bytes_per_sec = params_rate(params) * params_channels(params);
@@ -517,7 +509,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
        dpcm->bytes_per_sec = bytes_per_sec;
        dpcm->buffer_bytes = params_buffer_bytes(params);
        dpcm->period_bytes = params_period_bytes(params);
-       VPRINTK1(KERN_INFO "buffer_bytes=%d, period_bytes=%d, bps=%d\n",
+       snd_printdd("buffer_bytes=%d, period_bytes=%d, bps=%d\n",
                        dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec);
 
        return 0;
@@ -573,7 +565,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
        struct snd_pcm_substream *s;
        u16 e;
 
-       VPRINTK1(KERN_INFO "%c%d trigger\n",
+       snd_printdd("%c%d trigger\n",
                        SCHR(substream->stream), substream->number);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -597,7 +589,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                                * data??
                                */
                                unsigned int preload = ds->period_bytes * 1;
-                               VPRINTK2(KERN_INFO "%d preload x%x\n", s->number, preload);
+                               snd_printddd("%d preload x%x\n", s->number, preload);
                                hpi_handle_error(hpi_outstream_write_buf(
                                                ds->h_stream,
                                                &runtime->dma_area[0],
@@ -607,7 +599,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                        }
 
                        if (card->support_grouping) {
-                               VPRINTK1(KERN_INFO "\t%c%d group\n",
+                               snd_printdd("\t%c%d group\n",
                                                SCHR(s->stream),
                                                s->number);
                                e = hpi_stream_group_add(
@@ -622,7 +614,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                        } else
                                break;
                }
-               VPRINTK1(KERN_INFO "start\n");
+               snd_printdd("start\n");
                /* start the master stream */
                snd_card_asihpi_pcm_timer_start(substream);
                if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ||
@@ -644,14 +636,14 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                        s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
 
                        if (card->support_grouping) {
-                               VPRINTK1(KERN_INFO "\t%c%d group\n",
+                               snd_printdd("\t%c%d group\n",
                                SCHR(s->stream),
                                        s->number);
                                snd_pcm_trigger_done(s, substream);
                        } else
                                break;
                }
-               VPRINTK1(KERN_INFO "stop\n");
+               snd_printdd("stop\n");
 
                /* _prepare and _hwparams reset the stream */
                hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
@@ -664,12 +656,12 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                break;
 
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               VPRINTK1(KERN_INFO "pause release\n");
+               snd_printdd("pause release\n");
                hpi_handle_error(hpi_stream_start(dpcm->h_stream));
                snd_card_asihpi_pcm_timer_start(substream);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               VPRINTK1(KERN_INFO "pause\n");
+               snd_printdd("pause\n");
                snd_card_asihpi_pcm_timer_stop(substream);
                hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
                break;
@@ -741,7 +733,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
        u16 state;
        u32 buffer_size, bytes_avail, samples_played, on_card_bytes;
 
-       VPRINTK1(KERN_INFO "%c%d snd_card_asihpi_timer_function\n",
+       snd_printdd("%c%d snd_card_asihpi_timer_function\n",
                                SCHR(substream->stream), substream->number);
 
        /* find minimum newdata and buffer pos in group */
@@ -770,10 +762,10 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                                if ((bytes_avail == 0) &&
                                    (on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
                                        hpi_handle_error(hpi_stream_start(ds->h_stream));
-                                       VPRINTK1(KERN_INFO "P%d start\n", s->number);
+                                       snd_printdd("P%d start\n", s->number);
                                }
                        } else if (state == HPI_STATE_DRAINED) {
-                               VPRINTK1(KERN_WARNING "P%d drained\n",
+                               snd_printd(KERN_WARNING "P%d drained\n",
                                                s->number);
                                /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
                                continue; */
@@ -794,13 +786,13 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                                newdata);
                }
 
-               VPRINTK1(KERN_INFO "PB timer hw_ptr x%04lX, appl_ptr x%04lX\n",
+               snd_printdd("hw_ptr x%04lX, appl_ptr x%04lX\n",
                        (unsigned long)frames_to_bytes(runtime,
                                                runtime->status->hw_ptr),
                        (unsigned long)frames_to_bytes(runtime,
                                                runtime->control->appl_ptr));
 
-               VPRINTK1(KERN_INFO "%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X,"
+               snd_printdd("%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X,"
                        " aux=x%04X space=x%04X\n",
                        loops, SCHR(s->stream), s->number,
                        state,  ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail,
@@ -822,7 +814,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
 
        next_jiffies = max(next_jiffies, 1U);
        dpcm->timer.expires = jiffies + next_jiffies;
-       VPRINTK1(KERN_INFO "jif %d buf pos x%04X newdata x%04X xfer x%04X\n",
+       snd_printdd("jif %d buf pos x%04X newdata x%04X xfer x%04X\n",
                        next_jiffies, pcm_buf_dma_ofs, newdata, xfercount);
 
        snd_pcm_group_for_each_entry(s, substream) {
@@ -837,7 +829,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                if (xfercount && (on_card_bytes <= ds->period_bytes)) {
                        if (card->support_mmap) {
                                if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                                       VPRINTK2(KERN_INFO "P%d write x%04x\n",
+                                       snd_printddd("P%d write x%04x\n",
                                                        s->number,
                                                        ds->period_bytes);
                                        hpi_handle_error(
@@ -848,7 +840,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                                                        xfercount,
                                                        &ds->format));
                                } else {
-                                       VPRINTK2(KERN_INFO "C%d read x%04x\n",
+                                       snd_printddd("C%d read x%04x\n",
                                                s->number,
                                                xfercount);
                                        hpi_handle_error(
@@ -871,7 +863,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
 static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
                                          unsigned int cmd, void *arg)
 {
-       /* snd_printd(KERN_INFO "Playback ioctl %d\n", cmd); */
+       snd_printdd(KERN_INFO "Playback ioctl %d\n", cmd);
        return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
 
@@ -881,7 +873,7 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-       VPRINTK1(KERN_INFO "playback prepare %d\n", substream->number);
+       snd_printdd("playback prepare %d\n", substream->number);
 
        hpi_handle_error(hpi_outstream_reset(dpcm->h_stream));
        dpcm->pcm_buf_host_rw_ofs = 0;
@@ -898,7 +890,7 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
        snd_pcm_uframes_t ptr;
 
        ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs  % dpcm->buffer_bytes);
-       /* VPRINTK2(KERN_INFO "playback_pointer=x%04lx\n", (unsigned long)ptr); */
+       snd_printddd("playback_pointer=x%04lx\n", (unsigned long)ptr);
        return ptr;
 }
 
@@ -1014,12 +1006,13 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
 
        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
                card->update_interval_frames);
+
        snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
                card->update_interval_frames * 2, UINT_MAX);
 
        snd_pcm_set_sync(substream);
 
-       VPRINTK1(KERN_INFO "playback open\n");
+       snd_printdd("playback open\n");
 
        return 0;
 }
@@ -1030,7 +1023,7 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
        struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
        hpi_handle_error(hpi_outstream_close(dpcm->h_stream));
-       VPRINTK1(KERN_INFO "playback close\n");
+       snd_printdd("playback close\n");
 
        return 0;
 }
@@ -1050,13 +1043,13 @@ static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream,
        if (copy_from_user(runtime->dma_area, src, len))
                return -EFAULT;
 
-       VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n",
+       snd_printddd("playback copy%d %u bytes\n",
                        substream->number, len);
 
        hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream,
                                runtime->dma_area, len, &dpcm->format));
 
-       dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len;
+       dpcm->pcm_buf_host_rw_ofs += len;
 
        return 0;
 }
@@ -1066,16 +1059,11 @@ static int snd_card_asihpi_playback_silence(struct snd_pcm_substream *
                                            snd_pcm_uframes_t pos,
                                            snd_pcm_uframes_t count)
 {
-       unsigned int len;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
-
-       len = frames_to_bytes(runtime, count);
-       VPRINTK1(KERN_INFO "playback silence  %u bytes\n", len);
-
-       memset(runtime->dma_area, 0, len);
-       hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream,
-                               runtime->dma_area, len, &dpcm->format));
+       /* Usually writes silence to DMA buffer, which should be overwritten
+       by real audio later.  Our fifos cannot be overwritten, and are not
+       free-running DMAs. Silence is output on fifo underflow.
+       This callback is still required to allow the copy callback to be used.
+       */
        return 0;
 }
 
@@ -1110,7 +1098,7 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-       VPRINTK2(KERN_INFO "capture pointer %d=%d\n",
+       snd_printddd("capture pointer %d=%d\n",
                        substream->number, dpcm->pcm_buf_dma_ofs);
        /* NOTE Unlike playback can't use actual samples_played
                for the capture position, because those samples aren't yet in
@@ -1135,7 +1123,7 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
        dpcm->pcm_buf_dma_ofs = 0;
        dpcm->pcm_buf_elapsed_dma_ofs = 0;
 
-       VPRINTK1("Capture Prepare %d\n", substream->number);
+       snd_printdd("Capture Prepare %d\n", substream->number);
        return 0;
 }
 
@@ -1198,7 +1186,7 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
        if (dpcm == NULL)
                return -ENOMEM;
 
-       VPRINTK1("hpi_instream_open adapter %d stream %d\n",
+       snd_printdd("capture open adapter %d stream %d\n",
                   card->adapter_index, substream->number);
 
        err = hpi_handle_error(
@@ -1268,7 +1256,7 @@ static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream,
 
        len = frames_to_bytes(runtime, count);
 
-       VPRINTK2(KERN_INFO "capture copy%d %d bytes\n", substream->number, len);
+       snd_printddd("capture copy%d %d bytes\n", substream->number, len);
        hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream,
                                runtime->dma_area, len));
 
@@ -2887,6 +2875,9 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
        if (err)
                asihpi->update_interval_frames = 512;
 
+       if (!asihpi->support_mmap)
+               asihpi->update_interval_frames *= 2;
+
        hpi_handle_error(hpi_instream_open(asihpi->adapter_index,
                             0, &h_stream));
 
@@ -2909,7 +2900,6 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
                        asihpi->support_mrx
              );
 
-
        err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams);
        if (err < 0) {
                snd_printk(KERN_ERR "pcm_new failed\n");
@@ -2944,6 +2934,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
        sprintf(card->longname, "%s %i",
                        card->shortname, asihpi->adapter_index);
        err = snd_card_register(card);
+
        if (!err) {
                hpi_card->snd_card_asihpi = card;
                dev++;
index 734c6ee55d8a7ecc20fe56e3dce6c6b3f75397f0..2942d2a9ea10fd5be3c390ce6f30659f0368516a 100644 (file)
@@ -4255,6 +4255,84 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
        return 0;
 }
 
+/*
+ * Precision R5500
+ * 0x12 - HP/line-out
+ * 0x13 - speaker (mono)
+ * 0x15 - mic-in
+ */
+
+static struct hda_verb ad1984a_precision_verbs[] = {
+       /* Unmute main output path */
+       {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
+       /* Analog mixer; mute as default */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       /* Select mic as input */
+       {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
+       /* Configure as mic */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
+       /* HP unmute */
+       {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* turn on EAPD */
+       {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+       /* unsolicited event for pin-sense */
+       {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+       { } /* end */
+};
+
+static struct snd_kcontrol_new ad1984a_precision_mixers[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
+
+/* mute internal speaker if HP is plugged */
+static void ad1984a_precision_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_jack_detect(codec, 0x12);
+       snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+
+/* unsolicited event for HP jack sensing */
+static void ad1984a_precision_unsol_event(struct hda_codec *codec,
+                                        unsigned int res)
+{
+       if ((res >> 26) != AD1884A_HP_EVENT)
+               return;
+       ad1984a_precision_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1984a_precision_init(struct hda_codec *codec)
+{
+       ad198x_init(codec);
+       ad1984a_precision_automute(codec);
+       return 0;
+}
+
+
 /*
  * HP Touchsmart
  * port-A (0x11)      - front hp-out
@@ -4384,6 +4462,7 @@ enum {
        AD1884A_MOBILE,
        AD1884A_THINKPAD,
        AD1984A_TOUCHSMART,
+       AD1984A_PRECISION,
        AD1884A_MODELS
 };
 
@@ -4393,9 +4472,11 @@ static const char * const ad1884a_models[AD1884A_MODELS] = {
        [AD1884A_MOBILE]        = "mobile",
        [AD1884A_THINKPAD]      = "thinkpad",
        [AD1984A_TOUCHSMART]    = "touchsmart",
+       [AD1984A_PRECISION]     = "precision",
 };
 
 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
        SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
        SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
@@ -4489,6 +4570,14 @@ static int patch_ad1884a(struct hda_codec *codec)
                codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
                codec->patch_ops.init = ad1984a_thinkpad_init;
                break;
+       case AD1984A_PRECISION:
+               spec->mixers[0] = ad1984a_precision_mixers;
+               spec->init_verbs[spec->num_init_verbs++] =
+                       ad1984a_precision_verbs;
+               spec->multiout.dig_out_nid = 0;
+               codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
+               codec->patch_ops.init = ad1984a_precision_init;
+               break;
        case AD1984A_TOUCHSMART:
                spec->mixers[0] = ad1984a_touchsmart_mixers;
                spec->init_verbs[0] = ad1984a_touchsmart_verbs;
index 5d582de91c1904bcf3bee9446232b7ab8fca57ac..0ef0035fe99ff64d1b9d161177fe87a16015be78 100644 (file)
@@ -1290,7 +1290,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                case 0x10ec0883:
                case 0x10ec0885:
                case 0x10ec0887:
-               case 0x10ec0889:
+               /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
                        alc889_coef_init(codec);
                        break;
                case 0x10ec0888:
index c0dcfca9b5b55ed0b2e8737bf33823b915aae690..c66d3f64dcf89f6b5f0f59dea6cdbfd2b412bbb9 100644 (file)
@@ -1567,6 +1567,46 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x0104),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "UM-1G", */
+               .ifnum = 0,
+               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = & (const struct snd_usb_midi_endpoint_info) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+       }
+},
+{
+       /* Boss JS-8 Jam Station  */
+       USB_DEVICE(0x0582, 0x0109),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "BOSS", */
+               /* .product_name = "JS-8", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        /* has ID 0x0110 when not in Advanced Driver mode */
        USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f),