]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2011 16:25:34 +0000 (09:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2011 16:25:34 +0000 (09:25 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (33 commits)
  IPVS: Use global mutex in ip_vs_app.c
  ipvs: fix a typo in __ip_vs_control_init()
  veth: Fix the byte counters
  net ipv6: Fix duplicate /proc/sys/net/ipv6/neigh directory entries.
  macvlan: Fix use after free of struct macvlan_port.
  net: fix incorrect spelling in drop monitor protocol
  can: c_can: Do basic c_can configuration _before_ enabling the interrupts
  net/appletalk: fix atalk_release use after free
  ipx: fix ipx_release()
  snmp: SNMP_UPD_PO_STATS_BH() always called from softirq
  l2tp: fix possible oops on l2tp_eth module unload
  xfrm: Fix initialize repl field of struct xfrm_state
  netfilter: ipt_CLUSTERIP: fix buffer overflow
  netfilter: xtables: fix reentrancy
  netfilter: ipset: fix checking the type revision at create command
  netfilter: ipset: fix address ranges at hash:*port* types
  niu: Rename NIU parent platform device name to fix conflict.
  r8169: fix a bug in rtl8169_init_phy()
  bonding: fix a typo in a comment
  ftmac100: use resource_size()
  ...

422 files changed:
Documentation/ABI/testing/pstore
Documentation/ABI/testing/sysfs-devices-mmc [new file with mode: 0644]
Documentation/ABI/testing/sysfs-fs-pstore [deleted file]
Documentation/devicetree/bindings/hwmon/ads1015.txt [new file with mode: 0644]
Documentation/devicetree/bindings/open-pic.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/xfs-delayed-logging-design.txt
Documentation/hwmon/ads1015 [new file with mode: 0644]
Documentation/hwmon/hpfall.c [deleted file]
Documentation/hwmon/lis3lv02d [deleted file]
Documentation/hwmon/lm75
Documentation/hwmon/sch5627 [new file with mode: 0644]
Documentation/hwmon/w83795 [new file with mode: 0644]
Documentation/i2c/busses/i2c-i801
Documentation/i2c/instantiating-devices
Documentation/i2c/upgrading-clients
Documentation/kbuild/kbuild.txt
Documentation/laptops/hpfall.c [new file with mode: 0644]
Documentation/misc-devices/lis3lv02d [new file with mode: 0644]
Documentation/video4linux/Zoran
MAINTAINERS
Makefile
arch/arm/boot/compressed/Makefile
arch/arm/mach-mxs/include/mach/mmc.h [new file with mode: 0644]
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/plat-mxc/include/mach/esdhc.h
arch/arm/vfp/Makefile
arch/blackfin/Kconfig
arch/blackfin/configs/BF518F-EZBRD_defconfig
arch/blackfin/configs/BF526-EZBRD_defconfig
arch/blackfin/configs/BF527-EZKIT-V2_defconfig
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF538-EZKIT_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/include/asm/def_LPBlackfin.h
arch/blackfin/include/asm/dpmc.h
arch/blackfin/include/asm/ipipe.h
arch/blackfin/include/asm/ipipe_base.h
arch/blackfin/include/asm/irqflags.h
arch/blackfin/include/asm/smp.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/ipipe.c
arch/blackfin/kernel/irqchip.c
arch/blackfin/kernel/kgdb.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/vmlinux.lds.S
arch/blackfin/mach-bf518/include/mach/defBF512.h
arch/blackfin/mach-bf527/include/mach/defBF522.h
arch/blackfin/mach-bf533/boards/ip0x.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/dnp5370.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-bf537/include/mach/defBF534.h
arch/blackfin/mach-bf548/Kconfig
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/defBF544.h
arch/blackfin/mach-bf548/include/mach/defBF547.h
arch/blackfin/mach-bf548/include/mach/dma.h
arch/blackfin/mach-bf548/include/mach/irq.h
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/hotplug.c
arch/blackfin/mach-bf561/secondary.S
arch/blackfin/mach-bf561/smp.c
arch/blackfin/mach-common/arch_checks.c
arch/blackfin/mach-common/cache.S
arch/blackfin/mach-common/cpufreq.c
arch/blackfin/mach-common/dpmc.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/head.S
arch/blackfin/mach-common/interrupt.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/smp.c
arch/h8300/boot/compressed/Makefile
arch/ia64/kvm/Makefile
arch/ia64/sn/kernel/Makefile
arch/ia64/sn/kernel/sn2/Makefile
arch/ia64/sn/pci/Makefile
arch/ia64/sn/pci/pcibr/Makefile
arch/ia64/uv/kernel/Makefile
arch/microblaze/kernel/cpu/Makefile
arch/mips/Makefile
arch/mips/bcm63xx/boards/Makefile
arch/mips/fw/arc/Makefile
arch/mips/jz4740/Makefile
arch/mips/oprofile/Makefile
arch/mips/pmc-sierra/yosemite/Makefile
arch/mips/powertv/Makefile
arch/mips/powertv/asic/Makefile
arch/mips/powertv/pci/Makefile
arch/mn10300/Kconfig
arch/mn10300/include/asm/intctl-regs.h
arch/mn10300/kernel/Makefile
arch/mn10300/kernel/cevt-mn10300.c
arch/mn10300/kernel/csrc-mn10300.c
arch/mn10300/kernel/internal.h
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/smp.c
arch/mn10300/kernel/time.c
arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
arch/mn10300/unit-asb2364/include/unit/serial.h
arch/mn10300/unit-asb2364/irq-fpga.c
arch/mn10300/unit-asb2364/unit-init.c
arch/parisc/Kconfig
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/irq.h
arch/parisc/include/asm/pgtable.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/irq.c
arch/parisc/kernel/pacache.S
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/sysdev/mpic.c
arch/s390/boot/Makefile
arch/s390/kvm/Makefile
arch/s390/math-emu/Makefile
arch/sparc/include/asm/irq_32.h
arch/sparc/include/asm/irq_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/kernel/of_device_common.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/tile/lib/atomic_32.c
arch/um/sys-ppc/Makefile
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/unistd_32.h
arch/x86/include/asm/unistd_64.h
arch/x86/kernel/syscall_table_32.S
arch/xtensa/boot/Makefile
arch/xtensa/boot/lib/Makefile
drivers/char/mwave/Makefile
drivers/char/mwave/README
drivers/dma/Makefile
drivers/firewire/Kconfig
drivers/firewire/core-card.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firewire/core-iso.c
drivers/firewire/core-topology.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/abituguru.c
drivers/hwmon/abituguru3.c
drivers/hwmon/ads1015.c [new file with mode: 0644]
drivers/hwmon/hp_accel.c [deleted file]
drivers/hwmon/lis3lv02d.c [deleted file]
drivers/hwmon/lis3lv02d.h [deleted file]
drivers/hwmon/lis3lv02d_i2c.c [deleted file]
drivers/hwmon/lis3lv02d_spi.c [deleted file]
drivers/hwmon/lm75.c
drivers/hwmon/sch5627.c [new file with mode: 0644]
drivers/hwmon/sht15.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-i801.c
drivers/i2c/i2c-boardinfo.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Makefile
drivers/ieee802154/Makefile
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/evdev.c
drivers/input/input-polldev.c
drivers/input/input.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/max7359_keypad.c
drivers/input/keyboard/mcs_touchkey.c
drivers/input/keyboard/omap4-keypad.c
drivers/input/keyboard/qt1070.c [new file with mode: 0644]
drivers/input/keyboard/tc3589x-keypad.c
drivers/input/keyboard/tca6416-keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/ad714x-spi.c
drivers/input/misc/adxl34x-i2c.c
drivers/input/misc/adxl34x-spi.c
drivers/input/misc/ati_remote2.c
drivers/input/misc/uinput.c
drivers/input/misc/xen-kbdfront.c [new file with mode: 0644]
drivers/input/mouse/bcm5974.c
drivers/input/mouse/synaptics_i2c.c
drivers/input/sparse-keymap.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ad7879-spi.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel_mxt_ts.c [new file with mode: 0644]
drivers/input/touchscreen/qt602240_ts.c [deleted file]
drivers/input/touchscreen/tsc2005.c [new file with mode: 0644]
drivers/input/touchscreen/wm831x-ts.c [new file with mode: 0644]
drivers/input/xen-kbdfront.c [deleted file]
drivers/isdn/hisax/Makefile
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/rc/rc-main.c
drivers/memstick/Makefile
drivers/memstick/core/Makefile
drivers/memstick/host/Makefile
drivers/message/fusion/Makefile
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/cb710/Makefile
drivers/misc/lis3lv02d/Kconfig [new file with mode: 0644]
drivers/misc/lis3lv02d/Makefile [new file with mode: 0644]
drivers/misc/lis3lv02d/lis3lv02d.c [new file with mode: 0644]
drivers/misc/lis3lv02d/lis3lv02d.h [new file with mode: 0644]
drivers/misc/lis3lv02d/lis3lv02d_i2c.c [new file with mode: 0644]
drivers/misc/lis3lv02d/lis3lv02d_spi.c [new file with mode: 0644]
drivers/misc/sgi-gru/Makefile
drivers/mmc/card/Kconfig
drivers/mmc/card/block.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/Makefile
drivers/mmc/core/core.c
drivers/mmc/core/core.h
drivers/mmc/core/host.c
drivers/mmc/core/mmc.c
drivers/mmc/core/quirks.c [new file with mode: 0644]
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/cb710-mmc.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/msm_sdcc.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c [new file with mode: 0644]
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-s3c.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/via-sdmmc.c
drivers/net/caif/Makefile
drivers/net/skfp/Makefile
drivers/net/wan/lmc/Makefile
drivers/net/wireless/hostap/hostap_config.h
drivers/net/wireless/zd1211rw/Makefile
drivers/parisc/dino.c
drivers/parisc/eisa.c
drivers/parisc/gsc.c
drivers/parisc/iosapic.c
drivers/parisc/superio.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/hp_accel.c [new file with mode: 0644]
drivers/pps/clients/Makefile
drivers/rapidio/Makefile
drivers/rapidio/switches/Makefile
drivers/rtc/Makefile
drivers/scsi/aacraid/Makefile
drivers/scsi/aic94xx/Makefile
drivers/scsi/libsas/Makefile
drivers/scsi/lpfc/Makefile
drivers/scsi/mvsas/Makefile
drivers/scsi/pcmcia/Makefile
drivers/scsi/scsi_error.c
drivers/usb/core/driver.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/video/intelfb/Makefile
drivers/video/matrox/matroxfb_base.c
fs/affs/Makefile
fs/bfs/dir.c
fs/coda/Makefile
fs/compat.c
fs/devpts/inode.c
fs/exec.c
fs/fifo.c
fs/gfs2/Makefile
fs/inode.c
fs/internal.h
fs/ioctl.c
fs/jfs/Makefile
fs/ncpfs/Makefile
fs/nfs/namespace.c
fs/nilfs2/alloc.c
fs/nilfs2/bmap.c
fs/nilfs2/bmap.h
fs/nilfs2/btree.c
fs/nilfs2/dir.c
fs/nilfs2/direct.c
fs/nilfs2/file.c
fs/nilfs2/inode.c
fs/nilfs2/ioctl.c
fs/nilfs2/mdt.h
fs/nilfs2/namei.c
fs/nilfs2/nilfs.h
fs/nilfs2/recovery.c
fs/nilfs2/sb.h [deleted file]
fs/nilfs2/segment.c
fs/nilfs2/segment.h
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c
fs/nilfs2/the_nilfs.h
fs/ntfs/Makefile
fs/ocfs2/Makefile
fs/ocfs2/dlm/Makefile
fs/ocfs2/dlmfs/Makefile
fs/open.c
fs/pstore/inode.c
fs/pstore/internal.h
fs/pstore/platform.c
fs/reiserfs/Makefile
fs/select.c
fs/sync.c
fs/xfs/Makefile
fs/xfs/linux-2.6/kmem.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_message.c [new file with mode: 0644]
fs/xfs/linux-2.6/xfs_message.h [new file with mode: 0644]
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_sysctl.c
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_dquot_item.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_bhv.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/support/debug.c [deleted file]
fs/xfs/support/debug.h [deleted file]
fs/xfs/xfs_alloc.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_quota.h
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.h
fs/xfs/xfs_rw.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_ail.c
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_trans_inode.c
fs/xfs/xfs_vnodeops.c
include/asm-generic/unistd.h
include/linux/dcache.h
include/linux/firewire.h
include/linux/i2c-id.h [deleted file]
include/linux/i2c.h
include/linux/i2c/ads1015.h [new file with mode: 0644]
include/linux/i2c/atmel_mxt_ts.h [new file with mode: 0644]
include/linux/i2c/mcs.h
include/linux/i2c/qt602240_ts.h [deleted file]
include/linux/input-polldev.h
include/linux/input.h
include/linux/magic.h
include/linux/mfd/wm831x/pdata.h
include/linux/mmc/card.h
include/linux/mmc/core.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/mmc.h
include/linux/nilfs2_fs.h
include/linux/spi/tsc2005.h [new file with mode: 0644]
include/linux/syscalls.h
kernel/gcov/Makefile
kernel/power/Makefile
kernel/signal.c
lib/Kconfig.debug
scripts/Makefile
scripts/Makefile.build
scripts/extract-ikconfig
scripts/genksyms/Makefile
scripts/genksyms/genksyms.c
scripts/genksyms/genksyms.h
scripts/genksyms/lex.c_shipped
scripts/genksyms/lex.l
scripts/genksyms/parse.c_shipped
scripts/genksyms/parse.h_shipped
scripts/genksyms/parse.y
scripts/mod/modpost.c
scripts/package/Makefile
scripts/package/buildtar
scripts/setlocalversion
scripts/tags.sh
scripts/unifdef.c
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf

index f1fb2a004264bc6989a20d92ca333b436c7154d4..ddf451ee2a08812eb16a28f3264618ca2e1e749b 100644 (file)
@@ -1,6 +1,6 @@
 Where:         /dev/pstore/...
-Date:          January 2011
-Kernel Version: 2.6.38
+Date:          March 2011
+Kernel Version: 2.6.39
 Contact:       tony.luck@intel.com
 Description:   Generic interface to platform dependent persistent storage.
 
@@ -11,7 +11,7 @@ Description:  Generic interface to platform dependent persistent storage.
                of the console log is captured, but other interesting
                data can also be saved.
 
-               # mount -t pstore - /dev/pstore
+               # mount -t pstore -o kmsg_bytes=8000 - /dev/pstore
 
                $ ls -l /dev/pstore
                total 0
@@ -33,3 +33,9 @@ Description:  Generic interface to platform dependent persistent storage.
                will be saved elsewhere and erased from persistent store
                soon after boot to free up space ready for the next
                catastrophe.
+
+               The 'kmsg_bytes' mount option changes the target amount of
+               data saved on each oops/panic. Pstore saves (possibly
+               multiple) files based on the record size of the underlying
+               persistent storage until at least this amount is reached.
+               Default is 10 Kbytes.
diff --git a/Documentation/ABI/testing/sysfs-devices-mmc b/Documentation/ABI/testing/sysfs-devices-mmc
new file mode 100644 (file)
index 0000000..5a50ab6
--- /dev/null
@@ -0,0 +1,21 @@
+What:          /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset
+Date:          January 2011
+Contact:       Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+               Enhanced area is a new feature defined in eMMC4.4 standard.
+               eMMC4.4 or later card can support such feature. This kind of
+               area can help to improve the card performance. If the feature
+               is enabled, this attribute will indicate the start address of
+               enhanced data area. If not, this attribute will be -EINVAL.
+               Unit Byte. Format decimal.
+
+What:          /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size
+Date:          January 2011
+Contact:       Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+               Enhanced area is a new feature defined in eMMC4.4 standard.
+               eMMC4.4 or later card can support such feature. This kind of
+               area can help to improve the card performance. If the feature
+               is enabled, this attribute will indicate the size of enhanced
+               data area. If not, this attribute will be -EINVAL.
+               Unit KByte. Format decimal.
diff --git a/Documentation/ABI/testing/sysfs-fs-pstore b/Documentation/ABI/testing/sysfs-fs-pstore
deleted file mode 100644 (file)
index 8e659d8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-What:          /sys/fs/pstore/kmsg_bytes
-Date:          January 2011
-Kernel Version: 2.6.38
-Contact:       "Tony Luck" <tony.luck@intel.com>
-Description:
-               Controls amount of console log that will be saved
-               to persistent store on oops/panic.
diff --git a/Documentation/devicetree/bindings/hwmon/ads1015.txt b/Documentation/devicetree/bindings/hwmon/ads1015.txt
new file mode 100644 (file)
index 0000000..918a507
--- /dev/null
@@ -0,0 +1,73 @@
+ADS1015 (I2C)
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+For configuration all possible combinations are mapped to 8 channels:
+  0: Voltage over AIN0 and AIN1.
+  1: Voltage over AIN0 and AIN3.
+  2: Voltage over AIN1 and AIN3.
+  3: Voltage over AIN2 and AIN3.
+  4: Voltage over AIN0 and GND.
+  5: Voltage over AIN1 and GND.
+  6: Voltage over AIN2 and GND.
+  7: Voltage over AIN3 and GND.
+
+Each channel can be configured individually:
+ - pga is the programmable gain amplifier (values are full scale)
+    0: +/- 6.144 V
+    1: +/- 4.096 V
+    2: +/- 2.048 V (default)
+    3: +/- 1.024 V
+    4: +/- 0.512 V
+    5: +/- 0.256 V
+ - data_rate in samples per second
+    0: 128
+    1: 250
+    2: 490
+    3: 920
+    4: 1600 (default)
+    5: 2400
+    6: 3300
+
+1) The /ads1015 node
+
+  Required properties:
+
+   - compatible : must be "ti,ads1015"
+   - reg : I2C bus address of the device
+   - #address-cells : must be <1>
+   - #size-cells : must be <0>
+
+  The node contains child nodes for each channel that the platform uses.
+
+  Example ADS1015 node:
+
+    ads1015@49 {
+           compatible = "ti,ads1015";
+           reg = <0x49>;
+           #address-cells = <1>;
+           #size-cells = <0>;
+
+           [ child node definitions... ]
+    }
+
+2) channel nodes
+
+  Required properties:
+
+   - reg : the channel number
+
+  Optional properties:
+
+   - ti,gain : the programmable gain amplifier setting
+   - ti,datarate : the converter data rate
+
+  Example ADS1015 channel node:
+
+    channel@4 {
+           reg = <4>;
+           ti,gain = <3>;
+           ti,datarate = <5>;
+    };
diff --git a/Documentation/devicetree/bindings/open-pic.txt b/Documentation/devicetree/bindings/open-pic.txt
new file mode 100644 (file)
index 0000000..909a902
--- /dev/null
@@ -0,0 +1,98 @@
+* Open PIC Binding
+
+This binding specifies what properties must be available in the device tree
+representation of an Open PIC compliant interrupt controller.  This binding is
+based on the binding defined for Open PIC in [1] and is a superset of that
+binding.
+
+Required properties:
+
+  NOTE: Many of these descriptions were paraphrased here from [1] to aid
+        readability.
+
+    - compatible: Specifies the compatibility list for the PIC.  The type
+      shall be <string> and the value shall include "open-pic".
+
+    - reg: Specifies the base physical address(s) and size(s) of this
+      PIC's addressable register space.  The type shall be <prop-encoded-array>.
+
+    - interrupt-controller: The presence of this property identifies the node
+      as an Open PIC.  No property value shall be defined.
+
+    - #interrupt-cells: Specifies the number of cells needed to encode an
+      interrupt source.  The type shall be a <u32> and the value shall be 2.
+
+    - #address-cells: Specifies the number of cells needed to encode an
+      address.  The type shall be <u32> and the value shall be 0.  As such,
+      'interrupt-map' nodes do not have to specify a parent unit address.
+
+Optional properties:
+
+    - pic-no-reset: The presence of this property indicates that the PIC
+      shall not be reset during runtime initialization.  No property value shall
+      be defined.  The presence of this property also mandates that any
+      initialization related to interrupt sources shall be limited to sources
+      explicitly referenced in the device tree.
+
+* Interrupt Specifier Definition
+
+  Interrupt specifiers consists of 2 cells encoded as
+  follows:
+
+    - <1st-cell>: The interrupt-number that identifies the interrupt source.
+
+    - <2nd-cell>: The level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+* Examples
+
+Example 1:
+
+       /*
+        * An Open PIC interrupt controller
+        */
+       mpic: pic@40000 {
+               // This is an interrupt controller node.
+               interrupt-controller;
+
+               // No address cells so that 'interrupt-map' nodes which reference
+               // this Open PIC node do not need a parent address specifier.
+               #address-cells = <0>;
+
+               // Two cells to encode interrupt sources.
+               #interrupt-cells = <2>;
+
+               // Offset address of 0x40000 and size of 0x40000.
+               reg = <0x40000 0x40000>;
+
+               // Compatible with Open PIC.
+               compatible = "open-pic";
+
+               // The PIC shall not be reset.
+               pic-no-reset;
+       };
+
+Example 2:
+
+       /*
+        * An interrupt generating device that is wired to an Open PIC.
+        */
+       serial0: serial@4500 {
+               // Interrupt source '42' that is active high level-sensitive.
+               // Note that there are only two cells as specified in the interrupt
+               // parent's '#interrupt-cells' property.
+               interrupts = <42 2>;
+
+               // The interrupt controller that this device is wired to.
+               interrupt-parent = <&mpic>;
+       };
+
+* References
+
+[1] Power.org (TM) Standard for Embedded Power Architecture (TM) Platform
+    Requirements (ePAPR), Version 1.0, July 2008.
+    (http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf)
+
index f487c6918d7870c57bec4202cf22482af21b3d6f..895330940f5dfb1560f78dce424dca686d312bf3 100644 (file)
@@ -585,16 +585,6 @@ Who:    NeilBrown <neilb@suse.de>
 
 ----------------------------
 
-What:  i2c_adapter.id
-When:  June 2011
-Why:   This field is deprecated. I2C device drivers shouldn't change their
-       behavior based on the underlying I2C adapter. Instead, the I2C
-       adapter driver should instantiate the I2C devices and provide the
-       needed platform-specific information.
-Who:   Jean Delvare <khali@linux-fr.org>
-
-----------------------------
-
 What:  cancel_rearming_delayed_work[queue]()
 When:  2.6.39
 
@@ -645,3 +635,12 @@ Who:       Florian Westphal <fw@strlen.de>
 Files: include/linux/netfilter_ipv4/ipt_addrtype.h
 
 ----------------------------
+
+What:  i2c_driver.attach_adapter
+       i2c_driver.detach_adapter
+When:  September 2011
+Why:   These legacy callbacks should no longer be used as i2c-core offers
+       a variety of preferable alternative ways to instantiate I2C devices.
+Who:   Jean Delvare <khali@linux-fr.org>
+
+----------------------------
index 7445bf335dae7eeba4bd6640a82fa3987f48d2cc..5282e3e5141310ac1b73c3dd28d192d020932d97 100644 (file)
@@ -791,10 +791,3 @@ mount option. Fundamentally, there is no reason why the log manager would not
 be able to swap methods automatically and transparently depending on load
 characteristics, but this should not be necessary if delayed logging works as
 designed.
-
-Roadmap:
-
-2.6.39 Switch default mount option to use delayed logging
-       => should be roughly 12 months after initial merge
-       => enough time to shake out remaining problems before next round of
-          enterprise distro kernel rebases
diff --git a/Documentation/hwmon/ads1015 b/Documentation/hwmon/ads1015
new file mode 100644 (file)
index 0000000..f6fe9c2
--- /dev/null
@@ -0,0 +1,72 @@
+Kernel driver ads1015
+=====================
+
+Supported chips:
+  * Texas Instruments ADS1015
+    Prefix: 'ads1015'
+    Datasheet: Publicly available at the Texas Instruments website :
+               http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+
+Authors:
+        Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments ADS1015.
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+The inputs can be made available by 8 sysfs input files in0_input - in7_input:
+in0: Voltage over AIN0 and AIN1.
+in1: Voltage over AIN0 and AIN3.
+in2: Voltage over AIN1 and AIN3.
+in3: Voltage over AIN2 and AIN3.
+in4: Voltage over AIN0 and GND.
+in5: Voltage over AIN1 and GND.
+in6: Voltage over AIN2 and GND.
+in7: Voltage over AIN3 and GND.
+
+Which inputs are available can be configured using platform data or devicetree.
+
+By default all inputs are exported.
+
+Platform Data
+-------------
+
+In linux/i2c/ads1015.h platform data is defined, channel_data contains
+configuration data for the used input combinations:
+- pga is the programmable gain amplifier (values are full scale)
+  0: +/- 6.144 V
+  1: +/- 4.096 V
+  2: +/- 2.048 V
+  3: +/- 1.024 V
+  4: +/- 0.512 V
+  5: +/- 0.256 V
+- data_rate in samples per second
+  0: 128
+  1: 250
+  2: 490
+  3: 920
+  4: 1600
+  5: 2400
+  6: 3300
+
+Example:
+struct ads1015_platform_data data = {
+       .channel_data = {
+               [2] = { .enabled = true, .pga = 1, .data_rate = 0 },
+               [4] = { .enabled = true, .pga = 4, .data_rate = 5 },
+       }
+};
+
+In this case only in2_input (FS +/- 4.096 V, 128 SPS) and in4_input
+(FS +/- 0.512 V, 2400 SPS) would be created.
+
+Devicetree
+----------
+
+Configuration is also possible via devicetree:
+Documentation/devicetree/bindings/hwmon/ads1015.txt
diff --git a/Documentation/hwmon/hpfall.c b/Documentation/hwmon/hpfall.c
deleted file mode 100644 (file)
index a4a8fc5..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Disk protection for HP machines.
- *
- * Copyright 2008 Eric Piel
- * Copyright 2009 Pavel Machek <pavel@ucw.cz>
- *
- * GPLv2.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sched.h>
-
-char unload_heads_path[64];
-
-int set_unload_heads_path(char *device)
-{
-       char devname[64];
-
-       if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
-               return -EINVAL;
-       strncpy(devname, device + 5, sizeof(devname));
-
-       snprintf(unload_heads_path, sizeof(unload_heads_path),
-                               "/sys/block/%s/device/unload_heads", devname);
-       return 0;
-}
-int valid_disk(void)
-{
-       int fd = open(unload_heads_path, O_RDONLY);
-       if (fd < 0) {
-               perror(unload_heads_path);
-               return 0;
-       }
-
-       close(fd);
-       return 1;
-}
-
-void write_int(char *path, int i)
-{
-       char buf[1024];
-       int fd = open(path, O_RDWR);
-       if (fd < 0) {
-               perror("open");
-               exit(1);
-       }
-       sprintf(buf, "%d", i);
-       if (write(fd, buf, strlen(buf)) != strlen(buf)) {
-               perror("write");
-               exit(1);
-       }
-       close(fd);
-}
-
-void set_led(int on)
-{
-       write_int("/sys/class/leds/hp::hddprotect/brightness", on);
-}
-
-void protect(int seconds)
-{
-       write_int(unload_heads_path, seconds*1000);
-}
-
-int on_ac(void)
-{
-//     /sys/class/power_supply/AC0/online
-}
-
-int lid_open(void)
-{
-//     /proc/acpi/button/lid/LID/state
-}
-
-void ignore_me(void)
-{
-       protect(0);
-       set_led(0);
-}
-
-int main(int argc, char **argv)
-{
-       int fd, ret;
-       struct sched_param param;
-
-       if (argc == 1)
-               ret = set_unload_heads_path("/dev/sda");
-       else if (argc == 2)
-               ret = set_unload_heads_path(argv[1]);
-       else
-               ret = -EINVAL;
-
-       if (ret || !valid_disk()) {
-               fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
-                               argv[0]);
-               exit(1);
-       }
-
-       fd = open("/dev/freefall", O_RDONLY);
-       if (fd < 0) {
-               perror("/dev/freefall");
-               return EXIT_FAILURE;
-       }
-
-       daemon(0, 0);
-       param.sched_priority = sched_get_priority_max(SCHED_FIFO);
-       sched_setscheduler(0, SCHED_FIFO, &param);
-       mlockall(MCL_CURRENT|MCL_FUTURE);
-
-       signal(SIGALRM, ignore_me);
-
-       for (;;) {
-               unsigned char count;
-
-               ret = read(fd, &count, sizeof(count));
-               alarm(0);
-               if ((ret == -1) && (errno == EINTR)) {
-                       /* Alarm expired, time to unpark the heads */
-                       continue;
-               }
-
-               if (ret != sizeof(count)) {
-                       perror("read");
-                       break;
-               }
-
-               protect(21);
-               set_led(1);
-               if (1 || on_ac() || lid_open())
-                       alarm(2);
-               else
-                       alarm(20);
-       }
-
-       close(fd);
-       return EXIT_SUCCESS;
-}
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d
deleted file mode 100644 (file)
index 06534f2..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-Kernel driver lis3lv02d
-=======================
-
-Supported chips:
-
-  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
-  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
-
-Authors:
-        Yan Burman <burman.yan@gmail.com>
-       Eric Piel <eric.piel@tremplin-utc.net>
-
-
-Description
------------
-
-This driver provides support for the accelerometer found in various HP laptops
-sporting the feature officially called "HP Mobile Data Protection System 3D" or
-"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
-models (full list can be found in drivers/hwmon/hp_accel.c) will have their
-axis automatically oriented on standard way (eg: you can directly play
-neverball). The accelerometer data is readable via
-/sys/devices/platform/lis3lv02d. Reported values are scaled
-to mg values (1/1000th of earth gravity).
-
-Sysfs attributes under /sys/devices/platform/lis3lv02d/:
-position - 3D position that the accelerometer reports. Format: "(x,y,z)"
-rate - read reports the sampling rate of the accelerometer device in HZ.
-       write changes sampling rate of the accelerometer device.
-       Only values which are supported by HW are accepted.
-selftest - performs selftest for the chip as specified by chip manufacturer.
-
-This driver also provides an absolute input class device, allowing
-the laptop to act as a pinball machine-esque joystick. Joystick device can be
-calibrated. Joystick device can be in two different modes.
-By default output values are scaled between -32768 .. 32767. In joystick raw
-mode, joystick and sysfs position entry have the same scale. There can be
-small difference due to input system fuzziness feature.
-Events are also available as input event device.
-
-Selftest is meant only for hardware diagnostic purposes. It is not meant to be
-used during normal operations. Position data is not corrupted during selftest
-but interrupt behaviour is not guaranteed to work reliably. In test mode, the
-sensing element is internally moved little bit. Selftest measures difference
-between normal mode and test mode. Chip specifications tell the acceptance
-limit for each type of the chip. Limits are provided via platform data
-to allow adjustment of the limits without a change to the actual driver.
-Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
-measured difference between modes. Axes are not remapped in selftest mode.
-Measurement values are provided to help HW diagnostic applications to make
-final decision.
-
-On HP laptops, if the led infrastructure is activated, support for a led
-indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
-
-Another feature of the driver is misc device called "freefall" that
-acts similar to /dev/rtc and reacts on free-fall interrupts received
-from the device. It supports blocking operations, poll/select and
-fasync operation modes. You must read 1 bytes from the device.  The
-result is number of free-fall interrupts since the last successful
-read (or 255 if number of interrupts would not fit). See the hpfall.c
-file for an example on using the device.
-
-
-Axes orientation
-----------------
-
-For better compatibility between the various laptops. The values reported by
-the accelerometer are converted into a "standard" organisation of the axes
-(aka "can play neverball out of the box"):
- * When the laptop is horizontal the position reported is about 0 for X and Y
-       and a positive value for Z
- * If the left side is elevated, X increases (becomes positive)
- * If the front side (where the touchpad is) is elevated, Y decreases
-       (becomes negative)
- * If the laptop is put upside-down, Z becomes negative
-
-If your laptop model is not recognized (cf "dmesg"), you can send an
-email to the maintainer to add it to the database.  When reporting a new
-laptop, please include the output of "dmidecode" plus the value of
-/sys/devices/platform/lis3lv02d/position in these four cases.
-
-Q&A
----
-
-Q: How do I safely simulate freefall? I have an HP "portable
-workstation" which has about 3.5kg and a plastic case, so letting it
-fall to the ground is out of question...
-
-A: The sensor is pretty sensitive, so your hands can do it. Lift it
-into free space, follow the fall with your hands for like 10
-centimeters. That should be enough to trigger the detection.
index 8e6356fe05d78bbea5cdaf41e2def9b2f5aaf5a4..a1790401fddee6bed131867878257b2004a91989 100644 (file)
@@ -7,6 +7,11 @@ Supported chips:
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
+  * National Semiconductor LM75A
+    Prefix: 'lm75a'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
   * Dallas Semiconductor DS75
     Prefix: 'lm75'
     Addresses scanned: I2C 0x48 - 0x4f
diff --git a/Documentation/hwmon/sch5627 b/Documentation/hwmon/sch5627
new file mode 100644 (file)
index 0000000..446a054
--- /dev/null
@@ -0,0 +1,22 @@
+Kernel driver sch5627
+=====================
+
+Supported chips:
+  * SMSC SCH5627
+    Prefix: 'sch5627'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Application Note available upon request
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+SMSC SCH5627 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 5 voltages, 4 fans and 8 temperatures.
+
+The hardware monitoring part of the SMSC SCH5627 is accessed by talking
+through an embedded microcontroller. An application note describing the
+protocol for communicating with the microcontroller is available upon
+request. Please mail me if you want a copy.
diff --git a/Documentation/hwmon/w83795 b/Documentation/hwmon/w83795
new file mode 100644 (file)
index 0000000..9f16037
--- /dev/null
@@ -0,0 +1,127 @@
+Kernel driver w83795
+====================
+
+Supported chips:
+  * Winbond/Nuvoton W83795G
+    Prefix: 'w83795g'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+  * Winbond/Nuvoton W83795ADG
+    Prefix: 'w83795adg'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+
+Authors:
+    Wei Song (Nuvoton)
+    Jean Delvare <khali@linux-fr.org>
+
+
+Pin mapping
+-----------
+
+Here is a summary of the pin mapping for the W83795G and W83795ADG.
+This can be useful to convert data provided by board manufacturers
+into working libsensors configuration statements.
+
+    W83795G                    |
+  Pin  | Name                  | Register      | Sysfs attribute
+------------------------------------------------------------------
+   13  | VSEN1 (VCORE1)        | 10h           | in0
+   14  | VSEN2 (VCORE2)        | 11h           | in1
+   15  | VSEN3 (VCORE3)        | 12h           | in2
+   16  | VSEN4                 | 13h           | in3
+   17  | VSEN5                 | 14h           | in4
+   18  | VSEN6                 | 15h           | in5
+   19  | VSEN7                 | 16h           | in6
+   20  | VSEN8                 | 17h           | in7
+   21  | VSEN9                 | 18h           | in8
+   22  | VSEN10                | 19h           | in9
+   23  | VSEN11                | 1Ah           | in10
+   28  | VTT                   | 1Bh           | in11
+   24  | 3VDD                  | 1Ch           | in12
+   25  | 3VSB                  | 1Dh           | in13
+   26  | VBAT                  | 1Eh           | in14
+    3  | VSEN12/TR5            | 1Fh           | in15/temp5
+    4  | VSEN13/TR5            | 20h           | in16/temp6
+  5/  6        | VDSEN14/TR1/TD1       | 21h           | in17/temp1
+  7/  8        | VDSEN15/TR2/TD2       | 22h           | in18/temp2
+  9/ 10        | VDSEN16/TR3/TD3       | 23h           | in19/temp3
+ 11/ 12        | VDSEN17/TR4/TD4       | 24h           | in20/temp4
+   40  | FANIN1                | 2Eh           | fan1
+   42  | FANIN2                | 2Fh           | fan2
+   44  | FANIN3                | 30h           | fan3
+   46  | FANIN4                | 31h           | fan4
+   48  | FANIN5                | 32h           | fan5
+   50  | FANIN6                | 33h           | fan6
+   52  | FANIN7                | 34h           | fan7
+   54  | FANIN8                | 35h           | fan8
+   57  | FANIN9                | 36h           | fan9
+   58  | FANIN10               | 37h           | fan10
+   59  | FANIN11               | 38h           | fan11
+   60  | FANIN12               | 39h           | fan12
+   31  | FANIN13               | 3Ah           | fan13
+   35  | FANIN14               | 3Bh           | fan14
+   41  | FANCTL1               | 10h (bank 2)  | pwm1
+   43  | FANCTL2               | 11h (bank 2)  | pwm2
+   45  | FANCTL3               | 12h (bank 2)  | pwm3
+   47  | FANCTL4               | 13h (bank 2)  | pwm4
+   49  | FANCTL5               | 14h (bank 2)  | pwm5
+   51  | FANCTL6               | 15h (bank 2)  | pwm6
+   53  | FANCTL7               | 16h (bank 2)  | pwm7
+   55  | FANCTL8               | 17h (bank 2)  | pwm8
+ 29/ 30        | PECI/TSI (DTS1)       | 26h           | temp7
+ 29/ 30        | PECI/TSI (DTS2)       | 27h           | temp8
+ 29/ 30        | PECI/TSI (DTS3)       | 28h           | temp9
+ 29/ 30        | PECI/TSI (DTS4)       | 29h           | temp10
+ 29/ 30        | PECI/TSI (DTS5)       | 2Ah           | temp11
+ 29/ 30        | PECI/TSI (DTS6)       | 2Bh           | temp12
+ 29/ 30        | PECI/TSI (DTS7)       | 2Ch           | temp13
+ 29/ 30        | PECI/TSI (DTS8)       | 2Dh           | temp14
+   27  | CASEOPEN#             | 46h           | intrusion0
+
+    W83795ADG                  |
+  Pin  | Name                  | Register      | Sysfs attribute
+------------------------------------------------------------------
+   10  | VSEN1 (VCORE1)        | 10h           | in0
+   11  | VSEN2 (VCORE2)        | 11h           | in1
+   12  | VSEN3 (VCORE3)        | 12h           | in2
+   13  | VSEN4                 | 13h           | in3
+   14  | VSEN5                 | 14h           | in4
+   15  | VSEN6                 | 15h           | in5
+   16  | VSEN7                 | 16h           | in6
+   17  | VSEN8                 | 17h           | in7
+   22  | VTT                   | 1Bh           | in11
+   18  | 3VDD                  | 1Ch           | in12
+   19  | 3VSB                  | 1Dh           | in13
+   20  | VBAT                  | 1Eh           | in14
+   48  | VSEN12/TR5            | 1Fh           | in15/temp5
+    1  | VSEN13/TR5            | 20h           | in16/temp6
+  2/  3        | VDSEN14/TR1/TD1       | 21h           | in17/temp1
+  4/  5        | VDSEN15/TR2/TD2       | 22h           | in18/temp2
+  6/  7        | VDSEN16/TR3/TD3       | 23h           | in19/temp3
+  8/  9        | VDSEN17/TR4/TD4       | 24h           | in20/temp4
+   32  | FANIN1                | 2Eh           | fan1
+   34  | FANIN2                | 2Fh           | fan2
+   36  | FANIN3                | 30h           | fan3
+   37  | FANIN4                | 31h           | fan4
+   38  | FANIN5                | 32h           | fan5
+   39  | FANIN6                | 33h           | fan6
+   40  | FANIN7                | 34h           | fan7
+   41  | FANIN8                | 35h           | fan8
+   43  | FANIN9                | 36h           | fan9
+   44  | FANIN10               | 37h           | fan10
+   45  | FANIN11               | 38h           | fan11
+   46  | FANIN12               | 39h           | fan12
+   24  | FANIN13               | 3Ah           | fan13
+   28  | FANIN14               | 3Bh           | fan14
+   33  | FANCTL1               | 10h (bank 2)  | pwm1
+   35  | FANCTL2               | 11h (bank 2)  | pwm2
+   23  | PECI (DTS1)           | 26h           | temp7
+   23  | PECI (DTS2)           | 27h           | temp8
+   23  | PECI (DTS3)           | 28h           | temp9
+   23  | PECI (DTS4)           | 29h           | temp10
+   23  | PECI (DTS5)           | 2Ah           | temp11
+   23  | PECI (DTS6)           | 2Bh           | temp12
+   23  | PECI (DTS7)           | 2Ch           | temp13
+   23  | PECI (DTS8)           | 2Dh           | temp14
+   21  | CASEOPEN#             | 46h           | intrusion0
index 93fe76e56522a199a0ab5044544673418be64ec0..6df69765ccb75045615dec13c3b564c550d18021 100644 (file)
@@ -16,8 +16,9 @@ Supported adapters:
   * Intel EP80579 (Tolapai)
   * Intel 82801JI (ICH10)
   * Intel 5/3400 Series (PCH)
-  * Intel Cougar Point (PCH)
+  * Intel 6 Series (PCH)
   * Intel Patsburg (PCH)
+  * Intel DH89xxCC (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index 87da405a85979d9cf925fc711590f5d0deef9b7c..9edb75d8c9b94cdc5d7d50241499892bca42243b 100644 (file)
@@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
        (...)
        i2c_adap = i2c_get_adapter(2);
        memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-       strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+       strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
        isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
                                                   normal_i2c, NULL);
        i2c_put_adapter(i2c_adap);
index 9a45f9bb6a255d421bd2903e69120c0a8e281017..d6991625c407d41102f25a008c4f4801396ec1b7 100644 (file)
@@ -61,7 +61,7 @@ static int example_attach(struct i2c_adapter *adap, int addr, int kind)
        return 0;
 }
 
-static int __devexit example_detach(struct i2c_client *client)
+static int example_detach(struct i2c_client *client)
 {
        struct example_state *state = i2c_get_clientdata(client);
 
@@ -81,7 +81,7 @@ static struct i2c_driver example_driver = {
                .name           = "example",
        },
        .attach_adapter = example_attach_adapter,
-       .detach_client  = __devexit_p(example_detach),
+       .detach_client  = example_detach,
        .suspend        = example_suspend,
        .resume         = example_resume,
 };
@@ -93,7 +93,7 @@ Updating the client
 The new style binding model will check against a list of supported
 devices and their associated address supplied by the code registering
 the busses. This means that the driver .attach_adapter and
-.detach_adapter methods can be removed, along with the addr_data,
+.detach_client methods can be removed, along with the addr_data,
 as follows:
 
 - static struct i2c_driver example_driver;
@@ -110,14 +110,14 @@ as follows:
 
  static struct i2c_driver example_driver = {
 -      .attach_adapter = example_attach_adapter,
--      .detach_client  = __devexit_p(example_detach),
+-      .detach_client  = example_detach,
  }
 
 Add the probe and remove methods to the i2c_driver, as so:
 
  static struct i2c_driver example_driver = {
 +      .probe          = example_probe,
-+      .remove         = __devexit_p(example_remove),
++      .remove         = example_remove,
  }
 
 Change the example_attach method to accept the new parameters
@@ -199,8 +199,8 @@ to delete the i2c_detach_client call. It is possible that you
 can also remove the ret variable as it is not not needed for
 any of the core functions.
 
-- static int __devexit example_detach(struct i2c_client *client)
-+ static int __devexit example_remove(struct i2c_client *client)
+- static int example_detach(struct i2c_client *client)
++ static int example_remove(struct i2c_client *client)
 {
        struct example_state *state = i2c_get_clientdata(client);
 
@@ -253,7 +253,7 @@ static int example_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit example_remove(struct i2c_client *client)
+static int example_remove(struct i2c_client *client)
 {
        struct example_state *state = i2c_get_clientdata(client);
 
@@ -275,7 +275,7 @@ static struct i2c_driver example_driver = {
        },
        .id_table       = example_idtable,
        .probe          = example_probe,
-       .remove         = __devexit_p(example_remove),
+       .remove         = example_remove,
        .suspend        = example_suspend,
        .resume         = example_resume,
 };
index 8f63b224ab0969a758e5347d055777f1601d0b4c..f1431d099fce31371aa74f63efed4f7ce5f9b64b 100644 (file)
@@ -196,3 +196,8 @@ to be included in the databases, separated by blank space. E.g.:
 To get all available archs you can also specify all. E.g.:
 
     $ make ALLSOURCE_ARCHS=all tags
+
+KBUILD_ENABLE_EXTRA_GCC_CHECKS
+--------------------------------------------------
+If enabled over the make command line with "W=1", it turns on additional
+gcc -W... options for more extensive build-time checking.
diff --git a/Documentation/laptops/hpfall.c b/Documentation/laptops/hpfall.c
new file mode 100644 (file)
index 0000000..a4a8fc5
--- /dev/null
@@ -0,0 +1,146 @@
+/* Disk protection for HP machines.
+ *
+ * Copyright 2008 Eric Piel
+ * Copyright 2009 Pavel Machek <pavel@ucw.cz>
+ *
+ * GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sched.h>
+
+char unload_heads_path[64];
+
+int set_unload_heads_path(char *device)
+{
+       char devname[64];
+
+       if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
+               return -EINVAL;
+       strncpy(devname, device + 5, sizeof(devname));
+
+       snprintf(unload_heads_path, sizeof(unload_heads_path),
+                               "/sys/block/%s/device/unload_heads", devname);
+       return 0;
+}
+int valid_disk(void)
+{
+       int fd = open(unload_heads_path, O_RDONLY);
+       if (fd < 0) {
+               perror(unload_heads_path);
+               return 0;
+       }
+
+       close(fd);
+       return 1;
+}
+
+void write_int(char *path, int i)
+{
+       char buf[1024];
+       int fd = open(path, O_RDWR);
+       if (fd < 0) {
+               perror("open");
+               exit(1);
+       }
+       sprintf(buf, "%d", i);
+       if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+               perror("write");
+               exit(1);
+       }
+       close(fd);
+}
+
+void set_led(int on)
+{
+       write_int("/sys/class/leds/hp::hddprotect/brightness", on);
+}
+
+void protect(int seconds)
+{
+       write_int(unload_heads_path, seconds*1000);
+}
+
+int on_ac(void)
+{
+//     /sys/class/power_supply/AC0/online
+}
+
+int lid_open(void)
+{
+//     /proc/acpi/button/lid/LID/state
+}
+
+void ignore_me(void)
+{
+       protect(0);
+       set_led(0);
+}
+
+int main(int argc, char **argv)
+{
+       int fd, ret;
+       struct sched_param param;
+
+       if (argc == 1)
+               ret = set_unload_heads_path("/dev/sda");
+       else if (argc == 2)
+               ret = set_unload_heads_path(argv[1]);
+       else
+               ret = -EINVAL;
+
+       if (ret || !valid_disk()) {
+               fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
+                               argv[0]);
+               exit(1);
+       }
+
+       fd = open("/dev/freefall", O_RDONLY);
+       if (fd < 0) {
+               perror("/dev/freefall");
+               return EXIT_FAILURE;
+       }
+
+       daemon(0, 0);
+       param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+       sched_setscheduler(0, SCHED_FIFO, &param);
+       mlockall(MCL_CURRENT|MCL_FUTURE);
+
+       signal(SIGALRM, ignore_me);
+
+       for (;;) {
+               unsigned char count;
+
+               ret = read(fd, &count, sizeof(count));
+               alarm(0);
+               if ((ret == -1) && (errno == EINTR)) {
+                       /* Alarm expired, time to unpark the heads */
+                       continue;
+               }
+
+               if (ret != sizeof(count)) {
+                       perror("read");
+                       break;
+               }
+
+               protect(21);
+               set_led(1);
+               if (1 || on_ac() || lid_open())
+                       alarm(2);
+               else
+                       alarm(20);
+       }
+
+       close(fd);
+       return EXIT_SUCCESS;
+}
diff --git a/Documentation/misc-devices/lis3lv02d b/Documentation/misc-devices/lis3lv02d
new file mode 100644 (file)
index 0000000..f1a4ec8
--- /dev/null
@@ -0,0 +1,92 @@
+Kernel driver lis3lv02d
+=======================
+
+Supported chips:
+
+  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
+  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
+
+Authors:
+        Yan Burman <burman.yan@gmail.com>
+       Eric Piel <eric.piel@tremplin-utc.net>
+
+
+Description
+-----------
+
+This driver provides support for the accelerometer found in various HP laptops
+sporting the feature officially called "HP Mobile Data Protection System 3D" or
+"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
+models (full list can be found in drivers/platform/x86/hp_accel.c) will have
+their axis automatically oriented on standard way (eg: you can directly play
+neverball). The accelerometer data is readable via
+/sys/devices/platform/lis3lv02d. Reported values are scaled
+to mg values (1/1000th of earth gravity).
+
+Sysfs attributes under /sys/devices/platform/lis3lv02d/:
+position - 3D position that the accelerometer reports. Format: "(x,y,z)"
+rate - read reports the sampling rate of the accelerometer device in HZ.
+       write changes sampling rate of the accelerometer device.
+       Only values which are supported by HW are accepted.
+selftest - performs selftest for the chip as specified by chip manufacturer.
+
+This driver also provides an absolute input class device, allowing
+the laptop to act as a pinball machine-esque joystick. Joystick device can be
+calibrated. Joystick device can be in two different modes.
+By default output values are scaled between -32768 .. 32767. In joystick raw
+mode, joystick and sysfs position entry have the same scale. There can be
+small difference due to input system fuzziness feature.
+Events are also available as input event device.
+
+Selftest is meant only for hardware diagnostic purposes. It is not meant to be
+used during normal operations. Position data is not corrupted during selftest
+but interrupt behaviour is not guaranteed to work reliably. In test mode, the
+sensing element is internally moved little bit. Selftest measures difference
+between normal mode and test mode. Chip specifications tell the acceptance
+limit for each type of the chip. Limits are provided via platform data
+to allow adjustment of the limits without a change to the actual driver.
+Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
+measured difference between modes. Axes are not remapped in selftest mode.
+Measurement values are provided to help HW diagnostic applications to make
+final decision.
+
+On HP laptops, if the led infrastructure is activated, support for a led
+indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
+
+Another feature of the driver is misc device called "freefall" that
+acts similar to /dev/rtc and reacts on free-fall interrupts received
+from the device. It supports blocking operations, poll/select and
+fasync operation modes. You must read 1 bytes from the device.  The
+result is number of free-fall interrupts since the last successful
+read (or 255 if number of interrupts would not fit). See the hpfall.c
+file for an example on using the device.
+
+
+Axes orientation
+----------------
+
+For better compatibility between the various laptops. The values reported by
+the accelerometer are converted into a "standard" organisation of the axes
+(aka "can play neverball out of the box"):
+ * When the laptop is horizontal the position reported is about 0 for X and Y
+       and a positive value for Z
+ * If the left side is elevated, X increases (becomes positive)
+ * If the front side (where the touchpad is) is elevated, Y decreases
+       (becomes negative)
+ * If the laptop is put upside-down, Z becomes negative
+
+If your laptop model is not recognized (cf "dmesg"), you can send an
+email to the maintainer to add it to the database.  When reporting a new
+laptop, please include the output of "dmidecode" plus the value of
+/sys/devices/platform/lis3lv02d/position in these four cases.
+
+Q&A
+---
+
+Q: How do I safely simulate freefall? I have an HP "portable
+workstation" which has about 3.5kg and a plastic case, so letting it
+fall to the ground is out of question...
+
+A: The sensor is pretty sensitive, so your hands can do it. Lift it
+into free space, follow the fall with your hands for like 10
+centimeters. That should be enough to trigger the detection.
index 699b60e070d216b1860e39aaa58c3f1967cc7866..c40e3bab08fa3cffc72c162931b8694d57fd2a03 100644 (file)
@@ -130,7 +130,7 @@ Card number: 4
 
 Note: No module for the mse3000 is available yet
 Note: No module for the vpx3224 is available yet
-Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
+Note: use encoder=X or decoder=X for non-default i2c chips
 
 ===========================
 
index c7a41b1fe453b267e02e5eef5ba649634dbc8060..38077a6568207d6898ad88e2dd955434873b3595 100644 (file)
@@ -198,7 +198,7 @@ F:  Documentation/scsi/aacraid.txt
 F:     drivers/scsi/aacraid/
 
 ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
-M:     Hans de Goede <j.w.r.degoede@hhs.nl>
+M:     Hans de Goede <hdegoede@redhat.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/abituguru.c
@@ -365,6 +365,14 @@ W: http://wiki-analog.com/ADP8860
 S:     Supported
 F:     drivers/video/backlight/adp8860_bl.c
 
+ADS1015 HARDWARE MONITOR DRIVER
+M:     Dirk Eibach <eibach@gdsys.de>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ads1015
+F:     drivers/hwmon/ads1015.c
+F:     include/linux/i2c/ads1015.h
+
 ADT746X FAN DRIVER
 M:     Colin Leroy <colin@colino.net>
 S:     Maintained
@@ -3913,8 +3921,8 @@ S:        Supported
 LIS3LV02D ACCELEROMETER DRIVER
 M:     Eric Piel <eric.piel@tremplin-utc.net>
 S:     Maintained
-F:     Documentation/hwmon/lis3lv02d
-F:     drivers/hwmon/lis3lv02d.*
+F:     Documentation/misc-devices/lis3lv02d
+F:     drivers/misc/lis3lv02d/
 
 LLC (802.2)
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@ -5769,6 +5777,13 @@ S:       Supported
 F:     Documentation/hwmon/emc2103
 F:     drivers/hwmon/emc2103.c
 
+SMSC SCH5627 HARDWARE MONITOR DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     lm-sensors@lm-sensors.org
+S:     Supported
+F:     Documentation/hwmon/sch5627
+F:     drivers/hwmon/sch5627.c
+
 SMSC47B397 HARDWARE MONITOR DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     lm-sensors@lm-sensors.org
index 92b8bed3059e5c9fc4e9938a905e00c66ee12f75..7d4e9c8da7295e628d8a7849b72e1d8651d8772c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -102,6 +102,10 @@ ifeq ("$(origin O)", "command line")
   KBUILD_OUTPUT := $(O)
 endif
 
+ifeq ("$(origin W)", "command line")
+  export KBUILD_ENABLE_EXTRA_GCC_CHECKS := 1
+endif
+
 # That's our default target when none is given on the command line
 PHONY := _all
 _all:
@@ -421,7 +425,7 @@ endif
 # of make so .config is not included in this case either (for *config).
 
 no-dot-config-targets := clean mrproper distclean \
-                        cscope TAGS tags help %docs check% coccicheck \
+                        cscope gtags TAGS tags help %docs check% coccicheck \
                         include/linux/version.h headers_% \
                         kernelversion %src-pkg
 
@@ -1018,7 +1022,7 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
 
 PHONY += __headers
 __headers: include/linux/version.h scripts_basic FORCE
-       $(Q)$(MAKE) $(build)=scripts scripts/unifdef
+       $(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
 headers_install_all:
@@ -1135,7 +1139,7 @@ CLEAN_FILES +=    vmlinux System.map \
 MRPROPER_DIRS  += include/config usr/include include/generated
 MRPROPER_FILES += .config .config.old .version .old_version             \
                   include/linux/version.h                               \
-                 Module.symvers tags TAGS cscope*
+                 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1222,6 +1226,7 @@ help:
        @echo  '  modules_prepare - Set up for building external modules'
        @echo  '  tags/TAGS       - Generate tags file for editors'
        @echo  '  cscope          - Generate cscope index'
+       @echo  '  gtags           - Generate GNU GLOBAL index'
        @echo  '  kernelrelease   - Output the release version string'
        @echo  '  kernelversion   - Output the version stored in Makefile'
        @echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
@@ -1262,6 +1267,7 @@ help:
        @echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
        @echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
        @echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
+       @echo  '  make W=1   [targets] Enable extra gcc checks'
        @echo  ''
        @echo  'Execute "make" or "make all" to build all targets marked with [*] '
        @echo  'For further info see the ./README file'
@@ -1380,7 +1386,7 @@ clean: $(clean-dirs)
 quiet_cmd_tags = GEN     $@
       cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
 
-tags TAGS cscope: FORCE
+tags TAGS cscope gtags: FORCE
        $(call cmd,tags)
 
 # Scripts to check various things for consistency
index f9f77c65dff32d8708ec98b799630076185bafc3..8ebbb511c7836383aac94622d0ed00aed5c5f29a 100644 (file)
@@ -95,8 +95,8 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-EXTRA_CFLAGS  := -fpic -fno-builtin
-EXTRA_AFLAGS  := -Wa,-march=all
+ccflags-y := -fpic -fno-builtin
+asflags-y := -Wa,-march=all
 
 # Provide size of uncompressed kernel to the decompressor via a linker symbol.
 LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image)
diff --git a/arch/arm/mach-mxs/include/mach/mmc.h b/arch/arm/mach-mxs/include/mach/mmc.h
new file mode 100644 (file)
index 0000000..211547a
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_MXS_MMC_H__
+#define __MACH_MXS_MMC_H__
+
+struct mxs_mmc_platform_data {
+       int wp_gpio;    /* write protect pin */
+       unsigned int flags;
+#define SLOTF_4_BIT_CAPABLE    (1 << 0)
+#define SLOTF_8_BIT_CAPABLE    (1 << 1)
+};
+#endif /* __MACH_MXS_MMC_H__ */
index 243291722c667484a22ec85337cc17b3f521f89e..31d5aa76975310a529084e575e0116e08a7846df 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/fb.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
-#include <linux/i2c/qt602240_ts.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/mfd/max8998.h>
 #include <linux/mfd/wm8994/pdata.h>
 #include <linux/regulator/fixed.h>
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -225,7 +226,7 @@ static void __init goni_radio_init(void)
 }
 
 /* TSP */
-static struct qt602240_platform_data qt602240_platform_data = {
+static struct mxt_platform_data qt602240_platform_data = {
        .x_line         = 17,
        .y_line         = 11,
        .x_size         = 800,
@@ -233,7 +234,8 @@ static struct qt602240_platform_data qt602240_platform_data = {
        .blen           = 0x21,
        .threshold      = 0x28,
        .voltage        = 2800000,              /* 2.8V */
-       .orient         = QT602240_DIAGONAL,
+       .orient         = MXT_DIAGONAL,
+       .irqflags       = IRQF_TRIGGER_FALLING,
 };
 
 static struct s3c2410_platform_i2c i2c2_data __initdata = {
index a48a9aaa56b1dd46093eb94288080bd2262c5062..86003f411755f02d29a937e547b9191a39cf4b77 100644 (file)
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio:   gpio for write_protect (-EINVAL if unused)
+ * @cd_gpio:   gpio for card_detect interrupt (-EINVAL if unused)
+ */
+
 struct esdhc_platform_data {
-       unsigned int wp_gpio;   /* write protect pin */
+       unsigned int wp_gpio;
+       unsigned int cd_gpio;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
index 39f6d8e1af73043890adcf8761b226b5f2e82d4d..6de73aab019599fd4a53abdffa39b863a090128f 100644 (file)
@@ -4,8 +4,8 @@
 # Copyright (C) 2001 ARM Limited
 #
 
-# EXTRA_CFLAGS := -DDEBUG
-# EXTRA_AFLAGS := -DDEBUG
+# ccflags-y := -DDEBUG
+# asflags-y := -DDEBUG
 
 KBUILD_AFLAGS  :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
 LDFLAGS                +=--no-warn-mismatch
index c09577ddc3c5b1ee9c93fd07ccf160e9b6ceae33..01615d4f57d6fc623ae9503480390964223c0a24 100644 (file)
@@ -33,6 +33,7 @@ config BLACKFIN
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select IRQ_PER_CPU if SMP
+       select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config GENERIC_CSUM
        def_bool y
@@ -690,13 +691,13 @@ endmenu
 
 
 menu "Blackfin Kernel Optimizations"
-       depends on !SMP
 
 comment "Memory Optimizations"
 
 config I_ENTRY_L1
        bool "Locate interrupt entry code in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, interrupt entry code (STORE/RESTORE CONTEXT) is linked
          into L1 instruction memory. (less latency)
@@ -704,6 +705,7 @@ config I_ENTRY_L1
 config EXCPT_IRQ_SYSC_L1
        bool "Locate entire ASM lowlevel exception / interrupt - Syscall and CPLB handler code in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the entire ASM lowlevel exception and interrupt entry code
          (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
@@ -712,6 +714,7 @@ config EXCPT_IRQ_SYSC_L1
 config DO_IRQ_L1
        bool "Locate frequently called do_irq dispatcher function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the frequently called do_irq dispatcher function is linked
          into L1 instruction memory. (less latency)
@@ -719,6 +722,7 @@ config DO_IRQ_L1
 config CORE_TIMER_IRQ_L1
        bool "Locate frequently called timer_interrupt() function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the frequently called timer_interrupt() function is linked
          into L1 instruction memory. (less latency)
@@ -726,6 +730,7 @@ config CORE_TIMER_IRQ_L1
 config IDLE_L1
        bool "Locate frequently idle function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the frequently called idle function is linked
          into L1 instruction memory. (less latency)
@@ -733,6 +738,7 @@ config IDLE_L1
 config SCHEDULE_L1
        bool "Locate kernel schedule function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the frequently called kernel schedule is linked
          into L1 instruction memory. (less latency)
@@ -740,6 +746,7 @@ config SCHEDULE_L1
 config ARITHMETIC_OPS_L1
        bool "Locate kernel owned arithmetic functions in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, arithmetic functions are linked
          into L1 instruction memory. (less latency)
@@ -747,6 +754,7 @@ config ARITHMETIC_OPS_L1
 config ACCESS_OK_L1
        bool "Locate access_ok function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the access_ok function is linked
          into L1 instruction memory. (less latency)
@@ -754,6 +762,7 @@ config ACCESS_OK_L1
 config MEMSET_L1
        bool "Locate memset function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the memset function is linked
          into L1 instruction memory. (less latency)
@@ -761,6 +770,7 @@ config MEMSET_L1
 config MEMCPY_L1
        bool "Locate memcpy function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the memcpy function is linked
          into L1 instruction memory. (less latency)
@@ -768,6 +778,7 @@ config MEMCPY_L1
 config STRCMP_L1
        bool "locate strcmp function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the strcmp function is linked
          into L1 instruction memory (less latency).
@@ -775,6 +786,7 @@ config STRCMP_L1
 config STRNCMP_L1
        bool "locate strncmp function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the strncmp function is linked
          into L1 instruction memory (less latency).
@@ -782,6 +794,7 @@ config STRNCMP_L1
 config STRCPY_L1
        bool "locate strcpy function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the strcpy function is linked
          into L1 instruction memory (less latency).
@@ -789,6 +802,7 @@ config STRCPY_L1
 config STRNCPY_L1
        bool "locate strncpy function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, the strncpy function is linked
          into L1 instruction memory (less latency).
@@ -796,6 +810,7 @@ config STRNCPY_L1
 config SYS_BFIN_SPINLOCK_L1
        bool "Locate sys_bfin_spinlock function in L1 Memory"
        default y
+       depends on !SMP
        help
          If enabled, sys_bfin_spinlock function is linked
          into L1 instruction memory. (less latency)
@@ -803,6 +818,7 @@ config SYS_BFIN_SPINLOCK_L1
 config IP_CHECKSUM_L1
        bool "Locate IP Checksum function in L1 Memory"
        default n
+       depends on !SMP
        help
          If enabled, the IP Checksum function is linked
          into L1 instruction memory. (less latency)
@@ -811,7 +827,7 @@ config CACHELINE_ALIGNED_L1
        bool "Locate cacheline_aligned data to L1 Data Memory"
        default y if !BF54x
        default n if BF54x
-       depends on !BF531
+       depends on !SMP && !BF531
        help
          If enabled, cacheline_aligned data is linked
          into L1 data memory. (less latency)
@@ -819,7 +835,7 @@ config CACHELINE_ALIGNED_L1
 config SYSCALL_TAB_L1
        bool "Locate Syscall Table L1 Data Memory"
        default n
-       depends on !BF531
+       depends on !SMP && !BF531
        help
          If enabled, the Syscall LUT is linked
          into L1 data memory. (less latency)
@@ -827,16 +843,16 @@ config SYSCALL_TAB_L1
 config CPLB_SWITCH_TAB_L1
        bool "Locate CPLB Switch Tables L1 Data Memory"
        default n
-       depends on !BF531
+       depends on !SMP && !BF531
        help
          If enabled, the CPLB Switch Tables are linked
          into L1 data memory. (less latency)
 
-config CACHE_FLUSH_L1
-       bool "Locate cache flush funcs in L1 Inst Memory"
+config ICACHE_FLUSH_L1
+       bool "Locate icache flush funcs in L1 Inst Memory"
        default y
        help
-         If enabled, the Blackfin cache flushing functions are linked
+         If enabled, the Blackfin icache flushing functions are linked
          into L1 instruction memory.
 
          Note that this might be required to address anomalies, but
@@ -844,9 +860,18 @@ config CACHE_FLUSH_L1
          If you are using a processor affected by an anomaly, the build
          system will double check for you and prevent it.
 
+config DCACHE_FLUSH_L1
+       bool "Locate dcache flush funcs in L1 Inst Memory"
+       default y
+       depends on !SMP
+       help
+         If enabled, the Blackfin dcache flushing functions are linked
+         into L1 instruction memory.
+
 config APP_STACK_L1
        bool "Support locating application stack in L1 Scratch Memory"
        default y
+       depends on !SMP
        help
          If enabled the application stack can be located in L1
          scratch memory (less latency).
@@ -856,7 +881,7 @@ config APP_STACK_L1
 config EXCEPTION_L1_SCRATCH
        bool "Locate exception stack in L1 Scratch Memory"
        default n
-       depends on !APP_STACK_L1
+       depends on !SMP && !APP_STACK_L1
        help
          Whenever an exception occurs, use the L1 Scratch memory for
          stack storage.  You cannot place the stacks of FLAT binaries
@@ -868,6 +893,7 @@ comment "Speed Optimizations"
 config BFIN_INS_LOWOVERHEAD
        bool "ins[bwl] low overhead, higher interrupt latency"
        default y
+       depends on !SMP
        help
          Reads on the Blackfin are speculative. In Blackfin terms, this means
          they can be interrupted at any time (even after they have been issued
index db8d38a12a9aeb79522ddbbb819514ec0b6c97f0..5edcb58d6f737f49a69a8dcf9784c2c2935e1dea 100644 (file)
@@ -115,6 +115,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 3e50d7857c2725bc05dcffaa0ffcab3212b9e10d..2e549572d4f59c5ff73ab137c56fd13a4b312dd2 100644 (file)
@@ -153,6 +153,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 023ff0df2692c2d2146908fe9d1ce391b83141c8..95cf2ba9de17ba2e95337efc8de0d14f3a21e754 100644 (file)
@@ -183,5 +183,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 4e5a121b3c563b9a9b42479c6164614e9e67bd3f..8be8e33fac526c7eb6526f39ce9f44c7a1521ab9 100644 (file)
@@ -175,5 +175,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 9f8fc84e4ac949be9b8c3b1105626bb5d8b5b3c6..a7eb54bf3089916359b3f178a3e26fc5980df1be 100644 (file)
@@ -108,5 +108,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index ccc432b722a0746681945133699484ec89b31615..0aafde6c8c2d00fd079c62999fb60cf7023dcc87 100644 (file)
@@ -122,5 +122,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 566695472a8486148ca1d230aa59567a770a6ba6..c9077fb581354bc621fe5e1ee152e9ae1933a56a 100644 (file)
@@ -133,5 +133,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index ac22124ccb6cc0515c9ac31317f32f25e04e6e90..6883803e6ca8902addc92ef80688bfd1aeac786a 100644 (file)
@@ -131,5 +131,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 944404b6ff08ad723cce862bb22815be4bb1b555..56151b5dbc4446e4f5710ec8ca263d48fe0fcba2 100644 (file)
@@ -205,5 +205,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 7e67ba31e9919655eb833e259ed970bd707b3e81..f5ed34e12e0ca9928e3b7b1a9bcbd339a076e6bd 100644 (file)
@@ -109,5 +109,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 141e5933e1aaf7f2be33a4617f43e7257288320e..1c0a82a105919aaf1b6523cd0d8afe8114e0c4ae 100644 (file)
@@ -111,5 +111,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index e3f0f4c49819e4a0d3823d6344f71fbf61a2ffc6..7600fe0696af1c9cda33471b1bf8a963e43df303 100644 (file)
     ({ BUG(); 0; }); \
 })
 #define bfin_write(addr, val) \
-({ \
+do { \
        switch (sizeof(*(addr))) { \
        case 1: bfin_write8(addr, val);  break; \
        case 2: bfin_write16(addr, val); break; \
        case 4: bfin_write32(addr, val); break; \
        default: BUG(); \
        } \
-})
+} while (0)
+
+#define bfin_write_or(addr, bits) \
+do { \
+       void *__addr = (void *)(addr); \
+       bfin_write(__addr, bfin_read(__addr) | (bits)); \
+} while (0)
+
+#define bfin_write_and(addr, bits) \
+do { \
+       void *__addr = (void *)(addr); \
+       bfin_write(__addr, bfin_read(__addr) & (bits)); \
+} while (0)
 
 #endif /* __ASSEMBLY__ */
 
index 3047120cfcff4b5ce9a7e8bca467a6df820f4aef..edf2a2ad518313883ff26cb8fc49168a1d4db669 100644 (file)
@@ -125,6 +125,9 @@ void unset_dram_srfs(void);
 
 #define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
 
+#ifdef CONFIG_CPU_FREQ
+#define CPUFREQ_CPU 0
+#endif
 struct bfin_dpmc_platform_data {
        const unsigned int *tuple_tab;
        unsigned short tabsize;
index 40f94a704c0202ace94e99429d7b67cb241d40f1..9e0cc0e2534f67376769410059b6fe76bf00600e 100644 (file)
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 #include <asm/traps.h>
+#include <asm/bitsperlong.h>
 
-#define IPIPE_ARCH_STRING     "1.12-00"
+#define IPIPE_ARCH_STRING     "1.16-01"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    12
-#define IPIPE_PATCH_NUMBER    0
+#define IPIPE_MINOR_NUMBER    16
+#define IPIPE_PATCH_NUMBER    1
 
 #ifdef CONFIG_SMP
 #error "I-pipe/blackfin: SMP not implemented"
@@ -55,25 +56,19 @@ do {                                                \
 #define task_hijacked(p)                                               \
        ({                                                              \
                int __x__ = __ipipe_root_domain_p;                      \
-               __clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
                if (__x__)                                              \
-                       hard_local_irq_enable();                                \
+                       hard_local_irq_enable();                        \
                !__x__;                                                 \
        })
 
 struct ipipe_domain;
 
 struct ipipe_sysinfo {
-
-       int ncpus;              /* Number of CPUs on board */
-       u64 cpufreq;            /* CPU frequency (in Hz) */
-
-       /* Arch-dependent block */
-
-       struct {
-               unsigned tmirq; /* Timer tick IRQ */
-               u64 tmfreq;     /* Timer frequency */
-       } archdep;
+       int sys_nr_cpus;        /* Number of CPUs on board */
+       int sys_hrtimer_irq;    /* hrtimer device IRQ */
+       u64 sys_hrtimer_freq;   /* hrtimer device frequency */
+       u64 sys_hrclock_freq;   /* hrclock device frequency */
+       u64 sys_cpu_freq;       /* CPU frequency (Hz) */
 };
 
 #define ipipe_read_tsc(t)                                      \
@@ -115,9 +110,19 @@ void __ipipe_enable_irqdesc(struct ipipe_domain *ipd,
 void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
                             unsigned irq);
 
-#define __ipipe_enable_irq(irq)                (irq_desc[irq].chip->unmask(irq))
+#define __ipipe_enable_irq(irq)                                                \
+       do {                                                            \
+               struct irq_desc *desc = irq_to_desc(irq);               \
+               struct irq_chip *chip = get_irq_desc_chip(desc);        \
+               chip->irq_unmask(&desc->irq_data);                      \
+       } while (0)
 
-#define __ipipe_disable_irq(irq)       (irq_desc[irq].chip->mask(irq))
+#define __ipipe_disable_irq(irq)                                       \
+       do {                                                            \
+               struct irq_desc *desc = irq_to_desc(irq);               \
+               struct irq_chip *chip = get_irq_desc_chip(desc);        \
+               chip->irq_mask(&desc->irq_data);                        \
+       } while (0)
 
 static inline int __ipipe_check_tickdev(const char *devname)
 {
@@ -128,12 +133,11 @@ void __ipipe_enable_pipeline(void);
 
 #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
 
-#define __ipipe_sync_pipeline  ___ipipe_sync_pipeline
-void ___ipipe_sync_pipeline(unsigned long syncmask);
+void ___ipipe_sync_pipeline(void);
 
 void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
 
-int __ipipe_get_irq_priority(unsigned irq);
+int __ipipe_get_irq_priority(unsigned int irq);
 
 void __ipipe_serial_debug(const char *fmt, ...);
 
@@ -152,7 +156,10 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
        return ffs(ul) - 1;
 }
 
-#define __ipipe_run_irqtail()  /* Must be a macro */                   \
+#define __ipipe_do_root_xirq(ipd, irq)                                 \
+       ((ipd)->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)))
+
+#define __ipipe_run_irqtail(irq)  /* Must be a macro */                        \
        do {                                                            \
                unsigned long __pending;                                \
                CSYNC();                                                \
@@ -164,42 +171,8 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
                }                                                       \
        } while (0)
 
-#define __ipipe_run_isr(ipd, irq)                                      \
-       do {                                                            \
-               if (!__ipipe_pipeline_head_p(ipd))                      \
-                       hard_local_irq_enable();                                \
-               if (ipd == ipipe_root_domain) {                         \
-                       if (unlikely(ipipe_virtual_irq_p(irq))) {       \
-                               irq_enter();                            \
-                               ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-                               irq_exit();                             \
-                       } else                                          \
-                               ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
-               } else {                                                \
-                       __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-                       ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-                       /* Attempt to exit the outer interrupt level before \
-                        * starting the deferred IRQ processing. */     \
-                       __ipipe_run_irqtail();                          \
-                       __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-               }                                                       \
-               hard_local_irq_disable();                                       \
-       } while (0)
-
 #define __ipipe_syscall_watched_p(p, sc)       \
-       (((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)
-
-void ipipe_init_irq_threads(void);
-
-int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
-
-#ifdef CONFIG_TICKSOURCE_CORETMR
-#define IRQ_SYSTMR             IRQ_CORETMR
-#define IRQ_PRIOTMR            IRQ_CORETMR
-#else
-#define IRQ_SYSTMR             IRQ_TIMER0
-#define IRQ_PRIOTMR            CONFIG_IRQ_TIMER0
-#endif
+       (ipipe_notifier_enabled_p(p) || (unsigned long)sc >= NR_syscalls)
 
 #ifdef CONFIG_BF561
 #define bfin_write_TIMER_DISABLE(val)  bfin_write_TMRS8_DISABLE(val)
@@ -219,11 +192,11 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 
 #define task_hijacked(p)               0
 #define ipipe_trap_notify(t, r)        0
+#define __ipipe_root_tick_p(regs)      1
 
-#define ipipe_init_irq_threads()               do { } while (0)
-#define ipipe_start_irq_thread(irq, desc)      0
+#endif /* !CONFIG_IPIPE */
 
-#ifndef CONFIG_TICKSOURCE_GPTMR0
+#ifdef CONFIG_TICKSOURCE_CORETMR
 #define IRQ_SYSTMR             IRQ_CORETMR
 #define IRQ_PRIOTMR            IRQ_CORETMR
 #else
@@ -231,10 +204,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 #define IRQ_PRIOTMR            CONFIG_IRQ_TIMER0
 #endif
 
-#define __ipipe_root_tick_p(regs)      1
-
-#endif /* !CONFIG_IPIPE */
-
 #define ipipe_update_tick_evtdev(evtdev)       do { } while (0)
 
 #endif /* !__ASM_BLACKFIN_IPIPE_H */
index 00409201d9edc7d69a225562caef7582e636d447..84a4ffd367475ef9c2cd32ab54f242844100fb12 100644 (file)
 
 #ifdef CONFIG_IPIPE
 
+#include <asm/bitsperlong.h>
+#include <mach/irq.h>
+
 #define IPIPE_NR_XIRQS         NR_IRQS
-#define IPIPE_IRQ_ISHIFT       5       /* 2^5 for 32bits arch. */
 
 /* Blackfin-specific, per-cpu pipeline status */
 #define IPIPE_SYNCDEFER_FLAG   15
 #define IPIPE_EVENT_INIT       (IPIPE_FIRST_EVENT + 4)
 #define IPIPE_EVENT_EXIT       (IPIPE_FIRST_EVENT + 5)
 #define IPIPE_EVENT_CLEANUP    (IPIPE_FIRST_EVENT + 6)
-#define IPIPE_LAST_EVENT       IPIPE_EVENT_CLEANUP
+#define IPIPE_EVENT_RETURN     (IPIPE_FIRST_EVENT + 7)
+#define IPIPE_LAST_EVENT       IPIPE_EVENT_RETURN
 #define IPIPE_NR_EVENTS                (IPIPE_LAST_EVENT + 1)
 
 #define IPIPE_TIMER_IRQ                IRQ_CORETMR
 
+#define __IPIPE_FEATURE_SYSINFO_V2     1
+
 #ifndef __ASSEMBLY__
 
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
@@ -63,6 +68,8 @@ void __ipipe_unlock_root(void);
 
 #endif /* !__ASSEMBLY__ */
 
+#define __IPIPE_FEATURE_SYSINFO_V2     1
+
 #endif /* CONFIG_IPIPE */
 
 #endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
index 3365cb97f539a7ede6d2a6e225b2ec69b579b4b6..b4bbb75a9e15a2483358a59599ca0eb677defc73 100644 (file)
@@ -89,15 +89,33 @@ static inline void __hard_local_irq_restore(unsigned long flags)
 #ifdef CONFIG_IPIPE
 
 #include <linux/compiler.h>
-#include <linux/ipipe_base.h>
 #include <linux/ipipe_trace.h>
+/*
+ * Way too many inter-deps between low-level headers in this port, so
+ * we redeclare the required bits we cannot pick from
+ * <asm/ipipe_base.h> to prevent circular dependencies.
+ */
+void __ipipe_stall_root(void);
+void __ipipe_unstall_root(void);
+unsigned long __ipipe_test_root(void);
+unsigned long __ipipe_test_and_stall_root(void);
+void __ipipe_restore_root(unsigned long flags);
+
+#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
+struct ipipe_domain;
+extern struct ipipe_domain ipipe_root;
+void ipipe_check_context(struct ipipe_domain *ipd);
+#define __check_irqop_context(ipd)  ipipe_check_context(&ipipe_root)
+#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */
+#define __check_irqop_context(ipd)  do { } while (0)
+#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */
 
 /*
  * Interrupt pipe interface to linux/irqflags.h.
  */
 static inline void arch_local_irq_disable(void)
 {
-       ipipe_check_context(ipipe_root_domain);
+       __check_irqop_context();
        __ipipe_stall_root();
        barrier();
 }
@@ -105,7 +123,7 @@ static inline void arch_local_irq_disable(void)
 static inline void arch_local_irq_enable(void)
 {
        barrier();
-       ipipe_check_context(ipipe_root_domain);
+       __check_irqop_context();
        __ipipe_unstall_root();
 }
 
@@ -119,16 +137,21 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
        return flags == bfin_no_irqs;
 }
 
-static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+static inline unsigned long arch_local_irq_save(void)
 {
-       x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+       unsigned long flags;
+
+       __check_irqop_context();
+       flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
        barrier();
+
+       return flags;
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
-       ipipe_check_context(ipipe_root_domain);
-       return __hard_local_irq_save();
+       __check_irqop_context();
+       __ipipe_restore_root(flags == bfin_no_irqs);
 }
 
 static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
@@ -192,7 +215,10 @@ static inline void hard_local_irq_restore(unsigned long flags)
 # define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 
-#else /* CONFIG_IPIPE */
+#define hard_local_irq_save_cond()             hard_local_irq_save()
+#define hard_local_irq_restore_cond(flags)     hard_local_irq_restore(flags)
+
+#else /* !CONFIG_IPIPE */
 
 /*
  * Direct interface to linux/irqflags.h.
@@ -212,7 +238,48 @@ static inline void hard_local_irq_restore(unsigned long flags)
 #define hard_local_irq_restore(flags)  __hard_local_irq_restore(flags)
 #define hard_local_irq_enable()                __hard_local_irq_enable()
 #define hard_local_irq_disable()       __hard_local_irq_disable()
-
+#define hard_local_irq_save_cond()             hard_local_save_flags()
+#define hard_local_irq_restore_cond(flags)     do { (void)(flags); } while (0)
 
 #endif /* !CONFIG_IPIPE */
+
+#ifdef CONFIG_SMP
+#define hard_local_irq_save_smp()              hard_local_irq_save()
+#define hard_local_irq_restore_smp(flags)      hard_local_irq_restore(flags)
+#else
+#define hard_local_irq_save_smp()              hard_local_save_flags()
+#define hard_local_irq_restore_smp(flags)      do { (void)(flags); } while (0)
+#endif
+
+/*
+ * Remap the arch-neutral IRQ state manipulation macros to the
+ * blackfin-specific hard_local_irq_* API.
+ */
+#define local_irq_save_hw(flags)                       \
+       do {                                            \
+               (flags) = hard_local_irq_save();        \
+       } while (0)
+#define local_irq_restore_hw(flags)            \
+       do {                                    \
+               hard_local_irq_restore(flags);  \
+       } while (0)
+#define local_irq_disable_hw()                 \
+       do {                                    \
+               hard_local_irq_disable();       \
+       } while (0)
+#define local_irq_enable_hw()                  \
+       do {                                    \
+               hard_local_irq_enable();        \
+       } while (0)
+#define local_irq_save_hw_notrace(flags)               \
+       do {                                            \
+               (flags) = __hard_local_irq_save();      \
+       } while (0)
+#define local_irq_restore_hw_notrace(flags)            \
+       do {                                            \
+               __hard_local_irq_restore(flags);        \
+       } while (0)
+
+#define irqs_disabled_hw()     hard_irqs_disabled()
+
 #endif
index f5b537967116d151c828eac66b2166b3d5f179eb..af6c0aa79bae9435ea5dff4f92f2c945051352aa 100644 (file)
 
 #define raw_smp_processor_id()  blackfin_core_id()
 
-extern char coreb_trampoline_start, coreb_trampoline_end;
+extern void bfin_relocate_coreb_l1_mem(void);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
+extern unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
 
 struct corelock_slot {
        int lock;
@@ -34,7 +39,7 @@ extern unsigned long dcache_invld_count[NR_CPUS];
 void smp_icache_flush_range_others(unsigned long start,
                                   unsigned long end);
 #ifdef CONFIG_HOTPLUG_CPU
-void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
+void coreb_die(void);
 void cpu_die(void);
 void platform_cpu_die(void);
 int __cpu_disable(void);
index 928ae975b87e20f978c6a29244093273623e1f78..c97497dd0d195fd5b3cdf605cc5a17c48f9d7f4a 100644 (file)
 #define __NR_fanotify_mark     372
 #define __NR_prlimit64         373
 #define __NR_cacheflush                374
+#define __NR_name_to_handle_at 375
+#define __NR_open_by_handle_at 376
+#define __NR_clock_adjtime     377
 
-#define __NR_syscall           375
+#define __NR_syscall           378
 #define NR_syscalls            __NR_syscall
 
 /* Old optional stuff no one actually uses */
index 1e485dfdc9f2133a37d1d7d8b81af47b6bf53814..6ce8dce753c9a49039a615e56cf8e83fbb8097bf 100644 (file)
@@ -84,6 +84,24 @@ static int __init proc_dma_init(void)
 late_initcall(proc_dma_init);
 #endif
 
+static void set_dma_peripheral_map(unsigned int channel, const char *device_id)
+{
+#ifdef CONFIG_BF54x
+       unsigned int per_map;
+
+       switch (channel) {
+               case CH_UART2_RX: per_map = 0xC << 12; break;
+               case CH_UART2_TX: per_map = 0xD << 12; break;
+               case CH_UART3_RX: per_map = 0xE << 12; break;
+               case CH_UART3_TX: per_map = 0xF << 12; break;
+               default:          return;
+       }
+
+       if (strncmp(device_id, "BFIN_UART", 9) == 0)
+               dma_ch[channel].regs->peripheral_map = per_map;
+#endif
+}
+
 /**
  *     request_dma - request a DMA channel
  *
@@ -111,19 +129,7 @@ int request_dma(unsigned int channel, const char *device_id)
                return -EBUSY;
        }
 
-#ifdef CONFIG_BF54x
-       if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
-               unsigned int per_map;
-               per_map = dma_ch[channel].regs->peripheral_map & 0xFFF;
-               if (strncmp(device_id, "BFIN_UART", 9) == 0)
-                       dma_ch[channel].regs->peripheral_map = per_map |
-                               ((channel - CH_UART2_RX + 0xC)<<12);
-               else
-                       dma_ch[channel].regs->peripheral_map = per_map |
-                               ((channel - CH_UART2_RX + 0x6)<<12);
-       }
-#endif
-
+       set_dma_peripheral_map(channel, device_id);
        dma_ch[channel].device_id = device_id;
        dma_ch[channel].irq = 0;
 
index 3b1da4aff2a1ed560f2c7041d85ccdf571f4972e..f37019c847c9b643c04676d0a2423f870286f16c 100644 (file)
@@ -154,7 +154,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
         * pending for it.
         */
        if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
-           ipipe_head_cpudom_var(irqpend_himask) == 0)
+           !__ipipe_ipending_p(ipipe_head_cpudom_ptr()))
                goto out;
 
        __ipipe_walk_pipeline(head);
@@ -185,25 +185,21 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 }
 EXPORT_SYMBOL(__ipipe_disable_irqdesc);
 
-int __ipipe_syscall_root(struct pt_regs *regs)
+asmlinkage int __ipipe_syscall_root(struct pt_regs *regs)
 {
        struct ipipe_percpu_domain_data *p;
-       unsigned long flags;
+       void (*hook)(void);
        int ret;
 
+       WARN_ON_ONCE(irqs_disabled_hw());
+
        /*
-        * We need to run the IRQ tail hook whenever we don't
-        * propagate a syscall to higher domains, because we know that
-        * important operations might be pending there (e.g. Xenomai
-        * deferred rescheduling).
+        * We need to run the IRQ tail hook each time we intercept a
+        * syscall, because we know that important operations might be
+        * pending there (e.g. Xenomai deferred rescheduling).
         */
-
-       if (regs->orig_p0 < NR_syscalls) {
-               void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
-               hook();
-               if ((current->flags & PF_EVNOTIFY) == 0)
-                       return 0;
-       }
+       hook = (__typeof__(hook))__ipipe_irq_tail_hook;
+       hook();
 
        /*
         * This routine either returns:
@@ -214,51 +210,47 @@ int __ipipe_syscall_root(struct pt_regs *regs)
         * tail work has to be performed (for handling signals etc).
         */
 
-       if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
+       if (!__ipipe_syscall_watched_p(current, regs->orig_p0) ||
+           !__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
                return 0;
 
        ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
 
-       flags = hard_local_irq_save();
+       hard_local_irq_disable();
 
-       if (!__ipipe_root_domain_p) {
-               hard_local_irq_restore(flags);
-               return 1;
+       /*
+        * This is the end of the syscall path, so we may
+        * safely assume a valid Linux task stack here.
+        */
+       if (current->ipipe_flags & PF_EVTRET) {
+               current->ipipe_flags &= ~PF_EVTRET;
+               __ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
        }
 
-       p = ipipe_root_cpudom_ptr();
-       if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
-               __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+       if (!__ipipe_root_domain_p)
+               ret = -1;
+       else {
+               p = ipipe_root_cpudom_ptr();
+               if (__ipipe_ipending_p(p))
+                       __ipipe_sync_pipeline();
+       }
 
-       hard_local_irq_restore(flags);
+       hard_local_irq_enable();
 
        return -ret;
 }
 
-unsigned long ipipe_critical_enter(void (*syncfn) (void))
-{
-       unsigned long flags;
-
-       flags = hard_local_irq_save();
-
-       return flags;
-}
-
-void ipipe_critical_exit(unsigned long flags)
-{
-       hard_local_irq_restore(flags);
-}
-
 static void __ipipe_no_irqtail(void)
 {
 }
 
 int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
 {
-       info->ncpus = num_online_cpus();
-       info->cpufreq = ipipe_cpu_freq();
-       info->archdep.tmirq = IPIPE_TIMER_IRQ;
-       info->archdep.tmfreq = info->cpufreq;
+       info->sys_nr_cpus = num_online_cpus();
+       info->sys_cpu_freq = ipipe_cpu_freq();
+       info->sys_hrtimer_irq = IPIPE_TIMER_IRQ;
+       info->sys_hrtimer_freq = __ipipe_core_clock;
+       info->sys_hrclock_freq = __ipipe_core_clock;
 
        return 0;
 }
@@ -289,6 +281,7 @@ int ipipe_trigger_irq(unsigned irq)
 asmlinkage void __ipipe_sync_root(void)
 {
        void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
+       struct ipipe_percpu_domain_data *p;
        unsigned long flags;
 
        BUG_ON(irqs_disabled());
@@ -300,19 +293,20 @@ asmlinkage void __ipipe_sync_root(void)
 
        clear_thread_flag(TIF_IRQ_SYNC);
 
-       if (ipipe_root_cpudom_var(irqpend_himask) != 0)
-               __ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
+       p = ipipe_root_cpudom_ptr();
+       if (__ipipe_ipending_p(p))
+               __ipipe_sync_pipeline();
 
        hard_local_irq_restore(flags);
 }
 
-void ___ipipe_sync_pipeline(unsigned long syncmask)
+void ___ipipe_sync_pipeline(void)
 {
        if (__ipipe_root_domain_p &&
            test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
                return;
 
-       __ipipe_sync_stage(syncmask);
+       __ipipe_sync_stage();
 }
 
 void __ipipe_disable_root_irqs_hw(void)
index 64cff54a8a58c488175b4fde8f88037107bc6c68..8f079392aff07796ac1cc46edef17ba829649b10 100644 (file)
@@ -39,21 +39,23 @@ int show_interrupts(struct seq_file *p, void *v)
        unsigned long flags;
 
        if (i < NR_IRQS) {
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
+               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);
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-               seq_printf(p, " %8s", irq_desc[i].chip->name);
+               seq_printf(p, " %8s", 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(&irq_desc[i].lock, flags);
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
        } else if (i == NR_IRQS) {
                seq_printf(p, "NMI: ");
                for_each_online_cpu(j)
index eb92592fd80ccb4beddb6ee828179c05f03d3d90..b8cfe34989e4e01fdcb4bff88fe992d950ef347f 100644 (file)
@@ -422,11 +422,7 @@ int kgdb_arch_handle_exception(int vector, int signo,
 
 struct kgdb_arch arch_kgdb_ops = {
        .gdb_bpt_instr = {0xa1},
-#ifdef CONFIG_SMP
-       .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
-#else
        .flags = KGDB_HW_BREAKPOINT,
-#endif
        .set_hw_breakpoint = bfin_set_hw_break,
        .remove_hw_breakpoint = bfin_remove_hw_break,
        .disable_hw_break = bfin_disable_hw_debug,
index ac71dc15cbdb501d82e6c7fe1301ae738f444368..805c6132c7796b26a632c85df14b8a58d508e1de 100644 (file)
@@ -215,11 +215,48 @@ void __init bfin_relocate_l1_mem(void)
 
        early_dma_memcpy_done();
 
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+       blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1;
+#endif
+
        /* if necessary, copy L2 text/data to L2 SRAM */
        if (L2_LENGTH && l2_len)
                memcpy(_stext_l2, _l2_lma, l2_len);
 }
 
+#ifdef CONFIG_SMP
+void __init bfin_relocate_coreb_l1_mem(void)
+{
+       unsigned long text_l1_len = (unsigned long)_text_l1_len;
+       unsigned long data_l1_len = (unsigned long)_data_l1_len;
+       unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
+
+       blackfin_dma_early_init();
+
+       /* if necessary, copy L1 text to L1 instruction SRAM */
+       if (L1_CODE_LENGTH && text_l1_len)
+               early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma,
+                               text_l1_len);
+
+       /* if necessary, copy L1 data to L1 data bank A SRAM */
+       if (L1_DATA_A_LENGTH && data_l1_len)
+               early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma,
+                               data_l1_len);
+
+       /* if necessary, copy L1 data B to L1 data bank B SRAM */
+       if (L1_DATA_B_LENGTH && data_b_l1_len)
+               early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma,
+                               data_b_l1_len);
+
+       early_dma_memcpy_done();
+
+#ifdef CONFIG_ICACHE_FLUSH_L1
+       blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 -
+                       (unsigned long)_stext_l1 + COREB_L1_CODE_START;
+#endif
+}
+#endif
+
 #ifdef CONFIG_ROMKERNEL
 void __init bfin_relocate_xip_data(void)
 {
index c40d07f708e8daabebcecd09fffc960f646dfaab..854fa49f1c3ec964f7f105fd9c0019d133cca420 100644 (file)
@@ -136,7 +136,7 @@ SECTIONS
 
        . = ALIGN(16);
        INIT_DATA_SECTION(16)
-       PERCPU(32, 4)
+       PERCPU(32, PAGE_SIZE)
 
        .exit.data :
        {
@@ -176,6 +176,7 @@ SECTIONS
        {
                . = ALIGN(4);
                __stext_l1 = .;
+               *(.l1.text.head)
                *(.l1.text)
 #ifdef CONFIG_SCHEDULE_L1
                SCHED_TEXT
index 27285823fb252613a1886ea71b48ee07ba200dab..cb1172f5075729994a12c27680b881fba226cffe 100644 (file)
 #define        PGTE_PPI                0x0000                  /*              Enable PPI D15:13                       */
 #define        PGTE_SPORT              0x0800                  /*              Enable DT1PRI/TFS1/TSCLK1       */
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks                                                                                                             */
-#define        HMDMAEN         0x0001  /* Enable Handshake DMA 0/1                                     */
-#define        REP                     0x0002  /* HDMA Request Polarity                                        */
-#define        UTE                     0x0004  /* Urgency Threshold Enable                                     */
-#define        OIE                     0x0010  /* Overflow Interrupt Enable                            */
-#define        BDIE            0x0020  /* Block Done Interrupt Enable                          */
-#define        MBDI            0x0040  /* Mask Block Done IRQ If Pending ECNT          */
-#define        DRQ                     0x0300  /* HDMA Request Type                                            */
-#define        DRQ_NONE        0x0000  /*              No Request                                                      */
-#define        DRQ_SINGLE      0x0100  /*              Channels Request Single                         */
-#define        DRQ_MULTI       0x0200  /*              Channels Request Multi (Default)        */
-#define        DRQ_URGENT      0x0300  /*              Channels Request Multi Urgent           */
-#define        RBC                     0x1000  /* Reload BCNT With IBCNT                                       */
-#define        PS                      0x2000  /* HDMA Pin Status                                                      */
-#define        OI                      0x4000  /* Overflow Interrupt Generated                         */
-#define        BDI                     0x8000  /* Block Done Interrupt Generated                       */
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
index 89f5420ee6cd35592b92c33729ef56560778e0b2..84ef11e52644cea94f70ca235a8b2888cdf0859d 100644 (file)
 #define        PGTE_PPI                0x0000                  /*              Enable PPI D15:13                       */
 #define        PGTE_SPORT              0x0800                  /*              Enable DT1PRI/TFS1/TSCLK1       */
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks                                                                                                             */
-#define        HMDMAEN         0x0001  /* Enable Handshake DMA 0/1                                     */
-#define        REP                     0x0002  /* HDMA Request Polarity                                        */
-#define        UTE                     0x0004  /* Urgency Threshold Enable                                     */
-#define        OIE                     0x0010  /* Overflow Interrupt Enable                            */
-#define        BDIE            0x0020  /* Block Done Interrupt Enable                          */
-#define        MBDI            0x0040  /* Mask Block Done IRQ If Pending ECNT          */
-#define        DRQ                     0x0300  /* HDMA Request Type                                            */
-#define        DRQ_NONE        0x0000  /*              No Request                                                      */
-#define        DRQ_SINGLE      0x0100  /*              Channels Request Single                         */
-#define        DRQ_MULTI       0x0200  /*              Channels Request Multi (Default)        */
-#define        DRQ_URGENT      0x0300  /*              Channels Request Multi Urgent           */
-#define        RBC                     0x1000  /* Reload BCNT With IBCNT                                       */
-#define        PS                      0x2000  /* HDMA Pin Status                                                      */
-#define        OI                      0x4000  /* Overflow Interrupt Generated                         */
-#define        BDI                     0x8000  /* Block Done Interrupt Generated                       */
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
index f869a3711480d233af5e61b9f5292c603709f57f..a377d8afea0389523e386ddc98046af3463ab947 100644 (file)
@@ -289,8 +289,6 @@ static struct platform_device *ip0x_devices[] __initdata = {
 
 static int __init ip0x_init(void)
 {
-       int i;
-
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
 
index 2c776e188a94403929f46e63870f7bc37669b346..d582b810e7a74b1bf3b0bd0a22946a3910845586 100644 (file)
@@ -775,7 +775,7 @@ static int __init cm_bf537e_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-       irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+       irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
        return 0;
 }
index 085661175ec7b0bc73922ce7d61c87dce387a828..cbb8098604c56834a520fe6885247be4220df3f7 100644 (file)
@@ -740,7 +740,7 @@ static int __init cm_bf537u_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-       irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+       irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
        return 0;
 }
index e1e9ea02ad898db7a8bc7fcccf72b434a3bfdc5c..6b4ff4605bffd9f44d12a1f32b4de004acae8429 100644 (file)
@@ -128,30 +128,11 @@ static struct platform_device asmb_flash_device = {
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 
-#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
-
-static int bfin_mmc_spi_init(struct device *dev,
-       irqreturn_t (*detect_int)(int, void *), void *data)
-{
-       return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int,
-               IRQF_TRIGGER_FALLING, "mmc-spi-detect", data);
-}
-
-static void bfin_mmc_spi_exit(struct device *dev, void *data)
-{
-       free_irq(MMC_SPI_CARD_DETECT_INT, data);
-}
-
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
        .enable_dma    = 0,      /* use no dma transfer with this chip*/
        .bits_per_word = 8,
 };
 
-static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
-       .init = bfin_mmc_spi_init,
-       .exit = bfin_mmc_spi_exit,
-       .detect_delay = 100, /* msecs */
-};
 #endif
 
 #if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
@@ -192,7 +173,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .max_speed_hz    = 20000000,
                .bus_num         = 0,
                .chip_select     = 1,
-               .platform_data   = &bfin_mmc_spi_pdata,
                .controller_data = &mmc_spi_chip_info,
                .mode            = SPI_MODE_3,
        },
index 0761b201abcab248d08483af8cb7946ddb124155..164a7e02c022ccdb2971899682d89653c94e3a15 100644 (file)
@@ -742,7 +742,7 @@ static int __init tcm_bf537_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-       irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+       irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
        return 0;
 }
index 725bb35f3aaa035e0bba4483be23d68d23554005..4a031dde173fb0ac965908b10727a95aa87f57cc 100644 (file)
 #define        PGTE_PPI                0x0000  /*              Enable PPI D15:13                       */
 #define        PGTE_SPORT              0x0800  /*              Enable DT1PRI/TFS1/TSCLK1       */
 
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks                                                                                                             */
-#define        HMDMAEN         0x0001  /* Enable Handshake DMA 0/1                                     */
-#define        REP                     0x0002  /* HDMA Request Polarity                                        */
-#define        UTE                     0x0004  /* Urgency Threshold Enable                                     */
-#define        OIE                     0x0010  /* Overflow Interrupt Enable                            */
-#define        BDIE            0x0020  /* Block Done Interrupt Enable                          */
-#define        MBDI            0x0040  /* Mask Block Done IRQ If Pending ECNT          */
-#define        DRQ                     0x0300  /* HDMA Request Type                                            */
-#define        DRQ_NONE        0x0000  /*              No Request                                                      */
-#define        DRQ_SINGLE      0x0100  /*              Channels Request Single                         */
-#define        DRQ_MULTI       0x0200  /*              Channels Request Multi (Default)        */
-#define        DRQ_URGENT      0x0300  /*              Channels Request Multi Urgent           */
-#define        RBC                     0x1000  /* Reload BCNT With IBCNT                                       */
-#define        PS                      0x2000  /* HDMA Pin Status                                                      */
-#define        OI                      0x4000  /* Overflow Interrupt Generated                         */
-#define        BDI                     0x8000  /* Block Done Interrupt Generated                       */
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000 
index 70189a0d1a1905d95dbf6c243f0f1c4e88d6e6d8..94acb586832e69a23036e6967ceb0a3142876d66 100644 (file)
@@ -42,6 +42,65 @@ config BF548_ATAPI_ALTERNATIVE_PORT
          async address or GPIO port F and G. Select y to route it
          to GPIO.
 
+choice
+       prompt "UART2 DMA channel selection"
+       depends on SERIAL_BFIN_UART2
+       default UART2_DMA_RX_ON_DMA18
+       help
+               UART2 DMA channel selection
+               RX -> DMA18
+               TX -> DMA19
+               or
+               RX -> DMA13
+               TX -> DMA14
+
+config UART2_DMA_RX_ON_DMA18
+       bool "UART2 DMA RX -> DMA18 TX -> DMA19"
+       help
+               UART2 DMA channel assignment
+               RX -> DMA18
+               TX -> DMA19
+               use SPORT2 default DMA channel
+
+config UART2_DMA_RX_ON_DMA13
+       bool "UART2 DMA RX -> DMA13 TX -> DMA14"
+       help
+               UART2 DMA channel assignment
+               RX -> DMA13
+               TX -> DMA14
+               use EPPI1 EPPI2 default DMA channel
+endchoice
+
+choice
+       prompt "UART3 DMA channel selection"
+       depends on SERIAL_BFIN_UART3
+       default UART3_DMA_RX_ON_DMA20
+       help
+               UART3 DMA channel selection
+               RX -> DMA20
+               TX -> DMA21
+               or
+               RX -> DMA15
+               TX -> DMA16
+
+config UART3_DMA_RX_ON_DMA20
+       bool "UART3 DMA RX -> DMA20 TX -> DMA21"
+       help
+               UART3 DMA channel assignment
+               RX -> DMA20
+               TX -> DMA21
+               use SPORT3 default DMA channel
+
+config UART3_DMA_RX_ON_DMA15
+       bool "UART3 DMA RX -> DMA15 TX -> DMA16"
+       help
+               UART3 DMA channel assignment
+               RX -> DMA15
+               TX -> DMA16
+               use PIXC default DMA channel
+
+endchoice
+
 comment "Interrupt Priority Assignment"
 menu "Priority"
 
index ce5a2bb147dc273219e5129675072fdc8e1393b2..93e19a54a8803d639fd5586a155954610861dbc7 100644 (file)
@@ -778,11 +778,12 @@ static struct platform_device bfin_sport3_uart_device = {
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-static unsigned short bfin_can_peripherals[] = {
+
+static unsigned short bfin_can0_peripherals[] = {
        P_CAN0_RX, P_CAN0_TX, 0
 };
 
-static struct resource bfin_can_resources[] = {
+static struct resource bfin_can0_resources[] = {
        {
                .start = 0xFFC02A00,
                .end = 0xFFC02FFF,
@@ -805,14 +806,53 @@ static struct resource bfin_can_resources[] = {
        },
 };
 
-static struct platform_device bfin_can_device = {
+static struct platform_device bfin_can0_device = {
        .name = "bfin_can",
-       .num_resources = ARRAY_SIZE(bfin_can_resources),
-       .resource = bfin_can_resources,
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_can0_resources),
+       .resource = bfin_can0_resources,
        .dev = {
-               .platform_data = &bfin_can_peripherals, /* Passed to driver */
+               .platform_data = &bfin_can0_peripherals, /* Passed to driver */
        },
 };
+
+static unsigned short bfin_can1_peripherals[] = {
+       P_CAN1_RX, P_CAN1_TX, 0
+};
+
+static struct resource bfin_can1_resources[] = {
+       {
+               .start = 0xFFC03200,
+               .end = 0xFFC037FF,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_CAN1_RX,
+               .end = IRQ_CAN1_RX,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_CAN1_TX,
+               .end = IRQ_CAN1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_CAN1_ERROR,
+               .end = IRQ_CAN1_ERROR,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_can1_device = {
+       .name = "bfin_can",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_can1_resources),
+       .resource = bfin_can1_resources,
+       .dev = {
+               .platform_data = &bfin_can1_peripherals, /* Passed to driver */
+       },
+};
+
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
@@ -1366,7 +1406,8 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-       &bfin_can_device,
+       &bfin_can0_device,
+       &bfin_can1_device,
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
index 642468c1bcb1ce7d7bc9b00479525d9dda2c7c58..bcccab36629c34295f107f6af44b81e58b9029a7 100644 (file)
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
 #endif /* _DEF_BF544_H */
index 2f3337cd311e880cc37d1f7fdebdc34559bae2b6..1cbba115f96f3d518eead9457913bcd8ca39ab7f 100644 (file)
 
 #define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
-
 #endif /* _DEF_BF547_H */
index a30d242c7398d378269bcd80b3a29d4f86674cc6..1a1091b071fd5a5168c078502dc4325c86fd3a72 100644 (file)
 #define CH_PIXC_OVERLAY                16
 #define CH_PIXC_OUTPUT         17
 #define CH_SPORT2_RX           18
-#define CH_UART2_RX            18
 #define CH_SPORT2_TX           19
-#define CH_UART2_TX            19
 #define CH_SPORT3_RX           20
-#define CH_UART3_RX            20
 #define CH_SPORT3_TX           21
-#define CH_UART3_TX            21
 #define CH_SDH                 22
 #define CH_NFC                 22
 #define CH_SPI2                        23
 
+#if defined(CONFIG_UART2_DMA_RX_ON_DMA13)
+#define CH_UART2_RX            13
+#define IRQ_UART2_RX           BFIN_IRQ(37)    /* UART2 RX USE EPP1 (DMA13) Interrupt */
+#define CH_UART2_TX            14
+#define IRQ_UART2_TX           BFIN_IRQ(38)    /* UART2 RX USE EPP1 (DMA14) Interrupt */
+#else                                          /* Default USE SPORT2's DMA Channel */
+#define CH_UART2_RX            18
+#define IRQ_UART2_RX           BFIN_IRQ(33)    /* UART2 RX (DMA18) Interrupt */
+#define CH_UART2_TX            19
+#define IRQ_UART2_TX           BFIN_IRQ(34)    /* UART2 TX (DMA19) Interrupt */
+#endif
+
+#if defined(CONFIG_UART3_DMA_RX_ON_DMA15)
+#define CH_UART3_RX            15
+#define IRQ_UART3_RX           BFIN_IRQ(64)    /* UART3 RX USE PIXC IN0 (DMA15) Interrupt */
+#define CH_UART3_TX            16
+#define IRQ_UART3_TX           BFIN_IRQ(65)    /* UART3 TX USE PIXC IN1 (DMA16) Interrupt */
+#else                                          /* Default USE SPORT3's DMA Channel */
+#define CH_UART3_RX            20
+#define IRQ_UART3_RX           BFIN_IRQ(35)    /* UART3 RX (DMA20) Interrupt */
+#define CH_UART3_TX            21
+#define IRQ_UART3_TX           BFIN_IRQ(36)    /* UART3 TX (DMA21) Interrupt */
+#endif
+
 #define CH_MEM_STREAM0_DEST    24
 #define CH_MEM_STREAM0_SRC     25
 #define CH_MEM_STREAM1_DEST    26
index 99fd1b2c53d8c3c3534fece60bcc3991bd97d193..7f87787e77382279a35a75b0f65a1ea3bbbdf505 100644 (file)
@@ -74,13 +74,9 @@ Events         (highest priority)  EMU         0
 #define IRQ_UART2_ERROR                BFIN_IRQ(31)    /* UART2 Status (Error) Interrupt */
 #define IRQ_CAN0_ERROR         BFIN_IRQ(32)    /* CAN0 Status (Error) Interrupt */
 #define IRQ_SPORT2_RX          BFIN_IRQ(33)    /* SPORT2 RX (DMA18) Interrupt */
-#define IRQ_UART2_RX           BFIN_IRQ(33)    /* UART2 RX (DMA18) Interrupt */
 #define IRQ_SPORT2_TX          BFIN_IRQ(34)    /* SPORT2 TX (DMA19) Interrupt */
-#define IRQ_UART2_TX           BFIN_IRQ(34)    /* UART2 TX (DMA19) Interrupt */
 #define IRQ_SPORT3_RX          BFIN_IRQ(35)    /* SPORT3 RX (DMA20) Interrupt */
-#define IRQ_UART3_RX           BFIN_IRQ(35)    /* UART3 RX (DMA20) Interrupt */
 #define IRQ_SPORT3_TX          BFIN_IRQ(36)    /* SPORT3 TX (DMA21) Interrupt */
-#define IRQ_UART3_TX           BFIN_IRQ(36)    /* UART3 TX (DMA21) Interrupt */
 #define IRQ_EPPI1              BFIN_IRQ(37)    /* EPP1 (DMA13) Interrupt */
 #define IRQ_EPPI2              BFIN_IRQ(38)    /* EPP2 (DMA14) Interrupt */
 #define IRQ_SPI1               BFIN_IRQ(39)    /* SPI1 (DMA5) Interrupt */
index 3b67929d4c0a5c75c25c1e29c311b0656fcc23e7..87595cd38afe1edc0c0ac9bd2f366f21389187c3 100644 (file)
@@ -541,7 +541,7 @@ static int __init cm_bf561_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-       irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+       irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
        return 0;
 }
index 4cd3b28cd046d86d51973fe0037abdeb63279ea6..42fc085629c7693d43789f6a7c248503c81f6089 100644 (file)
@@ -5,30 +5,27 @@
  * Licensed under the GPL-2 or later.
  */
 
+#include <linux/smp.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/smp.h>
-
-#define SIC_SYSIRQ(irq)        (irq - (IRQ_CORETMR + 1))
+#include <mach/pll.h>
 
 int hotplug_coreb;
 
 void platform_cpu_die(void)
 {
-       unsigned long iwr[2] = {0, 0};
-       unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32;
-       unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32);
-
+       unsigned long iwr;
        hotplug_coreb = 1;
 
-       iwr[bank] = bit;
-
        /* disable core timer */
        bfin_write_TCNTL(0);
 
-       /* clear ipi interrupt IRQ_SUPPLE_0 */
+       /* clear ipi interrupt IRQ_SUPPLE_0 of CoreB */
        bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1)));
        SSYNC();
 
-       coreb_sleep(iwr[0], iwr[1], 0);
+       /* set CoreB wakeup by ipi0, iwr will be discarded */
+       bfin_iwr_set_sup0(&iwr, &iwr, &iwr);
+       SSYNC();
+
+       coreb_die();
 }
index 4624eebbf9c4c92b5e95220282b3f676dd6dbf76..4c462838f4e1fc0f45123d6415fb445441d7d6c3 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
 
-__INIT
+/*
+ * This code must come first as CoreB is hardcoded (in hardware)
+ * to start at the beginning of its L1 instruction memory.
+ */
+.section .l1.text.head
 
 /* Lay the initial stack into the L1 scratch area of Core B */
 #define INITIAL_STACK  (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
@@ -160,43 +164,34 @@ ENTRY(_coreb_trampoline_start)
 .LWAIT_HERE:
        jump .LWAIT_HERE;
 ENDPROC(_coreb_trampoline_start)
-ENTRY(_coreb_trampoline_end)
 
+#ifdef CONFIG_HOTPLUG_CPU
 .section ".text"
-ENTRY(_set_sicb_iwr)
-       P0.H = hi(SICB_IWR0);
-       P0.L = lo(SICB_IWR0);
-       P1.H = hi(SICB_IWR1);
-       P1.L = lo(SICB_IWR1);
-       [P0] = R0;
-       [P1] = R1;
-       SSYNC;
-       RTS;
-ENDPROC(_set_sicb_iwr)
-
-ENTRY(_coreb_sleep)
+ENTRY(_coreb_die)
        sp.l = lo(INITIAL_STACK);
        sp.h = hi(INITIAL_STACK);
        fp = sp;
        usp = sp;
 
-       call _set_sicb_iwr;
-
        CLI R2;
        SSYNC;
        IDLE;
        STI R2;
 
        R0 = IWR_DISABLE_ALL;
-       R1 = IWR_DISABLE_ALL;
-       call _set_sicb_iwr;
+       P0.H = hi(SYSMMR_BASE);
+       P0.L = lo(SYSMMR_BASE);
+       [P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0;
+       [P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0;
+       SSYNC;
 
        p0.h = hi(COREB_L1_CODE_START);
        p0.l = lo(COREB_L1_CODE_START);
        jump (p0);
-ENDPROC(_coreb_sleep)
+ENDPROC(_coreb_die)
+#endif
 
-__CPUINIT
+__INIT
 ENTRY(_coreb_start)
        [--sp] = reti;
 
index 1074a7ef81c7ec3b530ef932212e9f5a2af9e238..5d68bf613b0b9dbe0fde9e2e3055fe23c0375f63 100644 (file)
@@ -30,18 +30,11 @@ void __init platform_init_cpus(void)
 
 void __init platform_prepare_cpus(unsigned int max_cpus)
 {
-       int len;
-
-       len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
-       BUG_ON(len > L1_CODE_LENGTH);
-
-       dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len);
+       bfin_relocate_coreb_l1_mem();
 
        /* Both cores ought to be present on a bf561! */
        cpu_set(0, cpu_present_map); /* CoreA */
        cpu_set(1, cpu_present_map); /* CoreB */
-
-       printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START);
 }
 
 int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
@@ -161,9 +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);
+
        bfin_coretmr_init();
        bfin_coretmr_clockevent_init();
-       get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR);
+
+       chip->irq_unmask(&desc->irq_data);
 #else
        /* Power down the core timer, just to play safe. */
        bfin_write_TCNTL(0);
index bceb98126c21e8eb4f71cb1a44e2110e0c08c49f..d8643fdd0fcf1d9ccc7812c7a46c9fd822d08213 100644 (file)
@@ -61,6 +61,6 @@
 # error "Anomaly 05000220 does not allow you to use Write Back cache with L2 or External Memory"
 #endif
 
-#if ANOMALY_05000491 && !defined(CONFIG_CACHE_FLUSH_L1)
+#if ANOMALY_05000491 && !defined(CONFIG_ICACHE_FLUSH_L1)
 # error You need IFLUSH in L1 inst while Anomaly 05000491 applies
 #endif
index ab4a925a443e4e82001df0beb146b7b7b8e3b40a..9f4dd35bfd743fbc91cf680c6f4cc90867fc0a05 100644 (file)
 #include <asm/cache.h>
 #include <asm/page.h>
 
-#ifdef CONFIG_CACHE_FLUSH_L1
-.section .l1.text
-#else
-.text
-#endif
-
 /* 05000443 - IFLUSH cannot be last instruction in hardware loop */
 #if ANOMALY_05000443
 # define BROK_FLUSH_INST "IFLUSH"
        RTS;
 .endm
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* Invalidate all instruction cache lines assocoiated with this memory area */
+#ifdef CONFIG_SMP
+# define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1
+#endif
 ENTRY(_blackfin_icache_flush_range)
        do_flush IFLUSH
 ENDPROC(_blackfin_icache_flush_range)
 
+#ifdef CONFIG_SMP
+.text
+# undef _blackfin_icache_flush_range
+ENTRY(_blackfin_icache_flush_range)
+       p0.L = LO(DSPID);
+       p0.H = HI(DSPID);
+       r3 = [p0];
+       r3 = r3.b (z);
+       p2 = r3;
+       p0.L = _blackfin_iflush_l1_entry;
+       p0.H = _blackfin_iflush_l1_entry;
+       p0 = p0 + (p2 << 2);
+       p1 = [p0];
+       jump (p1);
+ENDPROC(_blackfin_icache_flush_range)
+#endif
+
+#ifdef CONFIG_DCACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* Throw away all D-cached data in specified region without any obligation to
  * write them back.  Since the Blackfin ISA does not have an "invalidate"
  * instruction, we use flush/invalidate.  Perhaps as a speed optimization we
index f4cf11d362e1df4f67315a68714cac5faf6b293b..85dc6d69f9c02e1c58a8f438b8bbedf75aba50f3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Blackfin core clock scaling
  *
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
 #include <asm/time.h>
 #include <asm/dpmc.h>
 
-#define CPUFREQ_CPU 0
-
 /* this is the table of CCLK frequencies, in Hz */
-/* .index is the entry in the auxillary dpm_state_table[] */
+/* .index is the entry in the auxiliary dpm_state_table[] */
 static struct cpufreq_frequency_table bfin_freq_table[] = {
        {
                .frequency = CPUFREQ_TABLE_END,
@@ -46,7 +44,7 @@ static struct bfin_dpm_state {
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
 /*
- * normalized to maximum frequncy offset for CYCLES,
+ * normalized to maximum frequency offset for CYCLES,
  * used in time-ts cycles clock source, but could be used
  * somewhere also.
  */
index 02c7efd1bcf4807939135734a5f41e159b1af224..382099fd55619be3a4f1d40c99cdf034143943a4 100644 (file)
@@ -61,17 +61,63 @@ err_out:
 }
 
 #ifdef CONFIG_CPU_FREQ
+# ifdef CONFIG_SMP
+static void bfin_idle_this_cpu(void *info)
+{
+       unsigned long flags = 0;
+       unsigned long iwr0, iwr1, iwr2;
+       unsigned int cpu = smp_processor_id();
+
+       local_irq_save_hw(flags);
+       bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2);
+
+       platform_clear_ipi(cpu, IRQ_SUPPLE_0);
+       SSYNC();
+       asm("IDLE;");
+       bfin_iwr_restore(iwr0, iwr1, iwr2);
+
+       local_irq_restore_hw(flags);
+}
+
+static void bfin_idle_cpu(void)
+{
+       smp_call_function(bfin_idle_this_cpu, NULL, 0);
+}
+
+static void bfin_wakeup_cpu(void)
+{
+       unsigned int cpu;
+       unsigned int this_cpu = smp_processor_id();
+       cpumask_t mask = cpu_online_map;
+
+       cpu_clear(this_cpu, mask);
+       for_each_cpu_mask(cpu, mask)
+               platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+}
+
+# else
+static void bfin_idle_cpu(void) {}
+static void bfin_wakeup_cpu(void) {}
+# endif
+
 static int
 vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct cpufreq_freqs *freq = data;
 
+       if (freq->cpu != CPUFREQ_CPU)
+               return 0;
+
        if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
+               bfin_idle_cpu();
                bfin_set_vlev(bfin_get_vlev(freq->new));
                udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
-
-       } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)
+               bfin_wakeup_cpu();
+       } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) {
+               bfin_idle_cpu();
                bfin_set_vlev(bfin_get_vlev(freq->new));
+               bfin_wakeup_cpu();
+       }
 
        return 0;
 }
index bc08c98d008d8cf66e806476f4ce570b6cae396e..757943f620e78d2e595adba535c0404773bb5421 100644 (file)
@@ -952,8 +952,17 @@ ENDPROC(_evt_up_evt14)
 #ifdef CONFIG_IPIPE
 
 _resume_kernel_from_int:
+       r1 = LO(~0x8000) (Z);
+       r1 = r0 & r1;
+       r0 = 1;
+       r0 = r1 - r0;
+       r2 = r1 & r0;
+       cc = r2 == 0;
+       /* Sync the root stage only from the outer interrupt level. */
+       if !cc jump .Lnosync;
        r0.l = ___ipipe_sync_root;
        r0.h = ___ipipe_sync_root;
+       [--sp] = reti;
        [--sp] = rets;
        [--sp] = ( r7:4, p5:3 );
        SP += -12;
@@ -961,6 +970,8 @@ _resume_kernel_from_int:
        SP += 12;
        ( r7:4, p5:3 ) = [sp++];
        rets = [sp++];
+       reti = [sp++];
+.Lnosync:
        rts
 #elif defined(CONFIG_PREEMPT)
 
@@ -1738,6 +1749,9 @@ ENTRY(_sys_call_table)
        .long _sys_fanotify_mark
        .long _sys_prlimit64
        .long _sys_cacheflush
+       .long _sys_name_to_handle_at    /* 375 */
+       .long _sys_open_by_handle_at
+       .long _sys_clock_adjtime
 
        .rept NR_syscalls-(.-_sys_call_table)/4
        .long _sys_ni_syscall
index 4391621d90488a1fcb7f89f72efca8bf707ecc6a..581e2b0a71ace2468cbb29e7b82ecd2f179ae3e7 100644 (file)
@@ -31,6 +31,7 @@ ENDPROC(__init_clear_bss)
 ENTRY(__start)
        /* R0: argument of command line string, passed from uboot, save it */
        R7 = R0;
+
        /* Enable Cycle Counter and Nesting Of Interrupts */
 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
        R0 = SYSCFG_SNEN;
@@ -38,76 +39,49 @@ ENTRY(__start)
        R0 = SYSCFG_SNEN | SYSCFG_CCEN;
 #endif
        SYSCFG = R0;
-       R0 = 0;
-
-       /* Clear Out All the data and pointer Registers */
-       R1 = R0;
-       R2 = R0;
-       R3 = R0;
-       R4 = R0;
-       R5 = R0;
-       R6 = R0;
-
-       P0 = R0;
-       P1 = R0;
-       P2 = R0;
-       P3 = R0;
-       P4 = R0;
-       P5 = R0;
-
-       LC0 = r0;
-       LC1 = r0;
-       L0 = r0;
-       L1 = r0;
-       L2 = r0;
-       L3 = r0;
-
-       /* Clear Out All the DAG Registers */
-       B0 = r0;
-       B1 = r0;
-       B2 = r0;
-       B3 = r0;
-
-       I0 = r0;
-       I1 = r0;
-       I2 = r0;
-       I3 = r0;
-
-       M0 = r0;
-       M1 = r0;
-       M2 = r0;
-       M3 = r0;
+
+       /* Optimization register tricks: keep a base value in the
+        * reserved P registers so we use the load/store with an
+        * offset syntax.  R0 = [P5 + <constant>];
+        *   P5 - core MMR base
+        *   R6 - 0
+        */
+       r6 = 0;
+       p5.l = 0;
+       p5.h = hi(COREMMR_BASE);
+
+       /* Zero out registers required by Blackfin ABI */
+
+       /* Disable circular buffers */
+       L0 = r6;
+       L1 = r6;
+       L2 = r6;
+       L3 = r6;
+
+       /* Disable hardware loops in case we were started by 'go' */
+       LC0 = r6;
+       LC1 = r6;
 
        /*
         * Clear ITEST_COMMAND and DTEST_COMMAND registers,
         * Leaving these as non-zero can confuse the emulator
         */
-       p0.L = LO(DTEST_COMMAND);
-       p0.H = HI(DTEST_COMMAND);
-       [p0] = R0;
-       [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0;
+       [p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
+       [p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
        CSYNC;
 
        trace_buffer_init(p0,r0);
-       P0 = R1;
-       R0 = R1;
 
        /* Turn off the icache */
-       p0.l = LO(IMEM_CONTROL);
-       p0.h = HI(IMEM_CONTROL);
-       R1 = [p0];
-       R0 = ~ENICPLB;
-       R0 = R0 & R1;
-       [p0] = R0;
+       r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
+       BITCLR (r1, ENICPLB_P);
+       [p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
        SSYNC;
 
        /* Turn off the dcache */
-       p0.l = LO(DMEM_CONTROL);
-       p0.h = HI(DMEM_CONTROL);
-       R1 = [p0];
-       R0 = ~ENDCPLB;
-       R0 = R0 & R1;
-       [p0] = R0;
+       r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
+       BITCLR (r1, ENDCPLB_P);
+       [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
        SSYNC;
 
        /* in case of double faults, save a few things */
@@ -122,25 +96,25 @@ ENTRY(__start)
         * below
         */
        GET_PDA(p0, r0);
-       r6 = [p0 + PDA_DF_RETX];
+       r5 = [p0 + PDA_DF_RETX];
        p1.l = _init_saved_retx;
        p1.h = _init_saved_retx;
-       [p1] = r6;
+       [p1] = r5;
 
-       r6 = [p0 + PDA_DF_DCPLB];
+       r5 = [p0 + PDA_DF_DCPLB];
        p1.l = _init_saved_dcplb_fault_addr;
        p1.h = _init_saved_dcplb_fault_addr;
-       [p1] = r6;
+       [p1] = r5;
 
-       r6 = [p0 + PDA_DF_ICPLB];
+       r5 = [p0 + PDA_DF_ICPLB];
        p1.l = _init_saved_icplb_fault_addr;
        p1.h = _init_saved_icplb_fault_addr;
-       [p1] = r6;
+       [p1] = r5;
 
-       r6 = [p0 + PDA_DF_SEQSTAT];
+       r5 = [p0 + PDA_DF_SEQSTAT];
        p1.l = _init_saved_seqstat;
        p1.h = _init_saved_seqstat;
-       [p1] = r6;
+       [p1] = r5;
 #endif
 
        /* Initialize stack pointer */
@@ -155,7 +129,7 @@ ENTRY(__start)
        sti r0;
 #endif
 
-       r0 = 0 (x);
+       r0 = r6;
        /* Zero out all of the fun bss regions */
 #if L1_DATA_A_LENGTH > 0
        r1.l = __sbss_l1;
@@ -210,11 +184,9 @@ ENTRY(__start)
 
        /* EVT15 = _real_start */
 
-       p0.l = lo(EVT15);
-       p0.h = hi(EVT15);
        p1.l = _real_start;
        p1.h = _real_start;
-       [p0] = p1;
+       [p5 + (EVT15 - COREMMR_BASE)] = p1;
        csync;
 
 #ifdef CONFIG_EARLY_PRINTK
index 2df37db3b49b60dbe9df7e768b0fb31cf5946c69..469ce7282dc8b5f0d789382712be43924543a4e0 100644 (file)
@@ -274,16 +274,16 @@ ENDPROC(_evt_system_call)
  * level to EVT14 to prepare the caller for a normal interrupt
  * return through RTI.
  *
- * We currently use this facility in two occasions:
+ * We currently use this feature in two occasions:
  *
- * - to branch to __ipipe_irq_tail_hook as requested by a high
+ * - before branching to __ipipe_irq_tail_hook as requested by a high
  *   priority domain after the pipeline delivered an interrupt,
  *   e.g. such as Xenomai, in order to start its rescheduling
  *   procedure, since we may not switch tasks when IRQ levels are
  *   nested on the Blackfin, so we have to fake an interrupt return
  *   so that we may reschedule immediately.
  *
- * - to branch to sync_root_irqs, in order to play any interrupt
+ * - before branching to __ipipe_sync_root(), in order to play any interrupt
  *   pending for the root domain (i.e. the Linux kernel). This lowers
  *   the core priority level enough so that Linux IRQ handlers may
  *   never delay interrupts handled by high priority domains; we defer
index a604f19d8dc315df316058942042ef7ee9f8b5b6..6cd52395a999866f778d6d89e8b879ee7ab8386e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
+#include <linux/sched.h>
 #ifdef CONFIG_IPIPE
 #include <linux/ipipe.h>
 #endif
@@ -124,21 +125,21 @@ static void __init search_IAR(void)
  * This is for core internal IRQs
  */
 
-static void bfin_ack_noop(unsigned int irq)
+static void bfin_ack_noop(struct irq_data *d)
 {
        /* Dummy function.  */
 }
 
-static void bfin_core_mask_irq(unsigned int irq)
+static void bfin_core_mask_irq(struct irq_data *d)
 {
-       bfin_irq_flags &= ~(1 << irq);
+       bfin_irq_flags &= ~(1 << d->irq);
        if (!hard_irqs_disabled())
                hard_local_irq_enable();
 }
 
-static void bfin_core_unmask_irq(unsigned int irq)
+static void bfin_core_unmask_irq(struct irq_data *d)
 {
-       bfin_irq_flags |= 1 << irq;
+       bfin_irq_flags |= 1 << d->irq;
        /*
         * If interrupts are enabled, IMASK must contain the same value
         * as bfin_irq_flags.  Make sure that invariant holds.  If interrupts
@@ -176,6 +177,11 @@ static void bfin_internal_mask_irq(unsigned int irq)
        hard_local_irq_restore(flags);
 }
 
+static void bfin_internal_mask_irq_chip(struct irq_data *d)
+{
+       bfin_internal_mask_irq(d->irq);
+}
+
 #ifdef CONFIG_SMP
 static void bfin_internal_unmask_irq_affinity(unsigned int irq,
                const struct cpumask *affinity)
@@ -211,19 +217,24 @@ static void bfin_internal_unmask_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_SMP
-static void bfin_internal_unmask_irq(unsigned int irq)
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       bfin_internal_unmask_irq_affinity(irq, desc->affinity);
+       bfin_internal_unmask_irq_affinity(d->irq, d->affinity);
 }
 
-static int bfin_internal_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bfin_internal_set_affinity(struct irq_data *d,
+                                     const struct cpumask *mask, bool force)
 {
-       bfin_internal_mask_irq(irq);
-       bfin_internal_unmask_irq_affinity(irq, mask);
+       bfin_internal_mask_irq(d->irq);
+       bfin_internal_unmask_irq_affinity(d->irq, mask);
 
        return 0;
 }
+#else
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
+{
+       bfin_internal_unmask_irq(d->irq);
+}
 #endif
 
 #ifdef CONFIG_PM
@@ -279,28 +290,33 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
 
        return 0;
 }
+
+static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
+{
+       return bfin_internal_set_wake(d->irq, state);
+}
 #endif
 
 static struct irq_chip bfin_core_irqchip = {
        .name = "CORE",
-       .ack = bfin_ack_noop,
-       .mask = bfin_core_mask_irq,
-       .unmask = bfin_core_unmask_irq,
+       .irq_ack = bfin_ack_noop,
+       .irq_mask = bfin_core_mask_irq,
+       .irq_unmask = bfin_core_unmask_irq,
 };
 
 static struct irq_chip bfin_internal_irqchip = {
        .name = "INTN",
-       .ack = bfin_ack_noop,
-       .mask = bfin_internal_mask_irq,
-       .unmask = bfin_internal_unmask_irq,
-       .mask_ack = bfin_internal_mask_irq,
-       .disable = bfin_internal_mask_irq,
-       .enable = bfin_internal_unmask_irq,
+       .irq_ack = bfin_ack_noop,
+       .irq_mask = bfin_internal_mask_irq_chip,
+       .irq_unmask = bfin_internal_unmask_irq_chip,
+       .irq_mask_ack = bfin_internal_mask_irq_chip,
+       .irq_disable = bfin_internal_mask_irq_chip,
+       .irq_enable = bfin_internal_unmask_irq_chip,
 #ifdef CONFIG_SMP
-       .set_affinity = bfin_internal_set_affinity,
+       .irq_set_affinity = bfin_internal_set_affinity,
 #endif
 #ifdef CONFIG_PM
-       .set_wake = bfin_internal_set_wake,
+       .irq_set_wake = bfin_internal_set_wake_chip,
 #endif
 };
 
@@ -312,33 +328,32 @@ static void bfin_handle_irq(unsigned irq)
        __ipipe_handle_irq(irq, &regs);
        ipipe_trace_irq_exit(irq);
 #else /* !CONFIG_IPIPE */
-       struct irq_desc *desc = irq_desc + irq;
-       desc->handle_irq(irq, desc);
+       generic_handle_irq(irq);
 #endif  /* !CONFIG_IPIPE */
 }
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 static int error_int_mask;
 
-static void bfin_generic_error_mask_irq(unsigned int irq)
+static void bfin_generic_error_mask_irq(struct irq_data *d)
 {
-       error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
+       error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR));
        if (!error_int_mask)
                bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
 }
 
-static void bfin_generic_error_unmask_irq(unsigned int irq)
+static void bfin_generic_error_unmask_irq(struct irq_data *d)
 {
        bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
-       error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
+       error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR);
 }
 
 static struct irq_chip bfin_generic_error_irqchip = {
        .name = "ERROR",
-       .ack = bfin_ack_noop,
-       .mask_ack = bfin_generic_error_mask_irq,
-       .mask = bfin_generic_error_mask_irq,
-       .unmask = bfin_generic_error_unmask_irq,
+       .irq_ack = bfin_ack_noop,
+       .irq_mask_ack = bfin_generic_error_mask_irq,
+       .irq_mask = bfin_generic_error_mask_irq,
+       .irq_unmask = bfin_generic_error_unmask_irq,
 };
 
 static void bfin_demux_error_irq(unsigned int int_err_irq,
@@ -448,8 +463,10 @@ static void bfin_mac_status_ack_irq(unsigned int irq)
        }
 }
 
-static void bfin_mac_status_mask_irq(unsigned int irq)
+static void bfin_mac_status_mask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
+
        mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT));
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
        switch (irq) {
@@ -466,8 +483,10 @@ static void bfin_mac_status_mask_irq(unsigned int irq)
        bfin_mac_status_ack_irq(irq);
 }
 
-static void bfin_mac_status_unmask_irq(unsigned int irq)
+static void bfin_mac_status_unmask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
+
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
        switch (irq) {
        case IRQ_MAC_PHYINT:
@@ -484,7 +503,7 @@ static void bfin_mac_status_unmask_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_PM
-int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
+int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state)
 {
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
        return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state);
@@ -496,12 +515,12 @@ int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
 
 static struct irq_chip bfin_mac_status_irqchip = {
        .name = "MACST",
-       .ack = bfin_ack_noop,
-       .mask_ack = bfin_mac_status_mask_irq,
-       .mask = bfin_mac_status_mask_irq,
-       .unmask = bfin_mac_status_unmask_irq,
+       .irq_ack = bfin_ack_noop,
+       .irq_mask_ack = bfin_mac_status_mask_irq,
+       .irq_mask = bfin_mac_status_mask_irq,
+       .irq_unmask = bfin_mac_status_unmask_irq,
 #ifdef CONFIG_PM
-       .set_wake = bfin_mac_status_set_wake,
+       .irq_set_wake = bfin_mac_status_set_wake,
 #endif
 };
 
@@ -538,13 +557,9 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq,
 static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 {
 #ifdef CONFIG_IPIPE
-       _set_irq_handler(irq, handle_level_irq);
-#else
-       struct irq_desc *desc = irq_desc + irq;
-       /* May not call generic set_irq_handler() due to spinlock
-          recursion. */
-       desc->handle_irq = handle;
+       handle = handle_level_irq;
 #endif
+       __set_irq_handler_unlocked(irq, handle);
 }
 
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
@@ -552,17 +567,18 @@ extern void bfin_gpio_irq_prepare(unsigned gpio);
 
 #if !defined(CONFIG_BF54x)
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
        /* AFAIK ack_irq in case mask_ack is provided
         * get's only called for edge sense irqs
         */
-       set_gpio_data(irq_to_gpio(irq), 0);
+       set_gpio_data(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_desc + irq;
+       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)
@@ -571,39 +587,40 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
        set_gpio_maska(gpionr, 0);
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-       set_gpio_maska(irq_to_gpio(irq), 0);
+       set_gpio_maska(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-       set_gpio_maska(irq_to_gpio(irq), 1);
+       set_gpio_maska(irq_to_gpio(d->irq), 1);
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
-       u32 gpionr = irq_to_gpio(irq);
+       u32 gpionr = irq_to_gpio(d->irq);
 
        if (__test_and_set_bit(gpionr, gpio_enabled))
                bfin_gpio_irq_prepare(gpionr);
 
-       bfin_gpio_unmask_irq(irq);
+       bfin_gpio_unmask_irq(d);
 
        return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-       u32 gpionr = irq_to_gpio(irq);
+       u32 gpionr = irq_to_gpio(d->irq);
 
-       bfin_gpio_mask_irq(irq);
+       bfin_gpio_mask_irq(d);
        __clear_bit(gpionr, gpio_enabled);
        bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+       unsigned int irq = d->irq;
        int ret;
        char buf[16];
        u32 gpionr = irq_to_gpio(irq);
@@ -664,9 +681,9 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 }
 
 #ifdef CONFIG_PM
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
-       return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state);
+       return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state);
 }
 #endif
 
@@ -818,10 +835,10 @@ void init_pint_lut(void)
        }
 }
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_desc + irq;
-       u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       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);
 
@@ -835,10 +852,10 @@ static void bfin_gpio_ack_irq(unsigned int irq)
 
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-       struct irq_desc *desc = irq_desc + irq;
-       u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       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);
 
@@ -853,24 +870,25 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
        pint[bank]->mask_clear = pintbit;
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-       u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 
        pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-       u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
        u32 pintbit = PINT_BIT(pint_val);
        u32 bank = PINT_2_BANK(pint_val);
 
        pint[bank]->mask_set = pintbit;
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        u32 gpionr = irq_to_gpio(irq);
        u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
 
@@ -884,22 +902,23 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
        if (__test_and_set_bit(gpionr, gpio_enabled))
                bfin_gpio_irq_prepare(gpionr);
 
-       bfin_gpio_unmask_irq(irq);
+       bfin_gpio_unmask_irq(d);
 
        return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-       u32 gpionr = irq_to_gpio(irq);
+       u32 gpionr = irq_to_gpio(d->irq);
 
-       bfin_gpio_mask_irq(irq);
+       bfin_gpio_mask_irq(d);
        __clear_bit(gpionr, gpio_enabled);
        bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+       unsigned int irq = d->irq;
        int ret;
        char buf[16];
        u32 gpionr = irq_to_gpio(irq);
@@ -961,10 +980,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 u32 pint_saved_masks[NR_PINT_SYS_IRQS];
 u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
 
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
        u32 pint_irq;
-       u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
        u32 bank = PINT_2_BANK(pint_val);
        u32 pintbit = PINT_BIT(pint_val);
 
@@ -1066,17 +1085,17 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
 
 static struct irq_chip bfin_gpio_irqchip = {
        .name = "GPIO",
-       .ack = bfin_gpio_ack_irq,
-       .mask = bfin_gpio_mask_irq,
-       .mask_ack = bfin_gpio_mask_ack_irq,
-       .unmask = bfin_gpio_unmask_irq,
-       .disable = bfin_gpio_mask_irq,
-       .enable = bfin_gpio_unmask_irq,
-       .set_type = bfin_gpio_irq_type,
-       .startup = bfin_gpio_irq_startup,
-       .shutdown = bfin_gpio_irq_shutdown,
+       .irq_ack = bfin_gpio_ack_irq,
+       .irq_mask = bfin_gpio_mask_irq,
+       .irq_mask_ack = bfin_gpio_mask_ack_irq,
+       .irq_unmask = bfin_gpio_unmask_irq,
+       .irq_disable = bfin_gpio_mask_irq,
+       .irq_enable = bfin_gpio_unmask_irq,
+       .irq_set_type = bfin_gpio_irq_type,
+       .irq_startup = bfin_gpio_irq_startup,
+       .irq_shutdown = bfin_gpio_irq_shutdown,
 #ifdef CONFIG_PM
-       .set_wake = bfin_gpio_set_wake,
+       .irq_set_wake = bfin_gpio_set_wake,
 #endif
 };
 
@@ -1373,7 +1392,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
        struct ipipe_domain *this_domain = __ipipe_current_domain;
        struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
        struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
-       int irq, s;
+       int irq, s = 0;
 
        if (likely(vec == EVT_IVTMR_P))
                irq = IRQ_CORETMR;
@@ -1423,6 +1442,21 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
                        __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
        }
 
+       /*
+        * We don't want Linux interrupt handlers to run at the
+        * current core priority level (i.e. < EVT15), since this
+        * might delay other interrupts handled by a high priority
+        * domain. Here is what we do instead:
+        *
+        * - we raise the SYNCDEFER bit to prevent
+        * __ipipe_handle_irq() to sync the pipeline for the root
+        * stage for the incoming interrupt. Upon return, that IRQ is
+        * pending in the interrupt log.
+        *
+        * - we raise the TIF_IRQ_SYNC bit for the current thread, so
+        * that _schedule_and_signal_from_int will eventually sync the
+        * pipeline from EVT15.
+        */
        if (this_domain == ipipe_root_domain) {
                s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
                barrier();
@@ -1432,6 +1466,24 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
        __ipipe_handle_irq(irq, regs);
        ipipe_trace_irq_exit(irq);
 
+       if (user_mode(regs) &&
+           !ipipe_test_foreign_stack() &&
+           (current->ipipe_flags & PF_EVTRET) != 0) {
+               /*
+                * Testing for user_regs() does NOT fully eliminate
+                * foreign stack contexts, because of the forged
+                * interrupt returns we do through
+                * __ipipe_call_irqtail. In that case, we might have
+                * preempted a foreign stack context in a high
+                * priority domain, with a single interrupt level now
+                * pending after the irqtail unwinding is done. In
+                * which case user_mode() is now true, and the event
+                * gets dispatched spuriously.
+                */
+               current->ipipe_flags &= ~PF_EVTRET;
+               __ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
+       }
+
        if (this_domain == ipipe_root_domain) {
                set_thread_flag(TIF_IRQ_SYNC);
                if (!s) {
index 9f251406a76aced1985dc69f3d461ad5bf5bdaca..6e17a265c4d3158761450463b3c5a66e63a39bab 100644 (file)
  */
 struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
+
 void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
        *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
        *init_saved_dcplb_fault_addr_coreb;
@@ -105,10 +109,10 @@ static void ipi_flush_icache(void *info)
        struct blackfin_flush_data *fdata = info;
 
        /* Invalidate the memory holding the bounds of the flushed region. */
-       blackfin_dcache_invalidate_range((unsigned long)fdata,
-                                        (unsigned long)fdata + sizeof(*fdata));
+       invalidate_dcache_range((unsigned long)fdata,
+               (unsigned long)fdata + sizeof(*fdata));
 
-       blackfin_icache_flush_range(fdata->start, fdata->end);
+       flush_icache_range(fdata->start, fdata->end);
 }
 
 static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
@@ -244,12 +248,13 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
 {
        cpumask_t callmap;
 
+       preempt_disable();
        callmap = cpu_online_map;
        cpu_clear(smp_processor_id(), callmap);
-       if (cpus_empty(callmap))
-               return 0;
+       if (!cpus_empty(callmap))
+               smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
 
-       smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
+       preempt_enable();
 
        return 0;
 }
@@ -286,12 +291,13 @@ void smp_send_stop(void)
 {
        cpumask_t callmap;
 
+       preempt_disable();
        callmap = cpu_online_map;
        cpu_clear(smp_processor_id(), callmap);
-       if (cpus_empty(callmap))
-               return;
+       if (!cpus_empty(callmap))
+               smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
 
-       smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+       preempt_enable();
 
        return;
 }
@@ -361,8 +367,6 @@ void __cpuinit secondary_start_kernel(void)
         */
        init_exception_vectors();
 
-       bfin_setup_caches(cpu);
-
        local_irq_disable();
 
        /* Attach the new idle task to the global mm. */
@@ -381,6 +385,8 @@ void __cpuinit secondary_start_kernel(void)
 
        local_irq_enable();
 
+       bfin_setup_caches(cpu);
+
        /*
         * Calibrate loops per jiffy value.
         * IRQs need to be enabled here - D-cache can be invalidated
index d6189e057ed354804f04822ee78e73f2e069b827..6745cb1ffb4f71340f50a3710f9f8ec9bc2c840e 100644 (file)
@@ -5,7 +5,7 @@
 #
 
 targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS   := -traditional
+asflags-y      := -traditional
 
 OBJECTS = $(obj)/head.o $(obj)/misc.o
 
index 1089b3e918ace7d533bbecd96de0be54deb26cad..db3d7c5d10711a1d0357a0c179e752f1d6f0df58 100644 (file)
@@ -45,8 +45,8 @@ FORCE : $(obj)/$(offsets-file)
 # Makefile for Kernel-based Virtual Machine module
 #
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
-EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
+ccflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
+asflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
                coalesced_mmio.o irq_comm.o assigned-dev.o)
index 0591038735af53e40e128dd0b7fc0e4f4e7ab286..d27df1d45da7b224a184758b831d264030169903 100644 (file)
@@ -7,7 +7,7 @@
 # Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y                          += setup.o bte.o bte_error.o irq.o mca.o idle.o \
                                   huberror.o io_acpi_init.o io_common.o \
index 08e6565dc908d0b0f5e8358a14698211439bb1c0..3d09108d42776658d193c9e57b59becdfadec881 100644 (file)
@@ -9,7 +9,7 @@
 # sn2 specific kernel files
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
         prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
index ad4ef34dfe263cd66b496c445fd26e61246d02b7..df2a9014542664cf34b0c6f89b76fa898f95bb6d 100644 (file)
@@ -7,6 +7,6 @@
 #
 # Makefile for the sn pci general routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
index 01192d3247ddef19b1388cf39be80c03e3ee6d88..396bcae36309ab35e45e827546fd48db3b55e88e 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Makefile for the sn2 io routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y                          +=  pcibr_dma.o pcibr_reg.o \
                                    pcibr_ate.o pcibr_provider.o
index 8d92b4684d8e06714b06fbaacfcaec452c58a086..124e441d383d89d72ef72a5965e1d4875ece3b79 100644 (file)
@@ -7,7 +7,7 @@
 # Copyright (C) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y                          += setup.o
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
index 59cc7bceaf8c493d35ef426e9bafaad914dbf3ab..fceed4edea41966a4de1502b52d745b452966bbf 100644 (file)
@@ -6,7 +6,7 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_cache.o = -pg
 endif
 
-EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
+ccflags-y := -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
                -DCPU_REV=$(CPU_REV)
 
 obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o
index 7c1102e41fe25b917dcce6566c0bf494ceef867e..ac1d5b611a27d2ea08d34cf983bbef5f94f1776e 100644 (file)
@@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 archprepare:
 ifdef CONFIG_MIPS32_N32
        @echo '  Checking missing-syscalls for N32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
        @echo '  Checking missing-syscalls for O32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
 endif
 
 install:
index e5cc86dc1da83de4d2b09f6d134a81f1089bb1df..9f64fb41407743358f55a36377617613fb9a0383 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_BOARD_BCM963XX)           += board_bcm963xx.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index e0aaad482b0ebc806e971101a4f701ff30d2848e..5314b37aff2c493a736eb438a47f03d33cba509f 100644 (file)
@@ -9,4 +9,4 @@ lib-$(CONFIG_ARC_MEMORY)        += memory.o
 lib-$(CONFIG_ARC_CONSOLE)      += arc_con.o
 lib-$(CONFIG_ARC_PROMLIB)      += promlib.o
 
-EXTRA_CFLAGS                   += -Werror
+ccflags-y                      := -Werror
index a604eaeb6c08533616839485b6f8fc89a032ed2b..a9dff33212518d752b8620a969a79da3935543d1 100644 (file)
@@ -17,4 +17,4 @@ obj-$(CONFIG_JZ4740_QI_LB60)  += board-qi_lb60.o
 
 obj-$(CONFIG_PM) += pm.o
 
-EXTRA_CFLAGS += -Werror -Wall
+ccflags-y := -Werror -Wall
index 02cc65e52d11b47574b2940e5859a733f7d0fd85..4b9d7044e26c236b87f3f4497cacd5acd1cc7e4b 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -Werror
+ccflags-y := -Werror
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
index b16f95c3df654a089a33b7b9655228863421e865..02f5fb94ea2808a5bf580679421598e0659961d2 100644 (file)
@@ -6,4 +6,4 @@ obj-y    += irq.o prom.o py-console.o setup.o
 
 obj-$(CONFIG_SMP)              += smp.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index baf6e9092a9f84b941b37986dac89a289b5225a8..348d2e850ef5128d42a34fe761fe357fdb5fc5ff 100644 (file)
@@ -28,4 +28,4 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
 
 obj-$(CONFIG_USB) += powertv-usb.o
 
-EXTRA_CFLAGS += -Wall
+ccflags-y := -Wall
index f0e95dc0ac97b4f63e924f3ae4387eb49e73199b..d810a33182a4a6b76a250e86532930b2f4d23f98 100644 (file)
@@ -20,4 +20,4 @@ obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
        asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
        prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
index f5c62462fc9daf458b8248331dca8b6672a8bf7b..5783201cd2c81196659939f6ba495069118e6281 100644 (file)
@@ -18,4 +18,4 @@
 
 obj-$(CONFIG_PCI)      += fixup-powertv.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
index 243bfa23fd5863c0d8198d61352b2c0a8db9812a..10971be4306156a5eddc22746246c7a80dd83ea7 100644 (file)
@@ -1,7 +1,8 @@
 config MN10300
        def_bool y
        select HAVE_OPROFILE
-       select GENERIC_HARDIRQS
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config AM33_2
        def_bool n
@@ -53,21 +54,6 @@ config GENERIC_TIME
 config GENERIC_CLOCKEVENTS
        def_bool y
 
-config GENERIC_CLOCKEVENTS_BUILD
-       def_bool y
-       depends on GENERIC_CLOCKEVENTS
-
-config GENERIC_CLOCKEVENTS_BROADCAST
-       bool
-
-config CEVT_MN10300
-       def_bool y
-       depends on GENERIC_CLOCKEVENTS
-
-config CSRC_MN10300
-       def_bool y
-       depends on GENERIC_TIME
-
 config GENERIC_BUG
        def_bool y
 
index 585b708c2bc0620fb37b56df22a33df91e8ad5a1..d65bbeebe50a6253fcc76f96367a444d12a89c4f 100644 (file)
 
 #ifndef __ASSEMBLY__
 extern void set_intr_level(int irq, u16 level);
-extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
-extern void mn10300_intc_clear(unsigned int irq);
-extern void mn10300_intc_set(unsigned int irq);
-extern void mn10300_intc_enable(unsigned int irq);
-extern void mn10300_intc_disable(unsigned int irq);
 extern void mn10300_set_lateack_irq_type(int irq);
 #endif
 
index 8f5f1e81baf5c1527a2a82d1380f88918dd38d07..a06a2e10051d52b7a53e1227826325427cff9c0d 100644 (file)
@@ -8,7 +8,8 @@ fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
           ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
-          switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
+          switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+          csrc-mn10300.o cevt-mn10300.o
 
 obj-$(CONFIG_SMP) += smp.o smp-low.o
 
@@ -28,5 +29,3 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o
-obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o
index d4cb535bf7863750768090ed049d7702a9649e04..69cae0260786207d0c3b62fde6255f6b2f442995 100644 (file)
@@ -89,9 +89,10 @@ int __init init_clockevents(void)
        cd->name                = "Timestamp";
        cd->features            = CLOCK_EVT_FEAT_ONESHOT;
 
-       /* Calculate the min / max delta */
-       clockevent_set_clock(cd, MN10300_JCCLK);
+       /* Calculate shift/mult. We want to spawn at least 1 second */
+       clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1);
 
+       /* Calculate the min / max delta */
        cd->max_delta_ns        = clockevent_delta2ns(TMJCBR_MAX, cd);
        cd->min_delta_ns        = clockevent_delta2ns(100, cd);
 
@@ -110,9 +111,9 @@ int __init init_clockevents(void)
 #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
        /* setup timer irq affinity so it only runs on this cpu */
        {
-               struct irq_desc *desc;
-               desc = irq_to_desc(cd->irq);
-               cpumask_copy(desc->affinity, cpumask_of(cpu));
+               struct irq_data *data;
+               data = irq_get_irq_data(cd->irq);
+               cpumask_copy(data->affinity, cpumask_of(cpu));
                iact->flags |= IRQF_NOBALANCING;
        }
 #endif
index ba2f0c4d6e01c708309b5178c479c98eb152a5e2..45644cf18c41245904722c405d7faeff4861838a 100644 (file)
@@ -29,7 +29,6 @@ static struct clocksource clocksource_mn10300 = {
 int __init init_clocksource(void)
 {
        startup_timestamp_counter();
-       clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK);
-       clocksource_register(&clocksource_mn10300);
+       clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK);
        return 0;
 }
index 6a064ab5af0774b15887d9432209a9e2f9abe208..ea946613f46d12fb8f57cea490428e740f03015c 100644 (file)
@@ -33,13 +33,3 @@ extern void mn10300_low_ipi_handler(void);
  * time.c
  */
 extern irqreturn_t local_timer_interrupt(void);
-
-/*
- * time.c
- */
-#ifdef CONFIG_CEVT_MN10300
-extern void clockevent_set_clock(struct clock_event_device *, unsigned int);
-#endif
-#ifdef CONFIG_CSRC_MN10300
-extern void clocksource_set_clock(struct clocksource *, unsigned int);
-#endif
index ac11754ecec544c965c196f9dc857b2b398b22e0..f09fed5e6afc21a1f1349cafef258e6cdebed57c 100644 (file)
@@ -37,8 +37,9 @@ atomic_t irq_err_count;
 /*
  * MN10300 interrupt controller operations
  */
-static void mn10300_cpupic_ack(unsigned int irq)
+static void mn10300_cpupic_ack(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        unsigned long flags;
        u16 tmp;
 
@@ -61,13 +62,14 @@ static void __mask_and_set_icr(unsigned int irq,
        arch_local_irq_restore(flags);
 }
 
-static void mn10300_cpupic_mask(unsigned int irq)
+static void mn10300_cpupic_mask(struct irq_data *d)
 {
-       __mask_and_set_icr(irq, GxICR_LEVEL, 0);
+       __mask_and_set_icr(d->irq, GxICR_LEVEL, 0);
 }
 
-static void mn10300_cpupic_mask_ack(unsigned int irq)
+static void mn10300_cpupic_mask_ack(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
 #ifdef CONFIG_SMP
        unsigned long flags;
        u16 tmp;
@@ -85,7 +87,7 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
                tmp2 = GxICR(irq);
 
                irq_affinity_online[irq] =
-                       any_online_cpu(*irq_desc[irq].affinity);
+                       any_online_cpu(*d->affinity);
                CROSS_GxICR(irq, irq_affinity_online[irq]) =
                        (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
                tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -97,13 +99,14 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
 #endif /* CONFIG_SMP */
 }
 
-static void mn10300_cpupic_unmask(unsigned int irq)
+static void mn10300_cpupic_unmask(struct irq_data *d)
 {
-       __mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
+       __mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE);
 }
 
-static void mn10300_cpupic_unmask_clear(unsigned int irq)
+static void mn10300_cpupic_unmask_clear(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        /* the MN10300 PIC latches its interrupt request bit, even after the
         * device has ceased to assert its interrupt line and the interrupt
         * channel has been disabled in the PIC, so for level-triggered
@@ -121,7 +124,7 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
        } else {
                tmp = GxICR(irq);
 
-               irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
+               irq_affinity_online[irq] = any_online_cpu(*d->affinity);
                CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
                tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
        }
@@ -134,7 +137,8 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
 
 #ifdef CONFIG_SMP
 static int
-mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
+mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
+                          bool force)
 {
        unsigned long flags;
        int err;
@@ -142,7 +146,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
        flags = arch_local_cli_save();
 
        /* check irq no */
-       switch (irq) {
+       switch (d->irq) {
        case TMJCIRQ:
        case RESCHEDULE_IPI:
        case CALL_FUNC_SINGLE_IPI:
@@ -181,7 +185,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
                break;
 
        default:
-               set_bit(irq, irq_affinity_request);
+               set_bit(d->irq, irq_affinity_request);
                err = 0;
                break;
        }
@@ -202,15 +206,15 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
  * mask_ack() is provided), and mask_ack() just masks.
  */
 static struct irq_chip mn10300_cpu_pic_level = {
-       .name           = "cpu_l",
-       .disable        = mn10300_cpupic_mask,
-       .enable         = mn10300_cpupic_unmask_clear,
-       .ack            = NULL,
-       .mask           = mn10300_cpupic_mask,
-       .mask_ack       = mn10300_cpupic_mask,
-       .unmask         = mn10300_cpupic_unmask_clear,
+       .name                   = "cpu_l",
+       .irq_disable            = mn10300_cpupic_mask,
+       .irq_enable             = mn10300_cpupic_unmask_clear,
+       .irq_ack                = NULL,
+       .irq_mask               = mn10300_cpupic_mask,
+       .irq_mask_ack           = mn10300_cpupic_mask,
+       .irq_unmask             = mn10300_cpupic_unmask_clear,
 #ifdef CONFIG_SMP
-       .set_affinity   = mn10300_cpupic_setaffinity,
+       .irq_set_affinity       = mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -220,15 +224,15 @@ static struct irq_chip mn10300_cpu_pic_level = {
  * We use the latch clearing function of the PIC as the 'ACK' function.
  */
 static struct irq_chip mn10300_cpu_pic_edge = {
-       .name           = "cpu_e",
-       .disable        = mn10300_cpupic_mask,
-       .enable         = mn10300_cpupic_unmask,
-       .ack            = mn10300_cpupic_ack,
-       .mask           = mn10300_cpupic_mask,
-       .mask_ack       = mn10300_cpupic_mask_ack,
-       .unmask         = mn10300_cpupic_unmask,
+       .name                   = "cpu_e",
+       .irq_disable            = mn10300_cpupic_mask,
+       .irq_enable             = mn10300_cpupic_unmask,
+       .irq_ack                = mn10300_cpupic_ack,
+       .irq_mask               = mn10300_cpupic_mask,
+       .irq_mask_ack           = mn10300_cpupic_mask_ack,
+       .irq_unmask             = mn10300_cpupic_unmask,
 #ifdef CONFIG_SMP
-       .set_affinity   = mn10300_cpupic_setaffinity,
+       .irq_set_affinity       = mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -252,31 +256,6 @@ void set_intr_level(int irq, u16 level)
        __mask_and_set_icr(irq, GxICR_ENABLE, level);
 }
 
-void mn10300_intc_set_level(unsigned int irq, unsigned int level)
-{
-       set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
-}
-
-void mn10300_intc_clear(unsigned int irq)
-{
-       __mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
-}
-
-void mn10300_intc_set(unsigned int irq)
-{
-       __mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
-}
-
-void mn10300_intc_enable(unsigned int irq)
-{
-       mn10300_cpupic_unmask(irq);
-}
-
-void mn10300_intc_disable(unsigned int irq)
-{
-       mn10300_cpupic_mask(irq);
-}
-
 /*
  * mark an interrupt to be ACK'd after interrupt handlers have been run rather
  * than before
@@ -296,7 +275,7 @@ void __init init_IRQ(void)
        int irq;
 
        for (irq = 0; irq < NR_IRQS; irq++)
-               if (irq_desc[irq].chip == &no_irq_chip)
+               if (get_irq_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
@@ -384,12 +363,12 @@ int show_interrupts(struct seq_file *p, void *v)
 
                        if (i < NR_CPU_IRQS)
                                seq_printf(p, " %14s.%u",
-                                          irq_desc[i].chip->name,
+                                          irq_desc[i].irq_data.chip->name,
                                           (GxICR(i) & GxICR_LEVEL) >>
                                           GxICR_LEVEL_SHIFT);
                        else
                                seq_printf(p, " %14s",
-                                          irq_desc[i].chip->name);
+                                          irq_desc[i].irq_data.chip->name);
 
                        seq_printf(p, "  %s", action->name);
 
index 996384dba45da8dabca666d78328a00811aa4931..93c53739cfc94c58ba7d694af171dcfaf0f284df 100644 (file)
@@ -384,17 +384,21 @@ static void mn10300_serial_mask_ack(unsigned int irq)
        arch_local_irq_restore(flags);
 }
 
-static void mn10300_serial_nop(unsigned int irq)
+static void mn10300_serial_chip_mask_ack(struct irq_data *d)
+{
+       mn10300_serial_mask_ack(d->irq);
+}
+
+static void mn10300_serial_nop(struct irq_data *d)
 {
 }
 
 static struct irq_chip mn10300_serial_pic = {
        .name           = "mnserial",
-       .ack            = mn10300_serial_mask_ack,
-       .mask           = mn10300_serial_mask_ack,
-       .mask_ack       = mn10300_serial_mask_ack,
-       .unmask         = mn10300_serial_nop,
-       .end            = mn10300_serial_nop,
+       .irq_ack        = mn10300_serial_chip_mask_ack,
+       .irq_mask       = mn10300_serial_chip_mask_ack,
+       .irq_mask_ack   = mn10300_serial_chip_mask_ack,
+       .irq_unmask     = mn10300_serial_nop,
 };
 
 
index 0dcd1c686ba8e2c7126c1a478a034f3c7ad6e68e..1ebb79f1650d74b2fb38407694f44f17a18771ab 100644 (file)
@@ -113,15 +113,17 @@ static void init_ipi(void);
  */
 static void mn10300_ipi_disable(unsigned int irq);
 static void mn10300_ipi_enable(unsigned int irq);
-static void mn10300_ipi_ack(unsigned int irq);
-static void mn10300_ipi_nop(unsigned int irq);
+static void mn10300_ipi_chip_disable(struct irq_data *d);
+static void mn10300_ipi_chip_enable(struct irq_data *d);
+static void mn10300_ipi_ack(struct irq_data *d);
+static void mn10300_ipi_nop(struct irq_data *d);
 
 static struct irq_chip mn10300_ipi_type = {
        .name           = "cpu_ipi",
-       .disable        = mn10300_ipi_disable,
-       .enable         = mn10300_ipi_enable,
-       .ack            = mn10300_ipi_ack,
-       .eoi            = mn10300_ipi_nop
+       .irq_disable    = mn10300_ipi_chip_disable,
+       .irq_enable     = mn10300_ipi_chip_enable,
+       .irq_ack        = mn10300_ipi_ack,
+       .irq_eoi        = mn10300_ipi_nop
 };
 
 static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
@@ -236,6 +238,11 @@ static void mn10300_ipi_enable(unsigned int irq)
        arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_enable(struct irq_data *d)
+{
+       mn10300_ipi_enable(d->irq);
+}
+
 /**
  * mn10300_ipi_disable - Disable an IPI
  * @irq: The IPI to be disabled.
@@ -254,6 +261,12 @@ static void mn10300_ipi_disable(unsigned int irq)
        arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_disable(struct irq_data *d)
+{
+       mn10300_ipi_disable(d->irq);
+}
+
+
 /**
  * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC
  * @irq: The IPI to be acknowledged.
@@ -261,8 +274,9 @@ static void mn10300_ipi_disable(unsigned int irq)
  * Clear the interrupt detection flag for the IPI on the appropriate interrupt
  * channel in the PIC.
  */
-static void mn10300_ipi_ack(unsigned int irq)
+static void mn10300_ipi_ack(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        unsigned long flags;
        u16 tmp;
 
@@ -276,7 +290,7 @@ static void mn10300_ipi_ack(unsigned int irq)
  * mn10300_ipi_nop - Dummy IPI action
  * @irq: The IPI to be acted upon.
  */
-static void mn10300_ipi_nop(unsigned int irq)
+static void mn10300_ipi_nop(struct irq_data *d)
 {
 }
 
index 5b955000626d9f79fc3abe126dcc117c0076bc1e..67c6416a58f8304cae8a6eb3c5f4307185afb903 100644 (file)
@@ -93,79 +93,6 @@ irqreturn_t local_timer_interrupt(void)
        return IRQ_HANDLED;
 }
 
-#ifndef CONFIG_GENERIC_TIME
-/*
- * advance the kernel's time keeping clocks (xtime and jiffies)
- * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
- *   there's a need to update
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-       unsigned tsc, elapse;
-       irqreturn_t ret;
-
-       while (tsc = get_cycles(),
-              elapse = tsc - mn10300_last_tsc, /* time elapsed since last
-                                                * tick */
-              elapse > MN10300_TSC_PER_HZ
-              ) {
-               mn10300_last_tsc += MN10300_TSC_PER_HZ;
-
-               /* advance the kernel's time tracking system */
-               xtime_update(1);
-       }
-
-       ret = local_timer_interrupt();
-#ifdef CONFIG_SMP
-       send_IPI_allbutself(LOCAL_TIMER_IPI);
-#endif
-       return ret;
-}
-
-static struct irqaction timer_irq = {
-       .handler        = timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
-       .name           = "timer",
-};
-#endif /* CONFIG_GENERIC_TIME */
-
-#ifdef CONFIG_CSRC_MN10300
-void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
-{
-       u64 temp;
-       u32 shift;
-
-       /* Find a shift value */
-       for (shift = 32; shift > 0; shift--) {
-               temp = (u64) NSEC_PER_SEC << shift;
-               do_div(temp, clock);
-               if ((temp >> 32) == 0)
-                       break;
-       }
-       cs->shift = shift;
-       cs->mult = (u32) temp;
-}
-#endif
-
-#if CONFIG_CEVT_MN10300
-void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
-                                   unsigned int clock)
-{
-       u64 temp;
-       u32 shift;
-
-       /* Find a shift value */
-       for (shift = 32; shift > 0; shift--) {
-               temp = (u64) clock << shift;
-               do_div(temp, NSEC_PER_SEC);
-               if ((temp >> 32) == 0)
-                       break;
-       }
-       cd->shift = shift;
-       cd->mult = (u32) temp;
-}
-#endif
-
 /*
  * initialise the various timers used by the main part of the kernel
  */
@@ -177,11 +104,7 @@ void __init time_init(void)
         */
        TMPSCNT |= TMPSCNT_ENABLE;
 
-#ifdef CONFIG_GENERIC_TIME
        init_clocksource();
-#else
-       startup_timestamp_counter();
-#endif
 
        printk(KERN_INFO
               "timestamp counter I/O clock running at %lu.%02lu"
@@ -190,12 +113,7 @@ void __init time_init(void)
 
        mn10300_last_tsc = read_timestamp_counter();
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
        init_clockevents();
-#else
-       reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
-       setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL);
-#endif
 
 #ifdef CONFIG_MN10300_WD_TIMER
        /* start the watchdog timer */
index 7cf12054db65da40b87d3cffe4f48ec13a322daa..33f100f9b468ecb75a942673aab6169ed700a46b 100644 (file)
@@ -14,7 +14,7 @@
 #define ASB2364_FPGA_REG_RESET_USB     __SYSREG(0xa900130c, u16)
 #define ASB2364_FPGA_REG_RESET_AV      __SYSREG(0xa9001310, u16)
 
-#define ASB2364_FPGA_REG_IRQ(X)                __SYSREG(0xa9001590+((X)*4), u16)
+#define ASB2364_FPGA_REG_IRQ(X)                __SYSREG(0xa9001510+((X)*4), u16)
 #define ASB2364_FPGA_REG_IRQ_LAN       ASB2364_FPGA_REG_IRQ(0)
 #define ASB2364_FPGA_REG_IRQ_UART      ASB2364_FPGA_REG_IRQ(1)
 #define ASB2364_FPGA_REG_IRQ_I2C       ASB2364_FPGA_REG_IRQ(2)
index 7f048bbfdfd7f0edc8833261ca751a4a5b17f85e..92f224a97efcc612ba8fa2610d335d04e9cd788c 100644 (file)
@@ -59,18 +59,18 @@ static inline void __debug_to_serial(const char *p, int n)
 #define SERIAL_PORT_DFNS /* stolen by gdb-stub */
 
 #if defined(CONFIG_GDBSTUB_ON_TTYS0)
-#define GDBPORT_SERIAL_RX      __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 4, u8)
-#define GDBPORT_SERIAL_TX      __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
-#define GDBPORT_SERIAL_DLL     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
-#define GDBPORT_SERIAL_DLM     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
-#define GDBPORT_SERIAL_IER     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
-#define GDBPORT_SERIAL_IIR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
-#define GDBPORT_SERIAL_FCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
-#define GDBPORT_SERIAL_LCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
-#define GDBPORT_SERIAL_MCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
-#define GDBPORT_SERIAL_LSR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
-#define GDBPORT_SERIAL_MSR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
-#define GDBPORT_SERIAL_SCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_RX      __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 2, u8)
+#define GDBPORT_SERIAL_TX      __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 2, u8)
+#define GDBPORT_SERIAL_DLL     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8)
+#define GDBPORT_SERIAL_DLM     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8)
+#define GDBPORT_SERIAL_IER     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define GDBPORT_SERIAL_IIR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8)
+#define GDBPORT_SERIAL_FCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8)
+#define GDBPORT_SERIAL_LCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8)
+#define GDBPORT_SERIAL_MCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8)
+#define GDBPORT_SERIAL_LSR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8)
+#define GDBPORT_SERIAL_MSR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8)
+#define GDBPORT_SERIAL_SCR     __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8)
 #define GDBPORT_SERIAL_IRQ     SERIAL_IRQ
 
 #elif defined(CONFIG_GDBSTUB_ON_TTYS1)
index fcf29754e4d1770b4f1d1867ccad8d4e4325b1a2..ee84e62b16ede6e40d93592e3e6bd9342575cdd4 100644 (file)
 /*
  * FPGA PIC operations
  */
-static void asb2364_fpga_mask(unsigned int irq)
+static void asb2364_fpga_mask(struct irq_data *d)
 {
-       ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+       ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
        SyncExBus();
 }
 
-static void asb2364_fpga_ack(unsigned int irq)
+static void asb2364_fpga_ack(struct irq_data *d)
 {
-       ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+       ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
        SyncExBus();
 }
 
-static void asb2364_fpga_mask_ack(unsigned int irq)
+static void asb2364_fpga_mask_ack(struct irq_data *d)
 {
-       ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+       ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
        SyncExBus();
-       ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+       ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
        SyncExBus();
 }
 
-static void asb2364_fpga_unmask(unsigned int irq)
+static void asb2364_fpga_unmask(struct irq_data *d)
 {
-       ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000;
+       ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0000;
        SyncExBus();
 }
 
 static struct irq_chip asb2364_fpga_pic = {
        .name           = "fpga",
-       .ack            = asb2364_fpga_ack,
-       .mask           = asb2364_fpga_mask,
-       .mask_ack       = asb2364_fpga_mask_ack,
-       .unmask         = asb2364_fpga_unmask,
+       .irq_ack        = asb2364_fpga_ack,
+       .irq_mask       = asb2364_fpga_mask,
+       .irq_mask_ack   = asb2364_fpga_mask_ack,
+       .irq_unmask     = asb2364_fpga_unmask,
 };
 
 /*
@@ -88,6 +88,17 @@ void __init irq_fpga_init(void)
 {
        int irq;
 
+       ASB2364_FPGA_REG_MASK_LAN  = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_MASK_UART = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_MASK_I2C  = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_MASK_USB  = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_MASK_FPGA = 0x0001;
+       SyncExBus();
+
        for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
                set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq);
 
index 11440803db10f97a8adfdb320541850939f7535e..6359b41ce7e970ce0bc8f7d71919487b366b3d8e 100644 (file)
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
 #include <unit/fpga-regs.h>
+#include <unit/serial.h>
+#include <unit/smsc911x.h>
+
+#define TTYS0_SERIAL_IER       __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define LAN_IRQ_CFG            __SYSREG(SMSC911X_BASE + 0x54, u32)
+#define LAN_INT_EN             __SYSREG(SMSC911X_BASE + 0x5c, u32)
 
 /*
  * initialise some of the unit hardware before gdbstub is set up
  */
 asmlinkage void __init unit_init(void)
 {
+       /* Make sure we aren't going to get unexpected interrupts */
+       TTYS0_SERIAL_IER = 0;
+       SC0RXICR = 0;
+       SC0TXICR = 0;
+       SC1RXICR = 0;
+       SC1TXICR = 0;
+       SC2RXICR = 0;
+       SC2TXICR = 0;
+
+       /* Attempt to reset the FPGA attached peripherals */
+       ASB2364_FPGA_REG_RESET_LAN = 0x0000;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_UART = 0x0000;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_I2C = 0x0000;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_USB = 0x0000;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_AV = 0x0000;
+       SyncExBus();
+
        /* set up the external interrupts */
 
        /* XIRQ[0]: NAND RXBY */
@@ -56,7 +84,23 @@ asmlinkage void __init unit_init(void)
  */
 asmlinkage void __init unit_setup(void)
 {
+       /* Release the reset on the SMSC911X so that it is ready by the time we
+        * need it */
+       ASB2364_FPGA_REG_RESET_LAN = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_UART = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_I2C = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_USB = 0x0001;
+       SyncExBus();
+       ASB2364_FPGA_REG_RESET_AV = 0x0001;
+       SyncExBus();
 
+       /* Make sure the ethernet chipset isn't going to give us an interrupt
+        * storm from stuff it was doing pre-reset */
+       LAN_IRQ_CFG = 0;
+       LAN_INT_EN = 0;
 }
 
 /*
index fed2946f73352489e15a5c0448bf6bdc717a00cc..fafdf30bea9e5fc040f0c629078680716a8caf50 100644 (file)
@@ -15,6 +15,7 @@ config PARISC
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select IRQ_PER_CPU
+       select GENERIC_HARDIRQS_NO_DEPRECATED
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index f388a85bba113c7c6f050202e494ad0d71731a43..d18328b3f9386c0477e61340f44e995888a1c47e 100644 (file)
@@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_page_asm(void *);
 void flush_kernel_icache_page(void *);
-void flush_user_dcache_page(unsigned long);
-void flush_user_icache_page(unsigned long);
 void flush_user_dcache_range(unsigned long, unsigned long);
 void flush_user_icache_range(unsigned long, unsigned long);
 
@@ -37,6 +35,13 @@ void flush_cache_all_local(void);
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+void flush_kernel_dcache_page_addr(void *addr);
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+       flush_kernel_dcache_page_addr(page_address(page));
+}
+
 #define flush_kernel_dcache_range(start,size) \
        flush_kernel_dcache_range_asm((start), (start)+(size));
 /* vmap range flushes and invalidates.  Architecturally, we don't need
@@ -50,6 +55,16 @@ static inline void flush_kernel_vmap_range(void *vaddr, int size)
 }
 static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
 {
+       unsigned long start = (unsigned long)vaddr;
+       void *cursor = vaddr;
+
+       for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) {
+               struct page *page = vmalloc_to_page(cursor);
+
+               if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+                       flush_kernel_dcache_page(page);
+       }
+       flush_kernel_dcache_range_asm(start, start + size);
 }
 
 #define flush_cache_vmap(start, end)           flush_cache_all()
@@ -90,19 +105,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned
 void flush_cache_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end);
 
+/* defined in pacache.S exported in cache.c used by flush_anon_page */
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 #define ARCH_HAS_FLUSH_ANON_PAGE
 static inline void
 flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
 {
        if (PageAnon(page))
-               flush_user_dcache_page(vmaddr);
-}
-
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-void flush_kernel_dcache_page_addr(void *addr);
-static inline void flush_kernel_dcache_page(struct page *page)
-{
-       flush_kernel_dcache_page_addr(page_address(page));
+               flush_dcache_page_asm(page_to_phys(page), vmaddr);
 }
 
 #ifdef CONFIG_DEBUG_RODATA
index c67dccf2e31f801860a7392598e951560921f3ce..1073599a7be93e6fa2de4e40d88793e5fd62b531 100644 (file)
@@ -32,15 +32,10 @@ static __inline__ int irq_canonicalize(int irq)
 }
 
 struct irq_chip;
+struct irq_data;
 
-/*
- * Some useful "we don't have to do anything here" handlers.  Should
- * probably be provided by the generic code.
- */
-void no_ack_irq(unsigned int irq);
-void no_end_irq(unsigned int irq);
-void cpu_ack_irq(unsigned int irq);
-void cpu_eoi_irq(unsigned int irq);
+void cpu_ack_irq(struct irq_data *d);
+void cpu_eoi_irq(struct irq_data *d);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
@@ -49,7 +44,7 @@ extern unsigned long txn_alloc_addr(unsigned int);
 extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
 
 extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
-extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest);
+extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest);
 
 /* soft power switch support (power.c) */
 extern struct tasklet_struct power_tasklet;
index 6f1f65d3c0efb06bccbddb49612c4a3a1b01321e..5d7b8ce9fdf36507c8c541d76f4e176f9db01d94 100644 (file)
@@ -138,8 +138,7 @@ struct vm_area_struct;
 #define _PAGE_NO_CACHE_BIT 24   /* (0x080) Uncached Page (U bit) */
 #define _PAGE_ACCESSED_BIT 23   /* (0x100) Software: Page Accessed */
 #define _PAGE_PRESENT_BIT  22   /* (0x200) Software: translation valid */
-#define _PAGE_FLUSH_BIT    21   /* (0x400) Software: translation valid */
-                               /*             for cache flushing only */
+/* bit 21 was formerly the FLUSH bit but is now unused */
 #define _PAGE_USER_BIT     20   /* (0x800) Software: User accessible page */
 
 /* N.B. The bits are defined in terms of a 32 bit word above, so the */
@@ -173,7 +172,6 @@ struct vm_area_struct;
 #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
 #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
 #define _PAGE_PRESENT  (1 << xlate_pabit(_PAGE_PRESENT_BIT))
-#define _PAGE_FLUSH    (1 << xlate_pabit(_PAGE_FLUSH_BIT))
 #define _PAGE_USER     (1 << xlate_pabit(_PAGE_USER_BIT))
 #define _PAGE_FILE     (1 << xlate_pabit(_PAGE_FILE_BIT))
 
@@ -213,7 +211,6 @@ struct vm_area_struct;
 #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
 #define PAGE_KERNEL_UNC        __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
 #define PAGE_GATEWAY    __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
-#define PAGE_FLUSH      __pgprot(_PAGE_FLUSH)
 
 
 /*
@@ -261,7 +258,7 @@ extern unsigned long *empty_zero_page;
 
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
-#define pte_none(x)     ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH))
+#define pte_none(x)     (pte_val(x) == 0)
 #define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
 #define pte_clear(mm,addr,xp)  do { pte_val(*(xp)) = 0; } while (0)
 
@@ -444,13 +441,10 @@ struct mm_struct;
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_t old_pte;
-       pte_t pte;
 
        spin_lock(&pa_dbit_lock);
-       pte = old_pte = *ptep;
-       pte_val(pte) &= ~_PAGE_PRESENT;
-       pte_val(pte) |= _PAGE_FLUSH;
-       set_pte_at(mm,addr,ptep,pte);
+       old_pte = *ptep;
+       pte_clear(mm,addr,ptep);
        spin_unlock(&pa_dbit_lock);
 
        return old_pte;
index d054f3da3ff512fa07c0a5b5b818a8e53adfcada..3f11331c27755f835a228cfdc91e5f05cf808042 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
+#include <asm/shmparam.h>
 
 int split_tlb __read_mostly;
 int dcache_stride __read_mostly;
 int icache_stride __read_mostly;
 EXPORT_SYMBOL(dcache_stride);
 
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+EXPORT_SYMBOL(flush_dcache_page_asm);
+void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 
 /* On some machines (e.g. ones with the Merced bus), there can be
  * only a single PxTLB broadcast at a time; this must be guaranteed
@@ -259,81 +264,13 @@ void disable_sr_hashing(void)
                panic("SpaceID hashing is still on!\n");
 }
 
-/* Simple function to work out if we have an existing address translation
- * for a user space vma. */
-static inline int translation_exists(struct vm_area_struct *vma,
-                               unsigned long addr, unsigned long pfn)
-{
-       pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
-       pmd_t *pmd;
-       pte_t pte;
-
-       if(pgd_none(*pgd))
-               return 0;
-
-       pmd = pmd_offset(pgd, addr);
-       if(pmd_none(*pmd) || pmd_bad(*pmd))
-               return 0;
-
-       /* We cannot take the pte lock here: flush_cache_page is usually
-        * called with pte lock already held.  Whereas flush_dcache_page
-        * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
-        * the vma itself is secure, but the pte might come or go racily.
-        */
-       pte = *pte_offset_map(pmd, addr);
-       /* But pte_unmap() does nothing on this architecture */
-
-       /* Filter out coincidental file entries and swap entries */
-       if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
-               return 0;
-
-       return pte_pfn(pte) == pfn;
-}
-
-/* Private function to flush a page from the cache of a non-current
- * process.  cr25 contains the Page Directory of the current user
- * process; we're going to hijack both it and the user space %sr3 to
- * temporarily make the non-current process current.  We have to do
- * this because cache flushing may cause a non-access tlb miss which
- * the handlers have to fill in from the pgd of the non-current
- * process. */
 static inline void
-flush_user_cache_page_non_current(struct vm_area_struct *vma,
-                                 unsigned long vmaddr)
+__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+                  unsigned long physaddr)
 {
-       /* save the current process space and pgd */
-       unsigned long space = mfsp(3), pgd = mfctl(25);
-
-       /* we don't mind taking interrupts since they may not
-        * do anything with user space, but we can't
-        * be preempted here */
-       preempt_disable();
-
-       /* make us current */
-       mtctl(__pa(vma->vm_mm->pgd), 25);
-       mtsp(vma->vm_mm->context, 3);
-
-       flush_user_dcache_page(vmaddr);
-       if(vma->vm_flags & VM_EXEC)
-               flush_user_icache_page(vmaddr);
-
-       /* put the old current process back */
-       mtsp(space, 3);
-       mtctl(pgd, 25);
-       preempt_enable();
-}
-
-
-static inline void
-__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
-{
-       if (likely(vma->vm_mm->context == mfsp(3))) {
-               flush_user_dcache_page(vmaddr);
-               if (vma->vm_flags & VM_EXEC)
-                       flush_user_icache_page(vmaddr);
-       } else {
-               flush_user_cache_page_non_current(vma, vmaddr);
-       }
+       flush_dcache_page_asm(physaddr, vmaddr);
+       if (vma->vm_flags & VM_EXEC)
+               flush_icache_page_asm(physaddr, vmaddr);
 }
 
 void flush_dcache_page(struct page *page)
@@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page)
        struct vm_area_struct *mpnt;
        struct prio_tree_iter iter;
        unsigned long offset;
-       unsigned long addr;
+       unsigned long addr, old_addr = 0;
        pgoff_t pgoff;
-       unsigned long pfn = page_to_pfn(page);
-
 
        if (mapping && !mapping_mapped(mapping)) {
                set_bit(PG_dcache_dirty, &page->flags);
@@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page)
                offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
                addr = mpnt->vm_start + offset;
 
-               /* Flush instructions produce non access tlb misses.
-                * On PA, we nullify these instructions rather than
-                * taking a page fault if the pte doesn't exist.
-                * This is just for speed.  If the page translation
-                * isn't there, there's no point exciting the
-                * nadtlb handler into a nullification frenzy.
-                *
-                * Make sure we really have this page: the private
-                * mappings may cover this area but have COW'd this
-                * particular page.
-                */
-               if (translation_exists(mpnt, addr, pfn)) {
-                       __flush_cache_page(mpnt, addr);
-                       break;
+               if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+                       __flush_cache_page(mpnt, addr, page_to_phys(page));
+                       if (old_addr)
+                               printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
+                       old_addr = addr;
                }
        }
        flush_dcache_mmap_unlock(mapping);
@@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
 {
        BUG_ON(!vma->vm_mm->context);
 
-       if (likely(translation_exists(vma, vmaddr, pfn)))
-               __flush_cache_page(vma, vmaddr);
+       __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
 
 }
index 6337adef30f64f158086d6ff322dd20ed7ec6361..e5477092a5d4cde2cde30c2b11c79a6ffd58b18e 100644 (file)
 #ifndef CONFIG_64BIT
        /*
         * naitlb miss interruption handler (parisc 1.1 - 32 bit)
-        *
-        * Note: naitlb misses will be treated
-        * as an ordinary itlb miss for now.
-        * However, note that naitlb misses
-        * have the faulting address in the
-        * IOR/ISR.
         */
 
        .macro  naitlb_11 code
 
        mfctl   %isr,spc
-       b       itlb_miss_11
+       b       naitlb_miss_11
        mfctl   %ior,va
-       /* FIXME: If user causes a naitlb miss, the priv level may not be in
-        * lower bits of va, where the itlb miss handler is expecting them
-        */
 
        .align          32
        .endm
        
        /*
         * naitlb miss interruption handler (parisc 2.0)
-        *
-        * Note: naitlb misses will be treated
-        * as an ordinary itlb miss for now.
-        * However, note that naitlb misses
-        * have the faulting address in the
-        * IOR/ISR.
         */
 
        .macro  naitlb_20 code
 
        mfctl   %isr,spc
 #ifdef CONFIG_64BIT
-       b       itlb_miss_20w
+       b       naitlb_miss_20w
 #else
-       b       itlb_miss_20
+       b       naitlb_miss_20
 #endif
        mfctl   %ior,va
-       /* FIXME: If user causes a naitlb miss, the priv level may not be in
-        * lower bits of va, where the itlb miss handler is expecting them
-        */
 
        .align          32
        .endm
        copy            \va,\tmp1
        depi            0,31,23,\tmp1
        cmpb,COND(<>),n \tmp,\tmp1,\fault
-       ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+       mfctl           %cr19,\tmp      /* iir */
+       /* get the opcode (first six bits) into \tmp */
+       extrw,u         \tmp,5,6,\tmp
+       /*
+        * Only setting the T bit prevents data cache movein
+        * Setting access rights to zero prevents instruction cache movein
+        *
+        * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
+        * to type field and _PAGE_READ goes to top bit of PL1
+        */
+       ldi             (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
+       /*
+        * so if the opcode is one (i.e. this is a memory management
+        * instruction) nullify the next load so \prot is only T.
+        * Otherwise this is a normal data operation
+        */
+       cmpiclr,=       0x01,\tmp,%r0
+       ldi             (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
        depd,z          \prot,8,7,\prot
        /*
         * OK, it is in the temp alias region, check whether "from" or "to".
@@ -631,11 +630,7 @@ ENTRY(fault_vector_20)
        def             13
        def             14
        dtlb_20         15
-#if 0
        naitlb_20       16
-#else
-       def             16
-#endif
        nadtlb_20       17
        def             18
        def             19
@@ -678,11 +673,7 @@ ENTRY(fault_vector_11)
        def             13
        def             14
        dtlb_11         15
-#if 0
        naitlb_11       16
-#else
-       def             16
-#endif
        nadtlb_11       17
        def             18
        def             19
@@ -1203,7 +1194,7 @@ nadtlb_miss_20w:
        get_pgd         spc,ptp
        space_check     spc,t0,nadtlb_fault
 
-       L3_ptep         ptp,pte,t0,va,nadtlb_check_flush_20w
+       L3_ptep         ptp,pte,t0,va,nadtlb_check_alias_20w
 
        update_ptep     ptp,pte,t0,t1
 
@@ -1214,16 +1205,8 @@ nadtlb_miss_20w:
        rfir
        nop
 
-nadtlb_check_flush_20w:
-       bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-       /* Insert a "flush only" translation */
-
-       depdi,z         7,7,3,prot
-       depdi           1,10,1,prot
-
-       /* Drop prot bits from pte and convert to page addr for idtlbt */
-       convert_for_tlb_insert20 pte
+nadtlb_check_alias_20w:
+       do_alias        spc,t0,t1,va,pte,prot,nadtlb_emulate
 
        idtlbt          pte,prot
 
@@ -1255,25 +1238,7 @@ dtlb_miss_11:
        nop
 
 dtlb_check_alias_11:
-
-       /* Check to see if fault is in the temporary alias region */
-
-       cmpib,<>,n      0,spc,dtlb_fault /* forward */
-       ldil            L%(TMPALIAS_MAP_START),t0
-       copy            va,t1
-       depwi           0,31,23,t1
-       cmpb,<>,n       t0,t1,dtlb_fault /* forward */
-       ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-       depw,z          prot,8,7,prot
-
-       /*
-        * OK, it is in the temp alias region, check whether "from" or "to".
-        * Check "subtle" note in pacache.S re: r23/r26.
-        */
-
-       extrw,u,=       va,9,1,r0
-       or,tr           %r23,%r0,pte    /* If "from" use "from" page */
-       or              %r26,%r0,pte    /* else "to", use "to" page  */
+       do_alias        spc,t0,t1,va,pte,prot,dtlb_fault
 
        idtlba          pte,(va)
        idtlbp          prot,(va)
@@ -1286,7 +1251,7 @@ nadtlb_miss_11:
 
        space_check     spc,t0,nadtlb_fault
 
-       L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_11
+       L2_ptep         ptp,pte,t0,va,nadtlb_check_alias_11
 
        update_ptep     ptp,pte,t0,t1
 
@@ -1304,26 +1269,11 @@ nadtlb_miss_11:
        rfir
        nop
 
-nadtlb_check_flush_11:
-       bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-       /* Insert a "flush only" translation */
-
-       zdepi           7,7,3,prot
-       depi            1,10,1,prot
+nadtlb_check_alias_11:
+       do_alias        spc,t0,t1,va,pte,prot,nadtlb_emulate
 
-       /* Get rid of prot bits and convert to page addr for idtlba */
-
-       depi            0,31,ASM_PFN_PTE_SHIFT,pte
-       SHRREG          pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte
-
-       mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
-       mtsp            spc,%sr1
-
-       idtlba          pte,(%sr1,va)
-       idtlbp          prot,(%sr1,va)
-
-       mtsp            t0, %sr1        /* Restore sr1 */
+       idtlba          pte,(va)
+       idtlbp          prot,(va)
 
        rfir
        nop
@@ -1359,7 +1309,7 @@ nadtlb_miss_20:
 
        space_check     spc,t0,nadtlb_fault
 
-       L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_20
+       L2_ptep         ptp,pte,t0,va,nadtlb_check_alias_20
 
        update_ptep     ptp,pte,t0,t1
 
@@ -1372,21 +1322,14 @@ nadtlb_miss_20:
        rfir
        nop
 
-nadtlb_check_flush_20:
-       bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-       /* Insert a "flush only" translation */
-
-       depdi,z         7,7,3,prot
-       depdi           1,10,1,prot
-
-       /* Drop prot bits from pte and convert to page addr for idtlbt */
-       convert_for_tlb_insert20 pte
+nadtlb_check_alias_20:
+       do_alias        spc,t0,t1,va,pte,prot,nadtlb_emulate
 
        idtlbt          pte,prot
 
        rfir
        nop
+
 #endif
 
 nadtlb_emulate:
@@ -1484,6 +1427,36 @@ itlb_miss_20w:
        rfir
        nop
 
+naitlb_miss_20w:
+
+       /*
+        * I miss is a little different, since we allow users to fault
+        * on the gateway page which is in the kernel address space.
+        */
+
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,naitlb_fault
+
+       L3_ptep         ptp,pte,t0,va,naitlb_check_alias_20w
+
+       update_ptep     ptp,pte,t0,t1
+
+       make_insert_tlb spc,pte,prot
+
+       iitlbt          pte,prot
+
+       rfir
+       nop
+
+naitlb_check_alias_20w:
+       do_alias        spc,t0,t1,va,pte,prot,naitlb_fault
+
+       iitlbt          pte,prot
+
+       rfir
+       nop
+
 #else
 
 itlb_miss_11:
@@ -1508,6 +1481,38 @@ itlb_miss_11:
        rfir
        nop
 
+naitlb_miss_11:
+       get_pgd         spc,ptp
+
+       space_check     spc,t0,naitlb_fault
+
+       L2_ptep         ptp,pte,t0,va,naitlb_check_alias_11
+
+       update_ptep     ptp,pte,t0,t1
+
+       make_insert_tlb_11      spc,pte,prot
+
+       mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+       mtsp            spc,%sr1
+
+       iitlba          pte,(%sr1,va)
+       iitlbp          prot,(%sr1,va)
+
+       mtsp            t0, %sr1        /* Restore sr1 */
+
+       rfir
+       nop
+
+naitlb_check_alias_11:
+       do_alias        spc,t0,t1,va,pte,prot,itlb_fault
+
+       iitlba          pte,(%sr0, va)
+       iitlbp          prot,(%sr0, va)
+
+       rfir
+       nop
+
+
 itlb_miss_20:
        get_pgd         spc,ptp
 
@@ -1526,6 +1531,32 @@ itlb_miss_20:
        rfir
        nop
 
+naitlb_miss_20:
+       get_pgd         spc,ptp
+
+       space_check     spc,t0,naitlb_fault
+
+       L2_ptep         ptp,pte,t0,va,naitlb_check_alias_20
+
+       update_ptep     ptp,pte,t0,t1
+
+       make_insert_tlb spc,pte,prot
+
+       f_extend        pte,t0
+
+       iitlbt          pte,prot
+
+       rfir
+       nop
+
+naitlb_check_alias_20:
+       do_alias        spc,t0,t1,va,pte,prot,naitlb_fault
+
+       iitlbt          pte,prot
+
+       rfir
+       nop
+
 #endif
 
 #ifdef CONFIG_64BIT
@@ -1662,6 +1693,10 @@ nadtlb_fault:
        b               intr_save
        ldi             17,%r8
 
+naitlb_fault:
+       b               intr_save
+       ldi             16,%r8
+
 dtlb_fault:
        b               intr_save
        ldi             15,%r8
index d7d94b845dc2c8bb08ece9d5e420f8cae5b7abe2..cb450e1e79b322e074277aa9d56f8802476bd5c6 100644 (file)
@@ -52,9 +52,9 @@ static volatile unsigned long cpu_eiem = 0;
 */
 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
 
-static void cpu_mask_irq(unsigned int irq)
+static void cpu_mask_irq(struct irq_data *d)
 {
-       unsigned long eirr_bit = EIEM_MASK(irq);
+       unsigned long eirr_bit = EIEM_MASK(d->irq);
 
        cpu_eiem &= ~eirr_bit;
        /* Do nothing on the other CPUs.  If they get this interrupt,
@@ -63,7 +63,7 @@ static void cpu_mask_irq(unsigned int irq)
         * then gets disabled */
 }
 
-static void cpu_unmask_irq(unsigned int irq)
+static void __cpu_unmask_irq(unsigned int irq)
 {
        unsigned long eirr_bit = EIEM_MASK(irq);
 
@@ -75,9 +75,14 @@ static void cpu_unmask_irq(unsigned int irq)
        smp_send_all_nop();
 }
 
-void cpu_ack_irq(unsigned int irq)
+static void cpu_unmask_irq(struct irq_data *d)
+{
+       __cpu_unmask_irq(d->irq);
+}
+
+void cpu_ack_irq(struct irq_data *d)
 {
-       unsigned long mask = EIEM_MASK(irq);
+       unsigned long mask = EIEM_MASK(d->irq);
        int cpu = smp_processor_id();
 
        /* Clear in EIEM so we can no longer process */
@@ -90,9 +95,9 @@ void cpu_ack_irq(unsigned int irq)
        mtctl(mask, 23);
 }
 
-void cpu_eoi_irq(unsigned int irq)
+void cpu_eoi_irq(struct irq_data *d)
 {
-       unsigned long mask = EIEM_MASK(irq);
+       unsigned long mask = EIEM_MASK(d->irq);
        int cpu = smp_processor_id();
 
        /* set it in the eiems---it's no longer in process */
@@ -103,15 +108,16 @@ void cpu_eoi_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_SMP
-int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
+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)) {
+       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 */
-               cpumask_setall(irq_desc[irq].affinity);
+                * been set; we must reset it. Will fix - tglx
+                */
+               cpumask_setall(d->affinity);
                return -EINVAL;
        }
 
@@ -121,33 +127,34 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
        return cpu_dest;
 }
 
-static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
+                               bool force)
 {
        int cpu_dest;
 
-       cpu_dest = cpu_check_affinity(irq, dest);
+       cpu_dest = cpu_check_affinity(d, dest);
        if (cpu_dest < 0)
                return -1;
 
-       cpumask_copy(irq_desc[irq].affinity, dest);
+       cpumask_copy(d->affinity, dest);
 
        return 0;
 }
 #endif
 
 static struct irq_chip cpu_interrupt_type = {
-       .name           = "CPU",
-       .mask           = cpu_mask_irq,
-       .unmask         = cpu_unmask_irq,
-       .ack            = cpu_ack_irq,
-       .eoi            = cpu_eoi_irq,
+       .name                   = "CPU",
+       .irq_mask               = cpu_mask_irq,
+       .irq_unmask             = cpu_unmask_irq,
+       .irq_ack                = cpu_ack_irq,
+       .irq_eoi                = cpu_eoi_irq,
 #ifdef CONFIG_SMP
-       .set_affinity   = cpu_set_affinity_irq,
+       .irq_set_affinity       = cpu_set_affinity_irq,
 #endif
        /* XXX: Needs to be written.  We managed without it so far, but
         * we really ought to write it.
         */
-       .retrigger      = NULL,
+       .irq_retrigger  = NULL,
 };
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -181,7 +188,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].chip->name);
+               seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
 #ifndef PARISC_IRQ_CR16_COUNTS
                seq_printf(p, "  %s", action->name);
 
@@ -233,14 +240,14 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
        if (irq_desc[irq].action)
                return -EBUSY;
-       if (irq_desc[irq].chip != &cpu_interrupt_type)
+       if (get_irq_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);
-               cpu_unmask_irq(irq);
+               __cpu_unmask_irq(irq);
        }
        return 0;
 }
@@ -289,7 +296,8 @@ int txn_alloc_irq(unsigned int bits_wide)
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-       cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+       struct irq_data *d = irq_get_irq_data(irq);
+       cpumask_copy(d->affinity, cpumask_of(cpu));
 #endif
 
        return per_cpu(cpu_data, cpu).txn_addr;
@@ -333,6 +341,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        unsigned long eirr_val;
        int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
+       struct irq_desc *desc;
        cpumask_t dest;
 #endif
 
@@ -346,8 +355,9 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-       cpumask_copy(&dest, irq_desc[irq].affinity);
-       if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
+       desc = irq_to_desc(irq);
+       cpumask_copy(&dest, desc->irq_data.affinity);
+       if (CHECK_IRQ_PER_CPU(desc->status) &&
            !cpu_isset(smp_processor_id(), dest)) {
                int cpu = first_cpu(dest);
 
index 09b77b2553c6bf67c1fe36b4d502eda41cc56de5..a85823668cba041708285555e4cc31f2475f131f 100644 (file)
@@ -608,93 +608,131 @@ ENTRY(__clear_user_page_asm)
        .procend
 ENDPROC(__clear_user_page_asm)
 
-ENTRY(flush_kernel_dcache_page_asm)
+ENTRY(flush_dcache_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
 
+       ldil            L%(TMPALIAS_MAP_START), %r28
+#ifdef CONFIG_64BIT
+#if (TMPALIAS_MAP_START >= 0x80000000)
+       depdi           0, 31,32, %r28          /* clear any sign extension */
+       /* FIXME: page size dependend */
+#endif
+       extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
+       depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
+       depdi           0, 63,12, %r28          /* Clear any offset bits */
+#else
+       extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
+       depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
+       depwi           0, 31,12, %r28          /* Clear any offset bits */
+#endif
+
+       /* Purge any old translation */
+
+       pdtlb           0(%r28)
+
        ldil            L%dcache_stride, %r1
-       ldw             R%dcache_stride(%r1), %r23
+       ldw             R%dcache_stride(%r1), %r1
 
 #ifdef CONFIG_64BIT
        depdi,z         1, 63-PAGE_SHIFT,1, %r25
 #else
        depwi,z         1, 31-PAGE_SHIFT,1, %r25
 #endif
-       add             %r26, %r25, %r25
-       sub             %r25, %r23, %r25
-
-
-1:      fdc,m          %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       fdc,m           %r23(%r26)
-       cmpb,COND(<<)           %r26, %r25,1b
-       fdc,m           %r23(%r26)
+       add             %r28, %r25, %r25
+       sub             %r25, %r1, %r25
+
+
+1:      fdc,m          %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       fdc,m           %r1(%r28)
+       cmpb,COND(<<)           %r28, %r25,1b
+       fdc,m           %r1(%r28)
 
        sync
        bv              %r0(%r2)
-       nop
+       pdtlb           (%r25)
        .exit
 
        .procend
-ENDPROC(flush_kernel_dcache_page_asm)
-       
-ENTRY(flush_user_dcache_page)
+ENDPROC(flush_dcache_page_asm)
+
+ENTRY(flush_icache_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
 
-       ldil            L%dcache_stride, %r1
-       ldw             R%dcache_stride(%r1), %r23
-
+       ldil            L%(TMPALIAS_MAP_START), %r28
 #ifdef CONFIG_64BIT
-       depdi,z         1,63-PAGE_SHIFT,1, %r25
+#if (TMPALIAS_MAP_START >= 0x80000000)
+       depdi           0, 31,32, %r28          /* clear any sign extension */
+       /* FIXME: page size dependend */
+#endif
+       extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
+       depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
+       depdi           0, 63,12, %r28          /* Clear any offset bits */
 #else
-       depwi,z         1,31-PAGE_SHIFT,1, %r25
+       extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
+       depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
+       depwi           0, 31,12, %r28          /* Clear any offset bits */
 #endif
-       add             %r26, %r25, %r25
-       sub             %r25, %r23, %r25
 
+       /* Purge any old translation */
 
-1:      fdc,m          %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       fdc,m           %r23(%sr3, %r26)
-       cmpb,COND(<<)           %r26, %r25,1b
-       fdc,m           %r23(%sr3, %r26)
+       pitlb           (%sr0,%r28)
+
+       ldil            L%icache_stride, %r1
+       ldw             R%icache_stride(%r1), %r1
+
+#ifdef CONFIG_64BIT
+       depdi,z         1, 63-PAGE_SHIFT,1, %r25
+#else
+       depwi,z         1, 31-PAGE_SHIFT,1, %r25
+#endif
+       add             %r28, %r25, %r25
+       sub             %r25, %r1, %r25
+
+
+1:      fic,m          %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       fic,m           %r1(%r28)
+       cmpb,COND(<<)           %r28, %r25,1b
+       fic,m           %r1(%r28)
 
        sync
        bv              %r0(%r2)
-       nop
+       pitlb           (%sr0,%r25)
        .exit
 
        .procend
-ENDPROC(flush_user_dcache_page)
+ENDPROC(flush_icache_page_asm)
 
-ENTRY(flush_user_icache_page)
+ENTRY(flush_kernel_dcache_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -711,23 +749,23 @@ ENTRY(flush_user_icache_page)
        sub             %r25, %r23, %r25
 
 
-1:      fic,m          %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
-       fic,m           %r23(%sr3, %r26)
+1:      fdc,m          %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
+       fdc,m           %r23(%r26)
        cmpb,COND(<<)           %r26, %r25,1b
-       fic,m           %r23(%sr3, %r26)
+       fdc,m           %r23(%r26)
 
        sync
        bv              %r0(%r2)
@@ -735,8 +773,7 @@ ENTRY(flush_user_icache_page)
        .exit
 
        .procend
-ENDPROC(flush_user_icache_page)
-
+ENDPROC(flush_kernel_dcache_page_asm)
 
 ENTRY(purge_kernel_dcache_page)
        .proc
@@ -780,69 +817,6 @@ ENTRY(purge_kernel_dcache_page)
        .procend
 ENDPROC(purge_kernel_dcache_page)
 
-#if 0
-       /* Currently not used, but it still is a possible alternate
-        * solution.
-        */
-
-ENTRY(flush_alias_page)
-       .proc
-       .callinfo NO_CALLS
-       .entry
-
-       tophys_r1               %r26
-
-       ldil            L%(TMPALIAS_MAP_START), %r28
-#ifdef CONFIG_64BIT
-       extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
-       depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
-       depdi           0, 63,12, %r28          /* Clear any offset bits */
-#else
-       extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
-       depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
-       depwi           0, 31,12, %r28          /* Clear any offset bits */
-#endif
-
-       /* Purge any old translation */
-
-       pdtlb           0(%r28)
-
-       ldil            L%dcache_stride, %r1
-       ldw             R%dcache_stride(%r1), %r23
-
-#ifdef CONFIG_64BIT
-       depdi,z         1, 63-PAGE_SHIFT,1, %r29
-#else
-       depwi,z         1, 31-PAGE_SHIFT,1, %r29
-#endif
-       add             %r28, %r29, %r29
-       sub             %r29, %r23, %r29
-
-1:      fdc,m          %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       fdc,m           %r23(%r28)
-       cmpb,COND(<<)           %r28, %r29, 1b
-       fdc,m           %r23(%r28)
-
-       sync
-       bv              %r0(%r2)
-       nop
-       .exit
-
-       .procend
-#endif
 
        .export flush_user_dcache_range_asm
 
@@ -865,7 +839,6 @@ flush_user_dcache_range_asm:
        .exit
 
        .procend
-ENDPROC(flush_alias_page)
 
 ENTRY(flush_kernel_dcache_range_asm)
        .proc
index 946ec4947da282e90589a3012c8fb92653ecc5f2..7005ee0b074d744e6905fd8e0c6dfc144a3a4cb3 100644 (file)
@@ -367,6 +367,10 @@ struct mpic
 #define MPIC_SINGLE_DEST_CPU           0x00001000
 /* Enable CoreInt delivery of interrupts */
 #define MPIC_ENABLE_COREINT            0x00002000
+/* Disable resetting of the MPIC.
+ * NOTE: This flag trumps MPIC_WANTS_RESET.
+ */
+#define MPIC_NO_RESET                  0x00004000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK               0xf0000000
index 0175a676b34b5e577c4e52107bfd1f3e99c6e8d2..48223f9b8728d5e1433c6d13ab9c1c583780d2cb 100644 (file)
@@ -125,8 +125,10 @@ extern int ptrace_put_reg(struct task_struct *task, int regno,
 #endif /* ! __powerpc64__ */
 #define TRAP(regs)             ((regs)->trap & ~0xF)
 #ifdef __powerpc64__
+#define NV_REG_POISON          0xdeadbeefdeadbeefUL
 #define CHECK_FULL_REGS(regs)  BUG_ON(regs->trap & 1)
 #else
+#define NV_REG_POISON          0xdeadbeef
 #define CHECK_FULL_REGS(regs)                                                \
 do {                                                                         \
        if ((regs)->trap & 1)                                                 \
index 29852688ceaaae7f6f9c09cbc7e3f6350ee8170f..d225d99fe39d8f076ee637377a43692024c39232 100644 (file)
@@ -176,11 +176,14 @@ static void *is_devfn_node(struct device_node *dn, void *data)
  */
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
-       struct device_node *orig_dn = dev->dev.of_node;
+       struct pci_controller *phb = dev->sysdata;
        struct device_node *dn;
        unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-       dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
+       if (WARN_ON(!phb))
+               return NULL;
+
+       dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
        if (dn)
                dev->dev.of_node = dn;
        return dn;
index 9065369982911f19eab7ee34fa88209597cfbdeb..895b082f1e48bafe5c7826de6950edf14cff6d23 100644 (file)
@@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
                   unsigned int pos, unsigned int count,
                   void *kbuf, void __user *ubuf)
 {
-       int ret;
+       int i, ret;
 
        if (target->thread.regs == NULL)
                return -EIO;
 
-       CHECK_FULL_REGS(target->thread.regs);
+       if (!FULL_REGS(target->thread.regs)) {
+               /* We have a partial register set.  Fill 14-31 with bogus values */
+               for (i = 14; i < 32; i++)
+                       target->thread.regs->gpr[i] = NV_REG_POISON;
+       }
 
        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
                                  target->thread.regs,
@@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target,
        compat_ulong_t *k = kbuf;
        compat_ulong_t __user *u = ubuf;
        compat_ulong_t reg;
+       int i;
 
        if (target->thread.regs == NULL)
                return -EIO;
 
-       CHECK_FULL_REGS(target->thread.regs);
+       if (!FULL_REGS(target->thread.regs)) {
+               /* We have a partial register set.  Fill 14-31 with bogus values */
+               for (i = 14; i < 32; i++)
+                       target->thread.regs->gpr[i] = NV_REG_POISON; 
+       }
 
        pos /= sizeof(reg);
        count /= sizeof(reg);
index eb7021815e2da0c28e6bdc85be746e7135acd415..0f7c6718d26107c37e819be52d9794bbe7b9e883 100644 (file)
@@ -147,6 +147,16 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
 
 #endif /* CONFIG_MPIC_WEIRD */
 
+static inline unsigned int mpic_processor_id(struct mpic *mpic)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       return cpu;
+}
+
 /*
  * Register accessor functions
  */
@@ -210,19 +220,14 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
 
 static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
 {
-       unsigned int cpu = 0;
+       unsigned int cpu = mpic_processor_id(mpic);
 
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
        return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
 }
 
 static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
 {
-       unsigned int cpu = 0;
-
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
+       unsigned int cpu = mpic_processor_id(mpic);
 
        _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
 }
@@ -913,6 +918,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
        mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
 }
 
+void mpic_set_destination(unsigned int virq, unsigned int cpuid)
+{
+       struct mpic *mpic = mpic_from_irq(virq);
+       unsigned int src = mpic_irq_to_hw(virq);
+
+       DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
+           mpic, virq, src, cpuid);
+
+       if (src >= mpic->irq_count)
+               return;
+
+       mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
+}
+
 static struct irq_chip mpic_irq_chip = {
        .irq_mask       = mpic_mask_irq,
        .irq_unmask     = mpic_unmask_irq,
@@ -993,6 +1012,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
        /* Set default irq type */
        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
+        * is done here.
+        */
+       if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+               mpic_set_vector(virq, hw);
+               mpic_set_destination(virq, mpic_processor_id(mpic));
+               mpic_irq_set_priority(virq, 8);
+       }
+
        return 0;
 }
 
@@ -1040,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = {
        .xlate = mpic_host_xlate,
 };
 
+static int mpic_reset_prohibited(struct device_node *node)
+{
+       return node && of_get_property(node, "pic-no-reset", NULL);
+}
+
 /*
  * Exported functions
  */
@@ -1160,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
        /* Reset */
-       if (flags & MPIC_WANTS_RESET) {
+
+       /* When using a device-node, reset requests are only honored if the MPIC
+        * is allowed to reset.
+        */
+       if (mpic_reset_prohibited(node))
+               mpic->flags |= MPIC_NO_RESET;
+
+       if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
+               printk(KERN_DEBUG "mpic: Resetting\n");
                mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
                           | MPIC_GREG_GCONF_RESET);
@@ -1320,22 +1362,21 @@ void __init mpic_init(struct mpic *mpic)
 
        mpic_pasemi_msi_init(mpic);
 
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
-       else
-               cpu = 0;
+       cpu = mpic_processor_id(mpic);
 
-       for (i = 0; i < mpic->num_sources; i++) {
-               /* start with vector = source number, and masked */
-               u32 vecpri = MPIC_VECPRI_MASK | i |
-                       (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+       if (!(mpic->flags & MPIC_NO_RESET)) {
+               for (i = 0; i < mpic->num_sources; i++) {
+                       /* start with vector = source number, and masked */
+                       u32 vecpri = MPIC_VECPRI_MASK | i |
+                               (8 << MPIC_VECPRI_PRIORITY_SHIFT);
                
-               /* check if protected */
-               if (mpic->protected && test_bit(i, mpic->protected))
-                       continue;
-               /* init hw */
-               mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
-               mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+                       /* check if protected */
+                       if (mpic->protected && test_bit(i, mpic->protected))
+                               continue;
+                       /* init hw */
+                       mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+                       mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+               }
        }
        
        /* Init spurious vector */
index 8800cf090694766b87b6a881f28a93d77346aec2..635d677d3281e31eedf36a240b2a886e2d2f50cc 100644 (file)
@@ -6,7 +6,7 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname |  \
                        tr -c '[0-9A-Za-z]' '_'`__`date | \
                        tr -c '[0-9A-Za-z]' '_'`_t
 
-EXTRA_CFLAGS  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
+ccflags-y  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
 
 targets := image
 targets += bzImage
index e5221ec0b8e3eeb5b008aefb891841e795d98221..860d26514c08dce870a8810dee1ff1e2a676b719 100644 (file)
@@ -8,7 +8,7 @@
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm
+ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
 kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
 obj-$(CONFIG_KVM) += kvm.o
index c84890341052ce7377fbcf9eb75e11436157dea6..51d399549f604cc2632c329ec1a9776862cc3623 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_MATHEMU) := math.o
 
-EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
+ccflags-y := -I$(src) -Iinclude/math-emu -w
index cbf4801deaafc9c9bbb3cb11a3383c5e209a240d..eced3e3ebd30f5603b6a236d0bd7886e67d1ddf2 100644 (file)
@@ -13,4 +13,7 @@
 #define irq_canonicalize(irq)  (irq)
 
 extern void __init init_IRQ(void);
+
+#define NO_IRQ         0xffffffff
+
 #endif
index 4f09666f07984022543c39742231b499a5d085de..16dcae6d56e7a777b1c833bb8f6f16d57279271a 100644 (file)
@@ -97,4 +97,6 @@ extern void *softirq_stack[NR_CPUS];
 #define __ARCH_HAS_DO_SOFTIRQ
 #define ARCH_HAS_NMI_WATCHDOG
 
+#define NO_IRQ         0xffffffff
+
 #endif
index 03eb5a8f6f9363ccc55410e011328f843aa05474..2f475d7c0b53f7f127f5345a7bb1af7e81d9e8bc 100644 (file)
 #define __NR_fanotify_init     329
 #define __NR_fanotify_mark     330
 #define __NR_prlimit64         331
+#define __NR_name_to_handle_at 332
+#define __NR_open_by_handle_at 333
+#define __NR_clock_adjtime     334
 
-#define NR_syscalls            332
+#define NR_syscalls            335
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index 49ddff56cb04130ce1a84ccb0ed152ebf6516e9a..cb15bbf8a201478608672f85f55dc53f7b62247b 100644 (file)
@@ -22,6 +22,33 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index)
 }
 EXPORT_SYMBOL(irq_of_parse_and_map);
 
+int of_address_to_resource(struct device_node *node, int index,
+                          struct resource *r)
+{
+       struct platform_device *op = of_find_device_by_node(node);
+
+       if (!op || index >= op->num_resources)
+               return -EINVAL;
+
+       memcpy(r, &op->archdata.resource[index], sizeof(*r));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_address_to_resource);
+
+void __iomem *of_iomap(struct device_node *node, int index)
+{
+       struct platform_device *op = of_find_device_by_node(node);
+       struct resource *r;
+
+       if (!op || index >= op->num_resources)
+               return NULL;
+
+       r = &op->archdata.resource[index];
+
+       return of_ioremap(r, 0, resource_size(r), (char *) r->name);
+}
+EXPORT_SYMBOL(of_iomap);
+
 /* Take the archdata values for IOMMU, STC, and HOSTDATA found in
  * BUS and propagate to all child platform_device objects.
  */
index ec396e1916b92e4560505175bcdee3b59b3fef49..4b86eaf04fe57ef4ed1aa632462325a0f3372c95 100644 (file)
@@ -83,5 +83,5 @@ sys_call_table:
 /*315*/        .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/        .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/        .long sys_fanotify_mark, sys_prlimit64
+/*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 
index 8cfcaa54958054535dcd376296c1f71f780cc147..0331bafdf3a30c9d33f8d4c45228c7407eb2828f 100644 (file)
@@ -84,7 +84,7 @@ sys_call_table32:
        .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
-/*330*/        .word sys32_fanotify_mark, sys_prlimit64
+/*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
 
 #endif /* CONFIG_COMPAT */
 
@@ -160,4 +160,4 @@ sys_call_table:
        .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/        .word sys_fanotify_mark, sys_prlimit64
+/*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
index f02040d3614e25d06330ed5413b26aa87bcc53e7..46570211df5275766bdf8ef9284ab3edbb802f95 100644 (file)
@@ -202,32 +202,32 @@ static inline int *__futex_setup(int __user *v)
        return __atomic_hashed_lock((int __force *)v);
 }
 
-struct __get_user futex_set(int __user *v, int i)
+struct __get_user futex_set(u32 __user *v, int i)
 {
        return __atomic_xchg((int __force *)v, __futex_setup(v), i);
 }
 
-struct __get_user futex_add(int __user *v, int n)
+struct __get_user futex_add(u32 __user *v, int n)
 {
        return __atomic_xchg_add((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_or(int __user *v, int n)
+struct __get_user futex_or(u32 __user *v, int n)
 {
        return __atomic_or((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_andn(int __user *v, int n)
+struct __get_user futex_andn(u32 __user *v, int n)
 {
        return __atomic_andn((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_xor(int __user *v, int n)
+struct __get_user futex_xor(u32 __user *v, int n)
 {
        return __atomic_xor((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_cmpxchg(int __user *v, int o, int n)
+struct __get_user futex_cmpxchg(u32 __user *v, int o, int n)
 {
        return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n);
 }
index b8bc844fd2c46d8d9316890068d6927622aaab46..20d363bd70041d1022dd57a8f40a5405655efa90 100644 (file)
@@ -6,7 +6,7 @@ OBJ = built-in.o
 OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
        ptrace_user.o sysrq.o
 
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
 
 all: $(OBJ)
 
@@ -15,10 +15,10 @@ $(OBJ): $(OBJS)
        $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
 
 ptrace_user.o: ptrace_user.c
-       $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+       $(CC) -D__KERNEL__ $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 sigcontext.o: sigcontext.c
-       $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+       $(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 checksum.S:
        rm -f $@
@@ -53,13 +53,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
 checksum.o: checksum.S
        rm -f asm
        ln -s $(srctree)/include/asm-ppc asm
-       $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+       $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
        rm -f asm
 
 misc.o: misc.S ppc_defs.h
        rm -f asm
        ln -s $(srctree)/include/asm-ppc asm
-       $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+       $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
        rm -f asm
 
 clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
index 430312ba6e3f3b0b9cee93427feb69b18c9a5ab2..849a9d23c71d5c11080d92edbb705343879aa15e 100644 (file)
@@ -847,4 +847,5 @@ ia32_sys_call_table:
        .quad sys_name_to_handle_at
        .quad compat_sys_open_by_handle_at
        .quad compat_sys_clock_adjtime
+       .quad sys_syncfs
 ia32_syscall_end:
index ffaf183c619a21f30c24384f8aa9e106e496dfa2..a755ef5e5977540cd52b63e85374e8c4d03e7b8c 100644 (file)
 #define __NR_name_to_handle_at 341
 #define __NR_open_by_handle_at  342
 #define __NR_clock_adjtime     343
+#define __NR_syncfs             344
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 344
+#define NR_syscalls 345
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 5466bea670e7e3c14774c998fb0f90d089cb3d8a..160fa76bd5786e680da555ad96d8101a71edc99e 100644 (file)
@@ -675,6 +675,8 @@ __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
 __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
 #define __NR_clock_adjtime                     305
 __SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs                             306
+__SYSCALL(__NR_syncfs, sys_syncfs)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
index 5f181742e8f91c9510fbac2e0fd0ec7e12daf34d..abce34d5c79de0ce7e6275640a3470ccca9e1805 100644 (file)
@@ -343,3 +343,4 @@ ENTRY(sys_call_table)
        .long sys_name_to_handle_at
        .long sys_open_by_handle_at
        .long sys_clock_adjtime
+       .long sys_syncfs
index 40aa55b485be91747ebc401f5d5d4047ce71aa11..70fd1453e172abcd48c54e11b8fd0af278f3fe45 100644 (file)
@@ -14,7 +14,7 @@ HOSTFLAGS     += -Iarch/$(ARCH)/boot/include
 
 BIG_ENDIAN     := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
 
-export EXTRA_CFLAGS
+export ccflags-y
 export BIG_ENDIAN
 
 subdir-y       := lib
index d3d2aa2d883aa6e4d9abfc7571b7e3e5eadbc30f..ad8952e8a07f6d369192416d831917cd642f9075 100644 (file)
@@ -6,7 +6,7 @@ zlib    := inffast.c inflate.c inftrees.c
 
 lib-y  += $(zlib:.c=.o) zmem.o
 
-EXTRA_CFLAGS   += -Ilib/zlib_inflate
+ccflags-y      := -Ilib/zlib_inflate
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = cat $< > $@
index 26b4fce217b6475ecb3e8a696cb82e4f9f0cccb6..efa6a82e543dc70aab8be26359e73fc46e5cd589 100644 (file)
@@ -9,7 +9,7 @@ obj-$(CONFIG_MWAVE) += mwave.o
 mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o
 
 # To have the mwave driver disable other uarts if necessary
-# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
+# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES
 
 # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
-ccflags-y := -DMW_TRACE
+ccflags-y += -DMW_TRACE
index 480251fc78e2865dd3d387e59074fcefbce77b12..c2a58f428bc84778c0ca3f09d372cbecc8b24191 100644 (file)
@@ -11,7 +11,7 @@ are not saved by the BIOS and so do not persist after unload and reload.
        0x0008 tp3780i tracing
 
         Tracing only occurs if the driver has been compiled with the
-        MW_TRACE macro #defined  (i.e. let EXTRA_CFLAGS += -DMW_TRACE
+        MW_TRACE macro #defined  (i.e. let ccflags-y := -DMW_TRACE
         in the Makefile).
 
   mwave_3780i_irq=5/7/10/11/15
index 64b21f5cd740fc5dfa1d5f09b1a944ed1f661440..1be065a62f8c6784a17a814d7cfcc632ac67b368 100644 (file)
@@ -1,9 +1,5 @@
-ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-       ccflags-y       += -DDEBUG
-endif
-ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-       ccflags-y       += -DVERBOSE_DEBUG
-endif
+ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
+ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
index 0c56989cd9073b4d0770a5ad4d15d11a907605c1..2be6f452077257bcd7d085eea00bfda70de86e54 100644 (file)
@@ -75,7 +75,8 @@ config FIREWIRE_NOSY
          The following cards are known to be based on PCILynx or PCILynx-2:
          IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-2
          (PCI card), Newer Technology FireWire 2 Go (CardBus card),
-         Apple Power Mac G3 blue & white (onboard controller).
+         Apple Power Mac G3 blue & white and G4 with PCI graphics
+         (onboard controller).
 
          To compile this driver as a module, say M here:  The module will be
          called nosy.  Source code of a userspace interface to nosy, called
index 24ff35511e2b1b6a890e7fc9f9499e75c74459d1..3c44fbc81acba5758a38b77169dfe566c9b1cfd5 100644 (file)
@@ -75,6 +75,13 @@ static size_t config_rom_length = 1 + 4 + 1 + 1;
 #define BIB_IRMC               ((1) << 31)
 #define NODE_CAPABILITIES      0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
 
+/*
+ * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms),
+ * but we have to make it longer because there are many devices whose firmware
+ * is just too slow for that.
+ */
+#define DEFAULT_SPLIT_TIMEOUT  (2 * 8000)
+
 #define CANON_OUI              0x000085
 
 static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
@@ -233,7 +240,7 @@ static void br_work(struct work_struct *work)
 
        /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
        if (card->reset_jiffies != 0 &&
-           time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {
+           time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
                if (!schedule_delayed_work(&card->br_work, 2 * HZ))
                        fw_card_put(card);
                return;
@@ -316,7 +323,8 @@ static void bm_work(struct work_struct *work)
        irm_id   = card->irm_node->node_id;
        local_id = card->local_node->node_id;
 
-       grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
+       grace = time_after64(get_jiffies_64(),
+                            card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
 
        if ((is_next_generation(generation, card->bm_generation) &&
             !card->bm_abdicate) ||
@@ -511,10 +519,11 @@ void fw_card_initialize(struct fw_card *card,
        card->device = device;
        card->current_tlabel = 0;
        card->tlabel_mask = 0;
-       card->split_timeout_hi = 0;
-       card->split_timeout_lo = 800 << 19;
-       card->split_timeout_cycles = 800;
-       card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);
+       card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000;
+       card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19;
+       card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT;
+       card->split_timeout_jiffies =
+                       DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000);
        card->color = 0;
        card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
 
index 48ae712e21018e64cca840b3e146b728bda72f99..62ac111af2432d4f8f0c3216be5bf724343e4ea8 100644 (file)
@@ -64,6 +64,7 @@ struct client {
        struct idr resource_idr;
        struct list_head event_list;
        wait_queue_head_t wait;
+       wait_queue_head_t tx_flush_wait;
        u64 bus_reset_closure;
 
        struct fw_iso_context *iso_context;
@@ -251,6 +252,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
        idr_init(&client->resource_idr);
        INIT_LIST_HEAD(&client->event_list);
        init_waitqueue_head(&client->wait);
+       init_waitqueue_head(&client->tx_flush_wait);
        INIT_LIST_HEAD(&client->phy_receiver_link);
        kref_init(&client->kref);
 
@@ -520,10 +522,6 @@ static int release_client_resource(struct client *client, u32 handle,
 static void release_transaction(struct client *client,
                                struct client_resource *resource)
 {
-       struct outbound_transaction_resource *r = container_of(resource,
-                       struct outbound_transaction_resource, resource);
-
-       fw_cancel_transaction(client->device->card, &r->transaction);
 }
 
 static void complete_transaction(struct fw_card *card, int rcode,
@@ -540,22 +538,9 @@ static void complete_transaction(struct fw_card *card, int rcode,
                memcpy(rsp->data, payload, rsp->length);
 
        spin_lock_irqsave(&client->lock, flags);
-       /*
-        * 1. If called while in shutdown, the idr tree must be left untouched.
-        *    The idr handle will be removed and the client reference will be
-        *    dropped later.
-        * 2. If the call chain was release_client_resource ->
-        *    release_transaction -> complete_transaction (instead of a normal
-        *    conclusion of the transaction), i.e. if this resource was already
-        *    unregistered from the idr, the client reference will be dropped
-        *    by release_client_resource and we must not drop it here.
-        */
-       if (!client->in_shutdown &&
-           idr_find(&client->resource_idr, e->r.resource.handle)) {
-               idr_remove(&client->resource_idr, e->r.resource.handle);
-               /* Drop the idr's reference */
-               client_put(client);
-       }
+       idr_remove(&client->resource_idr, e->r.resource.handle);
+       if (client->in_shutdown)
+               wake_up(&client->tx_flush_wait);
        spin_unlock_irqrestore(&client->lock, flags);
 
        rsp->type = FW_CDEV_EVENT_RESPONSE;
@@ -575,7 +560,7 @@ static void complete_transaction(struct fw_card *card, int rcode,
                queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
                            NULL, 0);
 
-       /* Drop the transaction callback's reference */
+       /* Drop the idr's reference */
        client_put(client);
 }
 
@@ -614,9 +599,6 @@ static int init_request(struct client *client,
        if (ret < 0)
                goto failed;
 
-       /* Get a reference for the transaction callback */
-       client_get(client);
-
        fw_send_request(client->device->card, &e->r.transaction,
                        request->tcode, destination_id, request->generation,
                        speed, request->offset, e->response.data,
@@ -1223,7 +1205,8 @@ static void iso_resource_work(struct work_struct *work)
        todo = r->todo;
        /* Allow 1000ms grace period for other reallocations. */
        if (todo == ISO_RES_ALLOC &&
-           time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
+           time_before64(get_jiffies_64(),
+                         client->device->card->reset_jiffies + HZ)) {
                schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
                skip = true;
        } else {
@@ -1678,6 +1661,25 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
+static int is_outbound_transaction_resource(int id, void *p, void *data)
+{
+       struct client_resource *resource = p;
+
+       return resource->release == release_transaction;
+}
+
+static int has_outbound_transactions(struct client *client)
+{
+       int ret;
+
+       spin_lock_irq(&client->lock);
+       ret = idr_for_each(&client->resource_idr,
+                          is_outbound_transaction_resource, NULL);
+       spin_unlock_irq(&client->lock);
+
+       return ret;
+}
+
 static int shutdown_resource(int id, void *p, void *data)
 {
        struct client_resource *resource = p;
@@ -1713,6 +1715,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
        client->in_shutdown = true;
        spin_unlock_irq(&client->lock);
 
+       wait_event(client->tx_flush_wait, !has_outbound_transactions(client));
+
        idr_for_each(&client->resource_idr, shutdown_resource, client);
        idr_remove_all(&client->resource_idr);
        idr_destroy(&client->resource_idr);
index 6113b896e7901013d8564967e45edd5d8988c5d7..9a262439e3a7220aa8bd4712acb73dc99b63fb62 100644 (file)
@@ -747,7 +747,8 @@ static void fw_device_shutdown(struct work_struct *work)
                container_of(work, struct fw_device, work.work);
        int minor = MINOR(device->device.devt);
 
-       if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
+       if (time_before64(get_jiffies_64(),
+                         device->card->reset_jiffies + SHUTDOWN_DELAY)
            && !list_empty(&device->card->link)) {
                schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
                return;
@@ -954,8 +955,9 @@ static void fw_device_init(struct work_struct *work)
                        device->config_rom_retries++;
                        schedule_delayed_work(&device->work, RETRY_DELAY);
                } else {
-                       fw_notify("giving up on config rom for node id %x\n",
-                                 device->node_id);
+                       if (device->node->link_on)
+                               fw_notify("giving up on config rom for node id %x\n",
+                                         device->node_id);
                        if (device->node == device->card->root_node)
                                fw_schedule_bm_work(device->card, 0);
                        fw_device_release(&device->device);
@@ -1168,9 +1170,12 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
 
        switch (event) {
        case FW_NODE_CREATED:
-       case FW_NODE_LINK_ON:
-               if (!node->link_on)
-                       break;
+               /*
+                * Attempt to scan the node, regardless whether its self ID has
+                * the L (link active) flag set or not.  Some broken devices
+                * send L=0 but have an up-and-running link; others send L=1
+                * without actually having a link.
+                */
  create:
                device = kzalloc(sizeof(*device), GFP_ATOMIC);
                if (device == NULL)
@@ -1213,6 +1218,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                break;
 
        case FW_NODE_INITIATED_RESET:
+       case FW_NODE_LINK_ON:
                device = node->data;
                if (device == NULL)
                        goto create;
@@ -1230,10 +1236,10 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                break;
 
        case FW_NODE_UPDATED:
-               if (!node->link_on || node->data == NULL)
+               device = node->data;
+               if (device == NULL)
                        break;
 
-               device = node->data;
                device->node_id = node->node_id;
                smp_wmb();  /* update node_id before generation */
                device->generation = card->generation;
index c8658888e67bac701df8cf603b52220f5d219009..481056df9268db5cb51979c83a337715c7c6fb42 100644 (file)
@@ -235,45 +235,45 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
 static int manage_channel(struct fw_card *card, int irm_id, int generation,
                u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
 {
-       __be32 c, all, old;
-       int i, ret = -EIO, retry = 5;
+       __be32 bit, all, old;
+       int channel, ret = -EIO, retry = 5;
 
        old = all = allocate ? cpu_to_be32(~0) : 0;
 
-       for (i = 0; i < 32; i++) {
-               if (!(channels_mask & 1 << i))
+       for (channel = 0; channel < 32; channel++) {
+               if (!(channels_mask & 1 << channel))
                        continue;
 
                ret = -EBUSY;
 
-               c = cpu_to_be32(1 << (31 - i));
-               if ((old & c) != (all & c))
+               bit = cpu_to_be32(1 << (31 - channel));
+               if ((old & bit) != (all & bit))
                        continue;
 
                data[0] = old;
-               data[1] = old ^ c;
+               data[1] = old ^ bit;
                switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
                                           irm_id, generation, SCODE_100,
                                           offset, data, 8)) {
                case RCODE_GENERATION:
                        /* A generation change frees all channels. */
-                       return allocate ? -EAGAIN : i;
+                       return allocate ? -EAGAIN : channel;
 
                case RCODE_COMPLETE:
                        if (data[0] == old)
-                               return i;
+                               return channel;
 
                        old = data[0];
 
                        /* Is the IRM 1394a-2000 compliant? */
-                       if ((data[0] & c) == (data[1] & c))
+                       if ((data[0] & bit) == (data[1] & bit))
                                continue;
 
                        /* 1394-1995 IRM, fall through to retry. */
                default:
                        if (retry) {
                                retry--;
-                               i--;
+                               channel--;
                        } else {
                                ret = -EIO;
                        }
index 09be1a635505c4737283f595ef8c5ab70fffb631..193ed9233144b458a486dfd13f7217037522efc9 100644 (file)
@@ -545,7 +545,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
         */
        smp_wmb();
        card->generation = generation;
-       card->reset_jiffies = jiffies;
+       card->reset_jiffies = get_jiffies_64();
        card->bm_node_id  = 0xffff;
        card->bm_abdicate = bm_abdicate;
        fw_schedule_bm_work(card, 0);
index bd3c61b6dd8d5a76cab9f6380fd4e4a08e959ed6..f903d7b6f34a92bca580b5ed01cf422c9a8caf7c 100644 (file)
@@ -208,9 +208,11 @@ struct fw_ohci {
        struct context at_request_ctx;
        struct context at_response_ctx;
 
+       u32 it_context_support;
        u32 it_context_mask;     /* unoccupied IT contexts */
        struct iso_context *it_context_list;
        u64 ir_context_channels; /* unoccupied channels */
+       u32 ir_context_support;
        u32 ir_context_mask;     /* unoccupied IR contexts */
        struct iso_context *ir_context_list;
        u64 mc_channels; /* channels in use by the multichannel IR context */
@@ -338,7 +340,7 @@ static void log_irqs(u32 evt)
            !(evt & OHCI1394_busReset))
                return;
 
-       fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+       fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
            evt & OHCI1394_selfIDComplete       ? " selfID"             : "",
            evt & OHCI1394_RQPkt                ? " AR_req"             : "",
            evt & OHCI1394_RSPkt                ? " AR_resp"            : "",
@@ -351,6 +353,7 @@ static void log_irqs(u32 evt)
            evt & OHCI1394_cycle64Seconds       ? " cycle64Seconds"     : "",
            evt & OHCI1394_cycleInconsistent    ? " cycleInconsistent"  : "",
            evt & OHCI1394_regAccessFail        ? " regAccessFail"      : "",
+           evt & OHCI1394_unrecoverableError   ? " unrecoverableError" : "",
            evt & OHCI1394_busReset             ? " busReset"           : "",
            evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
                    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
@@ -1326,21 +1329,8 @@ static int at_context_queue_packet(struct context *ctx,
                                     DESCRIPTOR_IRQ_ALWAYS |
                                     DESCRIPTOR_BRANCH_ALWAYS);
 
-       /*
-        * If the controller and packet generations don't match, we need to
-        * bail out and try again.  If IntEvent.busReset is set, the AT context
-        * is halted, so appending to the context and trying to run it is
-        * futile.  Most controllers do the right thing and just flush the AT
-        * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
-        * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
-        * up stalling out.  So we just bail out in software and try again
-        * later, and everyone is happy.
-        * FIXME: Test of IntEvent.busReset may no longer be necessary since we
-        *        flush AT queues in bus_reset_tasklet.
-        * FIXME: Document how the locking works.
-        */
-       if (ohci->generation != packet->generation ||
-           reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+       /* FIXME: Document how the locking works. */
+       if (ohci->generation != packet->generation) {
                if (packet->payload_mapped)
                        dma_unmap_single(ohci->card.device, payload_bus,
                                         packet->payload_length, DMA_TO_DEVICE);
@@ -1590,6 +1580,47 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
 
 }
 
+static void detect_dead_context(struct fw_ohci *ohci,
+                               const char *name, unsigned int regs)
+{
+       u32 ctl;
+
+       ctl = reg_read(ohci, CONTROL_SET(regs));
+       if (ctl & CONTEXT_DEAD) {
+#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
+               fw_error("DMA context %s has stopped, error code: %s\n",
+                        name, evts[ctl & 0x1f]);
+#else
+               fw_error("DMA context %s has stopped, error code: %#x\n",
+                        name, ctl & 0x1f);
+#endif
+       }
+}
+
+static void handle_dead_contexts(struct fw_ohci *ohci)
+{
+       unsigned int i;
+       char name[8];
+
+       detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase);
+       detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase);
+       detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase);
+       detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase);
+       for (i = 0; i < 32; ++i) {
+               if (!(ohci->it_context_support & (1 << i)))
+                       continue;
+               sprintf(name, "IT%u", i);
+               detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i));
+       }
+       for (i = 0; i < 32; ++i) {
+               if (!(ohci->ir_context_support & (1 << i)))
+                       continue;
+               sprintf(name, "IR%u", i);
+               detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i));
+       }
+       /* TODO: maybe try to flush and restart the dead contexts */
+}
+
 static u32 cycle_timer_ticks(u32 cycle_timer)
 {
        u32 ticks;
@@ -1904,6 +1935,9 @@ static irqreturn_t irq_handler(int irq, void *data)
                        fw_notify("isochronous cycle inconsistent\n");
        }
 
+       if (unlikely(event & OHCI1394_unrecoverableError))
+               handle_dead_contexts(ohci);
+
        if (event & OHCI1394_cycle64Seconds) {
                spin_lock(&ohci->lock);
                update_bus_time(ohci);
@@ -2141,7 +2175,9 @@ static int ohci_enable(struct fw_card *card,
                OHCI1394_selfIDComplete |
                OHCI1394_regAccessFail |
                OHCI1394_cycle64Seconds |
-               OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong |
+               OHCI1394_cycleInconsistent |
+               OHCI1394_unrecoverableError |
+               OHCI1394_cycleTooLong |
                OHCI1394_masterIntEnable;
        if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
                irqs |= OHCI1394_busReset;
@@ -2657,6 +2693,10 @@ static int ohci_start_iso(struct fw_iso_context *base,
        u32 control = IR_CONTEXT_ISOCH_HEADER, match;
        int index;
 
+       /* the controller cannot start without any queued packets */
+       if (ctx->context.last->branch_address == 0)
+               return -ENODATA;
+
        switch (ctx->base.type) {
        case FW_ISO_CONTEXT_TRANSMIT:
                index = ctx - ohci->it_context_list;
@@ -2715,6 +2755,7 @@ static int ohci_stop_iso(struct fw_iso_context *base)
        }
        flush_writes(ohci);
        context_stop(&ctx->context);
+       tasklet_kill(&ctx->context.tasklet);
 
        return 0;
 }
@@ -3207,15 +3248,17 @@ static int __devinit pci_probe(struct pci_dev *dev,
 
        reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
        ohci->ir_context_channels = ~0ULL;
-       ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+       ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
        reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
+       ohci->ir_context_mask = ohci->ir_context_support;
        ohci->n_ir = hweight32(ohci->ir_context_mask);
        size = sizeof(struct iso_context) * ohci->n_ir;
        ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
 
        reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
-       ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+       ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
        reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
+       ohci->it_context_mask = ohci->it_context_support;
        ohci->n_it = hweight32(ohci->it_context_mask);
        size = sizeof(struct iso_context) * ohci->n_it;
        ohci->it_context_list = kzalloc(size, GFP_KERNEL);
@@ -3266,7 +3309,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
  fail_disable:
        pci_disable_device(dev);
  fail_free:
-       kfree(&ohci->card);
+       kfree(ohci);
        pmac_ohci_off(dev);
  fail:
        if (err == -ENOMEM)
@@ -3310,7 +3353,7 @@ static void pci_remove(struct pci_dev *dev)
        pci_iounmap(dev, ohci->registers);
        pci_release_region(dev, 0);
        pci_disable_device(dev);
-       kfree(&ohci->card);
+       kfree(ohci);
        pmac_ohci_off(dev);
 
        fw_notify("Removed fw-ohci device.\n");
index afa576a75a8ed443273d4722c03edc2bb8c31720..77ed589b360d7dce2d7567685fa032f96f40ed54 100644 (file)
@@ -472,18 +472,12 @@ static void complete_transaction(struct fw_card *card, int rcode,
         * So this callback only sets the rcode if it hasn't already
         * been set and only does the cleanup if the transaction
         * failed and we didn't already get a status write.
-        *
-        * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
-        * OXUF936QSE firmwares occasionally respond after Split_Timeout and
-        * complete the ORB just fine.  Note, we also get RCODE_CANCELLED
-        * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
         */
        spin_lock_irqsave(&card->lock, flags);
 
        if (orb->rcode == -1)
                orb->rcode = rcode;
-
-       if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
+       if (orb->rcode != RCODE_COMPLETE) {
                list_del(&orb->link);
                spin_unlock_irqrestore(&card->lock, flags);
 
@@ -532,7 +526,8 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 
        list_for_each_entry_safe(orb, next, &list, link) {
                retval = 0;
-               fw_cancel_transaction(device->card, &orb->t);
+               if (fw_cancel_transaction(device->card, &orb->t) == 0)
+                       continue;
 
                orb->rcode = RCODE_CANCELLED;
                orb->callback(orb, NULL);
index 61aa712333927815e5cb9d0d4777e8de3dacd1af..b85744fe846477221ad02221f78bb397c603f54d 100644 (file)
@@ -481,6 +481,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index c3d66269ed7d584bb655be926cef4b8e073699a9..e9687768a335d5461e1ed7785d0d8bd551af3724 100644 (file)
@@ -1333,6 +1333,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -1840,6 +1843,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index d485894ff4db877f2045db8c21934cbd2d41d547..65ac53d7aeccf86a9f3a0c1e7a6a9c00af0a470f 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI  0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO   0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS   0x0244
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI   0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO    0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS    0x0247
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
index cd74203c8178950408b95cb51dd69b01ccb1ceea..33dde8724e02faec04fe1388103343a4cf03eda2 100644 (file)
@@ -900,8 +900,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                        hid->ll_driver->hidinput_input_event;
                                input_dev->open = hidinput_open;
                                input_dev->close = hidinput_close;
-                               input_dev->setkeycode_new = hidinput_setkeycode;
-                               input_dev->getkeycode_new = hidinput_getkeycode;
+                               input_dev->setkeycode = hidinput_setkeycode;
+                               input_dev->getkeycode = hidinput_getkeycode;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
index 1bfb4439e4e1cb34fa4cb31a71eaf9a7db024071..e4bd13b3cd8b7e21dfeb3bb61b4762ba275033ba 100644 (file)
@@ -521,7 +521,7 @@ config SENSORS_LM75
                - Dallas Semiconductor DS75 and DS1775
                - Maxim MAX6625 and MAX6626
                - Microchip MCP980x
-               - National Semiconductor LM75
+               - National Semiconductor LM75, LM75A
                - NXP's LM75A
                - ST Microelectronics STDS75
                - TelCom (now Microchip) TCN75
@@ -959,6 +959,25 @@ config SENSORS_SMSC47B397
          This driver can also be built as a module.  If so, the module
          will be called smsc47b397.
 
+config SENSORS_SCH5627
+       tristate "SMSC SCH5627"
+       help
+         If you say yes here you get support for the hardware monitoring
+         features of the SMSC SCH5627 Super-I/O chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called sch5627.
+
+config SENSORS_ADS1015
+       tristate "Texas Instruments ADS1015"
+       depends on I2C
+       help
+         If you say yes here you get support for Texas Instruments ADS1015
+         12-bit 4-input ADC device.
+
+         This driver can also be built as a module.  If so, the module
+         will be called ads1015.
+
 config SENSORS_ADS7828
        tristate "Texas Instruments ADS7828"
        depends on I2C
@@ -1215,40 +1234,6 @@ config SENSORS_ULTRA45
          This driver provides support for the Ultra45 workstation environmental
          sensors.
 
-config SENSORS_LIS3_SPI
-       tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
-       depends on !ACPI && SPI_MASTER && INPUT
-       select INPUT_POLLDEV
-       default n
-       help
-         This driver provides support for the LIS3LV02Dx accelerometer connected
-         via SPI. The accelerometer data is readable via
-         /sys/devices/platform/lis3lv02d.
-
-         This driver also provides an absolute input class device, allowing
-         the laptop to act as a pinball machine-esque joystick.
-
-         This driver can also be built as modules.  If so, the core module
-         will be called lis3lv02d and a specific module for the SPI transport
-         is called lis3lv02d_spi.
-
-config SENSORS_LIS3_I2C
-       tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
-       depends on I2C && INPUT
-       select INPUT_POLLDEV
-       default n
-       help
-         This driver provides support for the LIS3LV02Dx accelerometer connected
-         via I2C. The accelerometer data is readable via
-         /sys/devices/platform/lis3lv02d.
-
-         This driver also provides an absolute input class device, allowing
-         the device to act as a pinball machine-esque joystick.
-
-         This driver can also be built as modules.  If so, the core module
-         will be called lis3lv02d and a specific module for the I2C transport
-         is called lis3lv02d_i2c.
-
 config SENSORS_APPLESMC
        tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
        depends on INPUT && X86
@@ -1296,36 +1281,6 @@ config SENSORS_ATK0110
          This driver can also be built as a module. If so, the module
          will be called asus_atk0110.
 
-config SENSORS_LIS3LV02D
-       tristate "STMicroeletronics LIS3* three-axis digital accelerometer"
-       depends on INPUT
-       select INPUT_POLLDEV
-       select NEW_LEDS
-       select LEDS_CLASS
-       default n
-       help
-         This driver provides support for the LIS3* accelerometers, such as the
-         LIS3LV02DL or the LIS331DL. In particular, it can be found in a number
-         of HP laptops, which have the "Mobile Data Protection System 3D" or
-         "3D DriveGuard" feature. On such systems the driver should load
-         automatically (via ACPI alias). The accelerometer might also be found
-         in other systems, connected via SPI or I2C. The accelerometer data is
-         readable via /sys/devices/platform/lis3lv02d.
-
-         This driver also provides an absolute input class device, allowing
-         a laptop to act as a pinball machine-esque joystick. It provides also
-         a misc device which can be used to detect free-fall. On HP laptops,
-         if the led infrastructure is activated, support for a led indicating
-         disk protection will be provided as hp::hddprotect. For more
-         information on the feature, refer to Documentation/hwmon/lis3lv02d.
-
-         This driver can also be built as modules.  If so, the core module
-         will be called lis3lv02d and a specific module for HP laptops will be
-         called hp_accel.
-
-         Say Y here if you have an applicable laptop and want to experience
-         the awesome power of lis3lv02d.
-
 endif # ACPI
 
 endif # HWMON
index bd0410e4b44f2fdbf39769a305291362c120bb35..54ca5939d028e1e40f7e4f7511b07055741c6486 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
 obj-$(CONFIG_SENSORS_ADM1029)  += adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)  += adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)  += adm9240.o
+obj-$(CONFIG_SENSORS_ADS1015)  += ads1015.o
 obj-$(CONFIG_SENSORS_ADS7828)  += ads7828.o
 obj-$(CONFIG_SENSORS_ADS7871)  += ads7871.o
 obj-$(CONFIG_SENSORS_ADT7411)  += adt7411.o
@@ -63,9 +64,6 @@ obj-$(CONFIG_SENSORS_JZ4740)  += jz4740-hwmon.o
 obj-$(CONFIG_SENSORS_K8TEMP)   += k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)  += k10temp.o
 obj-$(CONFIG_SENSORS_LINEAGE)  += lineage-pem.o
-obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
-obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o
-obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o
 obj-$(CONFIG_SENSORS_LM63)     += lm63.o
 obj-$(CONFIG_SENSORS_LM70)     += lm70.o
 obj-$(CONFIG_SENSORS_LM73)     += lm73.o
@@ -93,6 +91,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
 obj-$(CONFIG_SENSORS_S3C)      += s3c-hwmon.o
+obj-$(CONFIG_SENSORS_SCH5627)  += sch5627.o
 obj-$(CONFIG_SENSORS_SHT15)    += sht15.o
 obj-$(CONFIG_SENSORS_SHT21)    += sht21.o
 obj-$(CONFIG_SENSORS_SIS5595)  += sis5595.o
@@ -122,7 +121,5 @@ obj-$(CONFIG_SENSORS_MAX16064)      += max16064.o
 obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)  += max8688.o
 
-ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
 
index 8f07a9dda15216073df1cd937f68d33787e71306..0e05aa179eaa09c1c52763be60a84d1d41d3d3db 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+    abituguru.c Copyright (c) 2005-2006 Hans de Goede <hdegoede@redhat.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
@@ -1505,7 +1505,7 @@ static void __exit abituguru_exit(void)
        platform_driver_unregister(&abituguru_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru Sensor device");
 MODULE_LICENSE("GPL");
 
index 48d21e22e9302a66e2d8b467ea5c42532875514e..034cebfcd273cec998779f3c50b5da473f696d1a 100644 (file)
@@ -1,7 +1,7 @@
 /*
     abituguru3.c
 
-    Copyright (c) 2006-2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+    Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
     Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
 
     This program is free software; you can redistribute it and/or modify
@@ -1266,7 +1266,7 @@ static void __exit abituguru3_exit(void)
        platform_driver_unregister(&abituguru3_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
new file mode 100644 (file)
index 0000000..e9beeda
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+ *
+ * Based on the ads7828 driver by Steve Hardy.
+ *
+ * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <linux/i2c/ads1015.h>
+
+/* ADS1015 registers */
+enum {
+       ADS1015_CONVERSION = 0,
+       ADS1015_CONFIG = 1,
+};
+
+/* PGA fullscale voltages in mV */
+static const unsigned int fullscale_table[8] = {
+       6144, 4096, 2048, 1024, 512, 256, 256, 256 };
+
+/* Data rates in samples per second */
+static const unsigned int data_rate_table[8] = {
+       128, 250, 490, 920, 1600, 2400, 3300, 3300 };
+
+#define ADS1015_DEFAULT_CHANNELS 0xff
+#define ADS1015_DEFAULT_PGA 2
+#define ADS1015_DEFAULT_DATA_RATE 4
+
+struct ads1015_data {
+       struct device *hwmon_dev;
+       struct mutex update_lock; /* mutex protect updates */
+       struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+};
+
+static s32 ads1015_read_reg(struct i2c_client *client, unsigned int reg)
+{
+       s32 data = i2c_smbus_read_word_data(client, reg);
+
+       return (data < 0) ? data : swab16(data);
+}
+
+static s32 ads1015_write_reg(struct i2c_client *client, unsigned int reg,
+                            u16 val)
+{
+       return i2c_smbus_write_word_data(client, reg, swab16(val));
+}
+
+static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
+                             int *value)
+{
+       u16 config;
+       s16 conversion;
+       struct ads1015_data *data = i2c_get_clientdata(client);
+       unsigned int pga = data->channel_data[channel].pga;
+       int fullscale;
+       unsigned int data_rate = data->channel_data[channel].data_rate;
+       unsigned int conversion_time_ms;
+       int res;
+
+       mutex_lock(&data->update_lock);
+
+       /* get channel parameters */
+       res = ads1015_read_reg(client, ADS1015_CONFIG);
+       if (res < 0)
+               goto err_unlock;
+       config = res;
+       fullscale = fullscale_table[pga];
+       conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
+
+       /* setup and start single conversion */
+       config &= 0x001f;
+       config |= (1 << 15) | (1 << 8);
+       config |= (channel & 0x0007) << 12;
+       config |= (pga & 0x0007) << 9;
+       config |= (data_rate & 0x0007) << 5;
+
+       res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+       if (res < 0)
+               goto err_unlock;
+
+       /* wait until conversion finished */
+       msleep(conversion_time_ms);
+       res = ads1015_read_reg(client, ADS1015_CONFIG);
+       if (res < 0)
+               goto err_unlock;
+       config = res;
+       if (!(config & (1 << 15))) {
+               /* conversion not finished in time */
+               res = -EIO;
+               goto err_unlock;
+       }
+
+       res = ads1015_read_reg(client, ADS1015_CONVERSION);
+       if (res < 0)
+               goto err_unlock;
+       conversion = res;
+
+       mutex_unlock(&data->update_lock);
+
+       *value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
+
+       return 0;
+
+err_unlock:
+       mutex_unlock(&data->update_lock);
+       return res;
+}
+
+/* sysfs callback function */
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+       char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct i2c_client *client = to_i2c_client(dev);
+       int in;
+       int res;
+
+       res = ads1015_read_value(client, attr->index, &in);
+
+       return (res < 0) ? res : sprintf(buf, "%d\n", in);
+}
+
+static const struct sensor_device_attribute ads1015_in[] = {
+       SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+       SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+       SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+       SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+       SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+       SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+       SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+       SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+};
+
+/*
+ * Driver interface
+ */
+
+static int ads1015_remove(struct i2c_client *client)
+{
+       struct ads1015_data *data = i2c_get_clientdata(client);
+       int k;
+
+       hwmon_device_unregister(data->hwmon_dev);
+       for (k = 0; k < ADS1015_CHANNELS; ++k)
+               device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+       kfree(data);
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static int ads1015_get_channels_config_of(struct i2c_client *client)
+{
+       struct ads1015_data *data = i2c_get_clientdata(client);
+       struct device_node *node;
+
+       if (!client->dev.of_node
+           || !of_get_next_child(client->dev.of_node, NULL))
+               return -EINVAL;
+
+       for_each_child_of_node(client->dev.of_node, node) {
+               const __be32 *property;
+               int len;
+               unsigned int channel;
+               unsigned int pga = ADS1015_DEFAULT_PGA;
+               unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
+
+               property = of_get_property(node, "reg", &len);
+               if (!property || len != sizeof(int)) {
+                       dev_err(&client->dev, "invalid reg on %s\n",
+                               node->full_name);
+                       continue;
+               }
+
+               channel = be32_to_cpup(property);
+               if (channel > ADS1015_CHANNELS) {
+                       dev_err(&client->dev,
+                               "invalid channel index %d on %s\n",
+                               channel, node->full_name);
+                       continue;
+               }
+
+               property = of_get_property(node, "ti,gain", &len);
+               if (property && len == sizeof(int)) {
+                       pga = be32_to_cpup(property);
+                       if (pga > 6) {
+                               dev_err(&client->dev,
+                                       "invalid gain on %s\n",
+                                       node->full_name);
+                       }
+               }
+
+               property = of_get_property(node, "ti,datarate", &len);
+               if (property && len == sizeof(int)) {
+                       data_rate = be32_to_cpup(property);
+                       if (data_rate > 7) {
+                               dev_err(&client->dev,
+                                       "invalid data_rate on %s\n",
+                                       node->full_name);
+                       }
+               }
+
+               data->channel_data[channel].enabled = true;
+               data->channel_data[channel].pga = pga;
+               data->channel_data[channel].data_rate = data_rate;
+       }
+
+       return 0;
+}
+#endif
+
+static void ads1015_get_channels_config(struct i2c_client *client)
+{
+       unsigned int k;
+       struct ads1015_data *data = i2c_get_clientdata(client);
+       struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
+
+       /* prefer platform data */
+       if (pdata) {
+               memcpy(data->channel_data, pdata->channel_data,
+                      sizeof(data->channel_data));
+               return;
+       }
+
+#ifdef CONFIG_OF
+       if (!ads1015_get_channels_config_of(client))
+               return;
+#endif
+
+       /* fallback on default configuration */
+       for (k = 0; k < ADS1015_CHANNELS; ++k) {
+               data->channel_data[k].enabled = true;
+               data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
+               data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE;
+       }
+}
+
+static int ads1015_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct ads1015_data *data;
+       int err;
+       unsigned int k;
+
+       data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->update_lock);
+
+       /* build sysfs attribute group */
+       ads1015_get_channels_config(client);
+       for (k = 0; k < ADS1015_CHANNELS; ++k) {
+               if (!data->channel_data[k].enabled)
+                       continue;
+               err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
+               if (err)
+                       goto exit_free;
+       }
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               goto exit_remove;
+       }
+
+       return 0;
+
+exit_remove:
+       for (k = 0; k < ADS1015_CHANNELS; ++k)
+               device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+exit_free:
+       kfree(data);
+exit:
+       return err;
+}
+
+static const struct i2c_device_id ads1015_id[] = {
+       { "ads1015", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ads1015_id);
+
+static struct i2c_driver ads1015_driver = {
+       .driver = {
+               .name = "ads1015",
+       },
+       .probe = ads1015_probe,
+       .remove = ads1015_remove,
+       .id_table = ads1015_id,
+};
+
+static int __init sensors_ads1015_init(void)
+{
+       return i2c_add_driver(&ads1015_driver);
+}
+
+static void __exit sensors_ads1015_exit(void)
+{
+       i2c_del_driver(&ads1015_driver);
+}
+
+MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
+MODULE_DESCRIPTION("ADS1015 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_ads1015_init);
+module_exit(sensors_ads1015_exit);
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
deleted file mode 100644 (file)
index 3d21fa2..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  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/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/leds.h>
-#include <acpi/acpi_drivers.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-#define ACPI_MDPS_CLASS "accelerometer"
-
-/* Delayed LEDs infrastructure ------------------------------------ */
-
-/* Special LED class that can defer work */
-struct delayed_led_classdev {
-       struct led_classdev led_classdev;
-       struct work_struct work;
-       enum led_brightness new_brightness;
-
-       unsigned int led;               /* For driver */
-       void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
-};
-
-static inline void delayed_set_status_worker(struct work_struct *work)
-{
-       struct delayed_led_classdev *data =
-                       container_of(work, struct delayed_led_classdev, work);
-
-       data->set_brightness(data, data->new_brightness);
-}
-
-static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
-                             enum led_brightness brightness)
-{
-       struct delayed_led_classdev *data = container_of(led_cdev,
-                            struct delayed_led_classdev, led_classdev);
-       data->new_brightness = brightness;
-       schedule_work(&data->work);
-}
-
-/* HP-specific accelerometer driver ------------------------------------ */
-
-/* For automatic insertion of the module */
-static struct acpi_device_id lis3lv02d_device_ids[] = {
-       {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
-
-
-/**
- * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
- * @lis3: pointer to the device struct
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
-{
-       struct acpi_device *dev = lis3->bus_priv;
-       if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
-                                NULL, NULL) != AE_OK)
-               return -EINVAL;
-
-       return 0;
-}
-
-/**
- * lis3lv02d_acpi_read - ACPI ALRD method: read a register
- * @lis3: pointer to the device struct
- * @reg:    the register to read
- * @ret:    result of the operation
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
-{
-       struct acpi_device *dev = lis3->bus_priv;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list args = { 1, &arg0 };
-       unsigned long long lret;
-       acpi_status status;
-
-       arg0.integer.value = reg;
-
-       status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
-       *ret = lret;
-       return (status != AE_OK) ? -EINVAL : 0;
-}
-
-/**
- * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
- * @lis3: pointer to the device struct
- * @reg:    the register to write to
- * @val:    the value to write
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-       struct acpi_device *dev = lis3->bus_priv;
-       unsigned long long ret; /* Not used when writting */
-       union acpi_object in_obj[2];
-       struct acpi_object_list args = { 2, in_obj };
-
-       in_obj[0].type          = ACPI_TYPE_INTEGER;
-       in_obj[0].integer.value = reg;
-       in_obj[1].type          = ACPI_TYPE_INTEGER;
-       in_obj[1].integer.value = val;
-
-       if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
-{
-       lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
-       pr_info("hardware type %s found\n", dmi->ident);
-
-       return 1;
-}
-
-/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
- * If the value is negative, the opposite of the hw value is used. */
-#define DEFINE_CONV(name, x, y, z)                           \
-       static union axis_conversion lis3lv02d_axis_##name = \
-               { .as_array = { x, y, z } }
-DEFINE_CONV(normal, 1, 2, 3);
-DEFINE_CONV(y_inverted, 1, -2, 3);
-DEFINE_CONV(x_inverted, -1, 2, 3);
-DEFINE_CONV(z_inverted, 1, 2, -3);
-DEFINE_CONV(xy_swap, 2, 1, 3);
-DEFINE_CONV(xy_rotated_left, -2, 1, 3);
-DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
-DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
-DEFINE_CONV(xy_rotated_right, 2, -1, 3);
-DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
-
-#define AXIS_DMI_MATCH(_ident, _name, _axis) {         \
-       .ident = _ident,                                \
-       .callback = lis3lv02d_dmi_matched,              \
-       .matches = {                                    \
-               DMI_MATCH(DMI_PRODUCT_NAME, _name)      \
-       },                                              \
-       .driver_data = &lis3lv02d_axis_##_axis          \
-}
-
-#define AXIS_DMI_MATCH2(_ident, _class1, _name1,       \
-                               _class2, _name2,        \
-                               _axis) {                \
-       .ident = _ident,                                \
-       .callback = lis3lv02d_dmi_matched,              \
-       .matches = {                                    \
-               DMI_MATCH(DMI_##_class1, _name1),       \
-               DMI_MATCH(DMI_##_class2, _name2),       \
-       },                                              \
-       .driver_data = &lis3lv02d_axis_##_axis          \
-}
-static struct dmi_system_id lis3lv02d_dmi_ids[] = {
-       /* product names are truncated to match all kinds of a same model */
-       AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
-       AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
-       AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
-       AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
-       AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
-       AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
-       AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
-       AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
-       AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
-       AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
-       AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
-       AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
-       AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
-       AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
-       AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
-       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
-       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
-       /* Intel-based HP Pavilion dv5 */
-       AXIS_DMI_MATCH2("HPDV5_I",
-                       PRODUCT_NAME, "HP Pavilion dv5",
-                       BOARD_NAME, "3603",
-                       x_inverted),
-       /* AMD-based HP Pavilion dv5 */
-       AXIS_DMI_MATCH2("HPDV5_A",
-                       PRODUCT_NAME, "HP Pavilion dv5",
-                       BOARD_NAME, "3600",
-                       y_inverted),
-       AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
-       AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
-       AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
-       AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
-       AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
-       AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
-       AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
-       AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-       AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
-       { NULL, }
-/* Laptop models without axis info (yet):
- * "NC6910" "HP Compaq 6910"
- * "NC2400" "HP Compaq nc2400"
- * "NX74x0" "HP Compaq nx74"
- * "NX6325" "HP Compaq nx6325"
- * "NC4400" "HP Compaq nc4400"
- */
-};
-
-static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
-{
-       struct acpi_device *dev = lis3_dev.bus_priv;
-       unsigned long long ret; /* Not used when writing */
-       union acpi_object in_obj[1];
-       struct acpi_object_list args = { 1, in_obj };
-
-       in_obj[0].type          = ACPI_TYPE_INTEGER;
-       in_obj[0].integer.value = !!value;
-
-       acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
-}
-
-static struct delayed_led_classdev hpled_led = {
-       .led_classdev = {
-               .name                   = "hp::hddprotect",
-               .default_trigger        = "none",
-               .brightness_set         = delayed_sysfs_set,
-               .flags                  = LED_CORE_SUSPENDRESUME,
-       },
-       .set_brightness = hpled_set,
-};
-
-static acpi_status
-lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
-{
-       if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
-               struct acpi_resource_extended_irq *irq;
-               u32 *device_irq = context;
-
-               irq = &resource->data.extended_irq;
-               *device_irq = irq->interrupts[0];
-       }
-
-       return AE_OK;
-}
-
-static void lis3lv02d_enum_resources(struct acpi_device *device)
-{
-       acpi_status status;
-
-       status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-                                       lis3lv02d_get_resource, &lis3_dev.irq);
-       if (ACPI_FAILURE(status))
-               printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
-}
-
-static int lis3lv02d_add(struct acpi_device *device)
-{
-       int ret;
-
-       if (!device)
-               return -EINVAL;
-
-       lis3_dev.bus_priv = device;
-       lis3_dev.init = lis3lv02d_acpi_init;
-       lis3_dev.read = lis3lv02d_acpi_read;
-       lis3_dev.write = lis3lv02d_acpi_write;
-       strcpy(acpi_device_name(device), DRIVER_NAME);
-       strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
-       device->driver_data = &lis3_dev;
-
-       /* obtain IRQ number of our device from ACPI */
-       lis3lv02d_enum_resources(device);
-
-       /* If possible use a "standard" axes order */
-       if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
-               pr_info("Using custom axes %d,%d,%d\n",
-                       lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
-       } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
-               pr_info("laptop model unknown, using default axes configuration\n");
-               lis3_dev.ac = lis3lv02d_axis_normal;
-       }
-
-       /* call the core layer do its init */
-       ret = lis3lv02d_init_device(&lis3_dev);
-       if (ret)
-               return ret;
-
-       INIT_WORK(&hpled_led.work, delayed_set_status_worker);
-       ret = led_classdev_register(NULL, &hpled_led.led_classdev);
-       if (ret) {
-               lis3lv02d_joystick_disable();
-               lis3lv02d_poweroff(&lis3_dev);
-               flush_work(&hpled_led.work);
-               return ret;
-       }
-
-       return ret;
-}
-
-static int lis3lv02d_remove(struct acpi_device *device, int type)
-{
-       if (!device)
-               return -EINVAL;
-
-       lis3lv02d_joystick_disable();
-       lis3lv02d_poweroff(&lis3_dev);
-
-       led_classdev_unregister(&hpled_led.led_classdev);
-       flush_work(&hpled_led.work);
-
-       return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-
-#ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
-{
-       /* make sure the device is off when we suspend */
-       lis3lv02d_poweroff(&lis3_dev);
-       return 0;
-}
-
-static int lis3lv02d_resume(struct acpi_device *device)
-{
-       lis3lv02d_poweron(&lis3_dev);
-       return 0;
-}
-#else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
-#endif
-
-/* For the HP MDPS aka 3D Driveguard */
-static struct acpi_driver lis3lv02d_driver = {
-       .name  = DRIVER_NAME,
-       .class = ACPI_MDPS_CLASS,
-       .ids   = lis3lv02d_device_ids,
-       .ops = {
-               .add     = lis3lv02d_add,
-               .remove  = lis3lv02d_remove,
-               .suspend = lis3lv02d_suspend,
-               .resume  = lis3lv02d_resume,
-       }
-};
-
-static int __init lis3lv02d_init_module(void)
-{
-       int ret;
-
-       if (acpi_disabled)
-               return -ENODEV;
-
-       ret = acpi_bus_register_driver(&lis3lv02d_driver);
-       if (ret < 0)
-               return ret;
-
-       pr_info("driver loaded\n");
-
-       return 0;
-}
-
-static void __exit lis3lv02d_exit_module(void)
-{
-       acpi_bus_unregister_driver(&lis3lv02d_driver);
-}
-
-MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init_module);
-module_exit(lis3lv02d_exit_module);
-
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
deleted file mode 100644 (file)
index d805e8e..0000000
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
- *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  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/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/input-polldev.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/pm_runtime.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-
-/* joystick device poll interval in milliseconds */
-#define MDPS_POLL_INTERVAL 50
-#define MDPS_POLL_MIN     0
-#define MDPS_POLL_MAX     2000
-
-#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
-
-#define SELFTEST_OK           0
-#define SELFTEST_FAIL         -1
-#define SELFTEST_IRQ          -2
-
-#define IRQ_LINE0             0
-#define IRQ_LINE1             1
-
-/*
- * The sensor can also generate interrupts (DRDY) but it's pretty pointless
- * because they are generated even if the data do not change. So it's better
- * to keep the interrupt for the free-fall event. The values are updated at
- * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
- * some low processor, we poll the sensor only at 20Hz... enough for the
- * joystick.
- */
-
-#define LIS3_PWRON_DELAY_WAI_12B       (5000)
-#define LIS3_PWRON_DELAY_WAI_8B                (3000)
-
-/*
- * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
- * LIS302D spec says: 18 mG / digit
- * LIS3_ACCURACY is used to increase accuracy of the intermediate
- * calculation results.
- */
-#define LIS3_ACCURACY                  1024
-/* Sensitivity values for -2G +2G scale */
-#define LIS3_SENSITIVITY_12B           ((LIS3_ACCURACY * 1000) / 1024)
-#define LIS3_SENSITIVITY_8B            (18 * LIS3_ACCURACY)
-
-#define LIS3_DEFAULT_FUZZ_12B          3
-#define LIS3_DEFAULT_FLAT_12B          3
-#define LIS3_DEFAULT_FUZZ_8B           1
-#define LIS3_DEFAULT_FLAT_8B           1
-
-struct lis3lv02d lis3_dev = {
-       .misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
-};
-
-EXPORT_SYMBOL_GPL(lis3_dev);
-
-/* just like param_set_int() but does sanity-check so that it won't point
- * over the axis array size
- */
-static int param_set_axis(const char *val, const struct kernel_param *kp)
-{
-       int ret = param_set_int(val, kp);
-       if (!ret) {
-               int val = *(int *)kp->arg;
-               if (val < 0)
-                       val = -val;
-               if (!val || val > 3)
-                       return -EINVAL;
-       }
-       return ret;
-}
-
-static struct kernel_param_ops param_ops_axis = {
-       .set = param_set_axis,
-       .get = param_get_int,
-};
-
-module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
-MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
-
-static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
-{
-       s8 lo;
-       if (lis3->read(lis3, reg, &lo) < 0)
-               return 0;
-
-       return lo;
-}
-
-static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
-{
-       u8 lo, hi;
-
-       lis3->read(lis3, reg - 1, &lo);
-       lis3->read(lis3, reg, &hi);
-       /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
-       return (s16)((hi << 8) | lo);
-}
-
-/**
- * lis3lv02d_get_axis - For the given axis, give the value converted
- * @axis:      1,2,3 - can also be negative
- * @hw_values: raw values returned by the hardware
- *
- * Returns the converted value.
- */
-static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
-{
-       if (axis > 0)
-               return hw_values[axis - 1];
-       else
-               return -hw_values[-axis - 1];
-}
-
-/**
- * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
- * @lis3: pointer to the device struct
- * @x:    where to store the X axis value
- * @y:    where to store the Y axis value
- * @z:    where to store the Z axis value
- *
- * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
- */
-static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
-{
-       int position[3];
-       int i;
-
-       if (lis3->blkread) {
-               if (lis3_dev.whoami == WAI_12B) {
-                       u16 data[3];
-                       lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
-                       for (i = 0; i < 3; i++)
-                               position[i] = (s16)le16_to_cpu(data[i]);
-               } else {
-                       u8 data[5];
-                       /* Data: x, dummy, y, dummy, z */
-                       lis3->blkread(lis3, OUTX, 5, data);
-                       for (i = 0; i < 3; i++)
-                               position[i] = (s8)data[i * 2];
-               }
-       } else {
-               position[0] = lis3->read_data(lis3, OUTX);
-               position[1] = lis3->read_data(lis3, OUTY);
-               position[2] = lis3->read_data(lis3, OUTZ);
-       }
-
-       for (i = 0; i < 3; i++)
-               position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
-
-       *x = lis3lv02d_get_axis(lis3->ac.x, position);
-       *y = lis3lv02d_get_axis(lis3->ac.y, position);
-       *z = lis3lv02d_get_axis(lis3->ac.z, position);
-}
-
-/* conversion btw sampling rate and the register values */
-static int lis3_12_rates[4] = {40, 160, 640, 2560};
-static int lis3_8_rates[2] = {100, 400};
-static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
-
-/* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(void)
-{
-       u8 ctrl;
-       int shift;
-
-       lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-       ctrl &= lis3_dev.odr_mask;
-       shift = ffs(lis3_dev.odr_mask) - 1;
-       return lis3_dev.odrs[(ctrl >> shift)];
-}
-
-static int lis3lv02d_set_odr(int rate)
-{
-       u8 ctrl;
-       int i, len, shift;
-
-       if (!rate)
-               return -EINVAL;
-
-       lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-       ctrl &= ~lis3_dev.odr_mask;
-       len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
-       shift = ffs(lis3_dev.odr_mask) - 1;
-
-       for (i = 0; i < len; i++)
-               if (lis3_dev.odrs[i] == rate) {
-                       lis3_dev.write(&lis3_dev, CTRL_REG1,
-                                       ctrl | (i << shift));
-                       return 0;
-               }
-       return -EINVAL;
-}
-
-static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
-{
-       u8 ctlreg, reg;
-       s16 x, y, z;
-       u8 selftest;
-       int ret;
-       u8 ctrl_reg_data;
-       unsigned char irq_cfg;
-
-       mutex_lock(&lis3->mutex);
-
-       irq_cfg = lis3->irq_cfg;
-       if (lis3_dev.whoami == WAI_8B) {
-               lis3->data_ready_count[IRQ_LINE0] = 0;
-               lis3->data_ready_count[IRQ_LINE1] = 0;
-
-               /* Change interrupt cfg to data ready for selftest */
-               atomic_inc(&lis3_dev.wake_thread);
-               lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
-               lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
-               lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
-                               ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
-                               (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
-       }
-
-       if (lis3_dev.whoami == WAI_3DC) {
-               ctlreg = CTRL_REG4;
-               selftest = CTRL4_ST0;
-       } else {
-               ctlreg = CTRL_REG1;
-               if (lis3_dev.whoami == WAI_12B)
-                       selftest = CTRL1_ST;
-               else
-                       selftest = CTRL1_STP;
-       }
-
-       lis3->read(lis3, ctlreg, &reg);
-       lis3->write(lis3, ctlreg, (reg | selftest));
-       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-       /* Read directly to avoid axis remap */
-       x = lis3->read_data(lis3, OUTX);
-       y = lis3->read_data(lis3, OUTY);
-       z = lis3->read_data(lis3, OUTZ);
-
-       /* back to normal settings */
-       lis3->write(lis3, ctlreg, reg);
-       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-       results[0] = x - lis3->read_data(lis3, OUTX);
-       results[1] = y - lis3->read_data(lis3, OUTY);
-       results[2] = z - lis3->read_data(lis3, OUTZ);
-
-       ret = 0;
-
-       if (lis3_dev.whoami == WAI_8B) {
-               /* Restore original interrupt configuration */
-               atomic_dec(&lis3_dev.wake_thread);
-               lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
-               lis3->irq_cfg = irq_cfg;
-
-               if ((irq_cfg & LIS3_IRQ1_MASK) &&
-                       lis3->data_ready_count[IRQ_LINE0] < 2) {
-                       ret = SELFTEST_IRQ;
-                       goto fail;
-               }
-
-               if ((irq_cfg & LIS3_IRQ2_MASK) &&
-                       lis3->data_ready_count[IRQ_LINE1] < 2) {
-                       ret = SELFTEST_IRQ;
-                       goto fail;
-               }
-       }
-
-       if (lis3->pdata) {
-               int i;
-               for (i = 0; i < 3; i++) {
-                       /* Check against selftest acceptance limits */
-                       if ((results[i] < lis3->pdata->st_min_limits[i]) ||
-                           (results[i] > lis3->pdata->st_max_limits[i])) {
-                               ret = SELFTEST_FAIL;
-                               goto fail;
-                       }
-               }
-       }
-
-       /* test passed */
-fail:
-       mutex_unlock(&lis3->mutex);
-       return ret;
-}
-
-/*
- * Order of registers in the list affects to order of the restore process.
- * Perhaps it is a good idea to set interrupt enable register as a last one
- * after all other configurations
- */
-static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
-                              FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
-                              CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
-                              CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
-                              CTRL_REG1, CTRL_REG2, CTRL_REG3};
-
-static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
-                              FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
-                              DD_THSE_L, DD_THSE_H,
-                              CTRL_REG1, CTRL_REG3, CTRL_REG2};
-
-static inline void lis3_context_save(struct lis3lv02d *lis3)
-{
-       int i;
-       for (i = 0; i < lis3->regs_size; i++)
-               lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
-       lis3->regs_stored = true;
-}
-
-static inline void lis3_context_restore(struct lis3lv02d *lis3)
-{
-       int i;
-       if (lis3->regs_stored)
-               for (i = 0; i < lis3->regs_size; i++)
-                       lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
-}
-
-void lis3lv02d_poweroff(struct lis3lv02d *lis3)
-{
-       if (lis3->reg_ctrl)
-               lis3_context_save(lis3);
-       /* disable X,Y,Z axis and power down */
-       lis3->write(lis3, CTRL_REG1, 0x00);
-       if (lis3->reg_ctrl)
-               lis3->reg_ctrl(lis3, LIS3_REG_OFF);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
-{
-       u8 reg;
-
-       lis3->init(lis3);
-
-       /*
-        * Common configuration
-        * BDU: (12 bits sensors only) LSB and MSB values are not updated until
-        *      both have been read. So the value read will always be correct.
-        * Set BOOT bit to refresh factory tuning values.
-        */
-       lis3->read(lis3, CTRL_REG2, &reg);
-       if (lis3->whoami ==  WAI_12B)
-               reg |= CTRL2_BDU | CTRL2_BOOT;
-       else
-               reg |= CTRL2_BOOT_8B;
-       lis3->write(lis3, CTRL_REG2, reg);
-
-       /* LIS3 power on delay is quite long */
-       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-       if (lis3->reg_ctrl)
-               lis3_context_restore(lis3);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
-
-
-static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
-{
-       int x, y, z;
-
-       mutex_lock(&lis3_dev.mutex);
-       lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-       input_report_abs(pidev->input, ABS_X, x);
-       input_report_abs(pidev->input, ABS_Y, y);
-       input_report_abs(pidev->input, ABS_Z, z);
-       input_sync(pidev->input);
-       mutex_unlock(&lis3_dev.mutex);
-}
-
-static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
-{
-       if (lis3_dev.pm_dev)
-               pm_runtime_get_sync(lis3_dev.pm_dev);
-
-       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
-               atomic_set(&lis3_dev.wake_thread, 1);
-       /*
-        * Update coordinates for the case where poll interval is 0 and
-        * the chip in running purely under interrupt control
-        */
-       lis3lv02d_joystick_poll(pidev);
-}
-
-static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
-{
-       atomic_set(&lis3_dev.wake_thread, 0);
-       if (lis3_dev.pm_dev)
-               pm_runtime_put(lis3_dev.pm_dev);
-}
-
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
-{
-       if (!test_bit(0, &lis3_dev.misc_opened))
-               goto out;
-
-       /*
-        * Be careful: on some HP laptops the bios force DD when on battery and
-        * the lid is closed. This leads to interrupts as soon as a little move
-        * is done.
-        */
-       atomic_inc(&lis3_dev.count);
-
-       wake_up_interruptible(&lis3_dev.misc_wait);
-       kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
-out:
-       if (atomic_read(&lis3_dev.wake_thread))
-               return IRQ_WAKE_THREAD;
-       return IRQ_HANDLED;
-}
-
-static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
-{
-       struct input_dev *dev = lis3->idev->input;
-       u8 click_src;
-
-       mutex_lock(&lis3->mutex);
-       lis3->read(lis3, CLICK_SRC, &click_src);
-
-       if (click_src & CLICK_SINGLE_X) {
-               input_report_key(dev, lis3->mapped_btns[0], 1);
-               input_report_key(dev, lis3->mapped_btns[0], 0);
-       }
-
-       if (click_src & CLICK_SINGLE_Y) {
-               input_report_key(dev, lis3->mapped_btns[1], 1);
-               input_report_key(dev, lis3->mapped_btns[1], 0);
-       }
-
-       if (click_src & CLICK_SINGLE_Z) {
-               input_report_key(dev, lis3->mapped_btns[2], 1);
-               input_report_key(dev, lis3->mapped_btns[2], 0);
-       }
-       input_sync(dev);
-       mutex_unlock(&lis3->mutex);
-}
-
-static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
-{
-       int dummy;
-
-       /* Dummy read to ack interrupt */
-       lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
-       lis3->data_ready_count[index]++;
-}
-
-static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
-{
-       struct lis3lv02d *lis3 = data;
-       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
-
-       if (irq_cfg == LIS3_IRQ1_CLICK)
-               lis302dl_interrupt_handle_click(lis3);
-       else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
-               lis302dl_data_ready(lis3, IRQ_LINE0);
-       else
-               lis3lv02d_joystick_poll(lis3->idev);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
-{
-       struct lis3lv02d *lis3 = data;
-       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
-
-       if (irq_cfg == LIS3_IRQ2_CLICK)
-               lis302dl_interrupt_handle_click(lis3);
-       else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
-               lis302dl_data_ready(lis3, IRQ_LINE1);
-       else
-               lis3lv02d_joystick_poll(lis3->idev);
-
-       return IRQ_HANDLED;
-}
-
-static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &lis3_dev.misc_opened))
-               return -EBUSY; /* already open */
-
-       if (lis3_dev.pm_dev)
-               pm_runtime_get_sync(lis3_dev.pm_dev);
-
-       atomic_set(&lis3_dev.count, 0);
-       return 0;
-}
-
-static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
-{
-       fasync_helper(-1, file, 0, &lis3_dev.async_queue);
-       clear_bit(0, &lis3_dev.misc_opened); /* release the device */
-       if (lis3_dev.pm_dev)
-               pm_runtime_put(lis3_dev.pm_dev);
-       return 0;
-}
-
-static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
-                               size_t count, loff_t *pos)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       u32 data;
-       unsigned char byte_data;
-       ssize_t retval = 1;
-
-       if (count < 1)
-               return -EINVAL;
-
-       add_wait_queue(&lis3_dev.misc_wait, &wait);
-       while (true) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               data = atomic_xchg(&lis3_dev.count, 0);
-               if (data)
-                       break;
-
-               if (file->f_flags & O_NONBLOCK) {
-                       retval = -EAGAIN;
-                       goto out;
-               }
-
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       goto out;
-               }
-
-               schedule();
-       }
-
-       if (data < 255)
-               byte_data = data;
-       else
-               byte_data = 255;
-
-       /* make sure we are not going into copy_to_user() with
-        * TASK_INTERRUPTIBLE state */
-       set_current_state(TASK_RUNNING);
-       if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
-               retval = -EFAULT;
-
-out:
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&lis3_dev.misc_wait, &wait);
-
-       return retval;
-}
-
-static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
-{
-       poll_wait(file, &lis3_dev.misc_wait, wait);
-       if (atomic_read(&lis3_dev.count))
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
-{
-       return fasync_helper(fd, file, on, &lis3_dev.async_queue);
-}
-
-static const struct file_operations lis3lv02d_misc_fops = {
-       .owner   = THIS_MODULE,
-       .llseek  = no_llseek,
-       .read    = lis3lv02d_misc_read,
-       .open    = lis3lv02d_misc_open,
-       .release = lis3lv02d_misc_release,
-       .poll    = lis3lv02d_misc_poll,
-       .fasync  = lis3lv02d_misc_fasync,
-};
-
-static struct miscdevice lis3lv02d_misc_device = {
-       .minor   = MISC_DYNAMIC_MINOR,
-       .name    = "freefall",
-       .fops    = &lis3lv02d_misc_fops,
-};
-
-int lis3lv02d_joystick_enable(void)
-{
-       struct input_dev *input_dev;
-       int err;
-       int max_val, fuzz, flat;
-       int btns[] = {BTN_X, BTN_Y, BTN_Z};
-
-       if (lis3_dev.idev)
-               return -EINVAL;
-
-       lis3_dev.idev = input_allocate_polled_device();
-       if (!lis3_dev.idev)
-               return -ENOMEM;
-
-       lis3_dev.idev->poll = lis3lv02d_joystick_poll;
-       lis3_dev.idev->open = lis3lv02d_joystick_open;
-       lis3_dev.idev->close = lis3lv02d_joystick_close;
-       lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
-       lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
-       lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
-       input_dev = lis3_dev.idev->input;
-
-       input_dev->name       = "ST LIS3LV02DL Accelerometer";
-       input_dev->phys       = DRIVER_NAME "/input0";
-       input_dev->id.bustype = BUS_HOST;
-       input_dev->id.vendor  = 0;
-       input_dev->dev.parent = &lis3_dev.pdev->dev;
-
-       set_bit(EV_ABS, input_dev->evbit);
-       max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-       if (lis3_dev.whoami == WAI_12B) {
-               fuzz = LIS3_DEFAULT_FUZZ_12B;
-               flat = LIS3_DEFAULT_FLAT_12B;
-       } else {
-               fuzz = LIS3_DEFAULT_FUZZ_8B;
-               flat = LIS3_DEFAULT_FLAT_8B;
-       }
-       fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
-       flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
-
-       input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
-       input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
-       input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
-
-       lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
-       lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
-       lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
-
-       err = input_register_polled_device(lis3_dev.idev);
-       if (err) {
-               input_free_polled_device(lis3_dev.idev);
-               lis3_dev.idev = NULL;
-       }
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-
-void lis3lv02d_joystick_disable(void)
-{
-       if (lis3_dev.irq)
-               free_irq(lis3_dev.irq, &lis3_dev);
-       if (lis3_dev.pdata && lis3_dev.pdata->irq2)
-               free_irq(lis3_dev.pdata->irq2, &lis3_dev);
-
-       if (!lis3_dev.idev)
-               return;
-
-       if (lis3_dev.irq)
-               misc_deregister(&lis3lv02d_misc_device);
-       input_unregister_polled_device(lis3_dev.idev);
-       input_free_polled_device(lis3_dev.idev);
-       lis3_dev.idev = NULL;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
-
-/* Sysfs stuff */
-static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
-{
-       /*
-        * SYSFS functions are fast visitors so put-call
-        * immediately after the get-call. However, keep
-        * chip running for a while and schedule delayed
-        * suspend. This way periodic sysfs calls doesn't
-        * suffer from relatively long power up time.
-        */
-
-       if (lis3->pm_dev) {
-               pm_runtime_get_sync(lis3->pm_dev);
-               pm_runtime_put_noidle(lis3->pm_dev);
-               pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
-       }
-}
-
-static ssize_t lis3lv02d_selftest_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       s16 values[3];
-
-       static const char ok[] = "OK";
-       static const char fail[] = "FAIL";
-       static const char irq[] = "FAIL_IRQ";
-       const char *res;
-
-       lis3lv02d_sysfs_poweron(&lis3_dev);
-       switch (lis3lv02d_selftest(&lis3_dev, values)) {
-       case SELFTEST_FAIL:
-               res = fail;
-               break;
-       case SELFTEST_IRQ:
-               res = irq;
-               break;
-       case SELFTEST_OK:
-       default:
-               res = ok;
-               break;
-       }
-       return sprintf(buf, "%s %d %d %d\n", res,
-               values[0], values[1], values[2]);
-}
-
-static ssize_t lis3lv02d_position_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       int x, y, z;
-
-       lis3lv02d_sysfs_poweron(&lis3_dev);
-       mutex_lock(&lis3_dev.mutex);
-       lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-       mutex_unlock(&lis3_dev.mutex);
-       return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
-}
-
-static ssize_t lis3lv02d_rate_show(struct device *dev,
-                       struct device_attribute *attr, char *buf)
-{
-       lis3lv02d_sysfs_poweron(&lis3_dev);
-       return sprintf(buf, "%d\n", lis3lv02d_get_odr());
-}
-
-static ssize_t lis3lv02d_rate_set(struct device *dev,
-                               struct device_attribute *attr, const char *buf,
-                               size_t count)
-{
-       unsigned long rate;
-
-       if (strict_strtoul(buf, 0, &rate))
-               return -EINVAL;
-
-       lis3lv02d_sysfs_poweron(&lis3_dev);
-       if (lis3lv02d_set_odr(rate))
-               return -EINVAL;
-
-       return count;
-}
-
-static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
-static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
-static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
-                                           lis3lv02d_rate_set);
-
-static struct attribute *lis3lv02d_attributes[] = {
-       &dev_attr_selftest.attr,
-       &dev_attr_position.attr,
-       &dev_attr_rate.attr,
-       NULL
-};
-
-static struct attribute_group lis3lv02d_attribute_group = {
-       .attrs = lis3lv02d_attributes
-};
-
-
-static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
-{
-       lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-       if (IS_ERR(lis3->pdev))
-               return PTR_ERR(lis3->pdev);
-
-       return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
-}
-
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
-{
-       sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
-       platform_device_unregister(lis3->pdev);
-       if (lis3->pm_dev) {
-               /* Barrier after the sysfs remove */
-               pm_runtime_barrier(lis3->pm_dev);
-
-               /* SYSFS may have left chip running. Turn off if necessary */
-               if (!pm_runtime_suspended(lis3->pm_dev))
-                       lis3lv02d_poweroff(&lis3_dev);
-
-               pm_runtime_disable(lis3->pm_dev);
-               pm_runtime_set_suspended(lis3->pm_dev);
-       }
-       kfree(lis3->reg_cache);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
-
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
-                               struct lis3lv02d_platform_data *p)
-{
-       int err;
-       int ctrl2 = p->hipass_ctrl;
-
-       if (p->click_flags) {
-               dev->write(dev, CLICK_CFG, p->click_flags);
-               dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
-               dev->write(dev, CLICK_LATENCY, p->click_latency);
-               dev->write(dev, CLICK_WINDOW, p->click_window);
-               dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
-               dev->write(dev, CLICK_THSY_X,
-                       (p->click_thresh_x & 0xf) |
-                       (p->click_thresh_y << 4));
-
-               if (dev->idev) {
-                       struct input_dev *input_dev = lis3_dev.idev->input;
-                       input_set_capability(input_dev, EV_KEY, BTN_X);
-                       input_set_capability(input_dev, EV_KEY, BTN_Y);
-                       input_set_capability(input_dev, EV_KEY, BTN_Z);
-               }
-       }
-
-       if (p->wakeup_flags) {
-               dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
-               dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-               /* pdata value + 1 to keep this backward compatible*/
-               dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
-               ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
-       }
-
-       if (p->wakeup_flags2) {
-               dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
-               dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-               /* pdata value + 1 to keep this backward compatible*/
-               dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
-               ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
-       }
-       /* Configure hipass filters */
-       dev->write(dev, CTRL_REG2, ctrl2);
-
-       if (p->irq2) {
-               err = request_threaded_irq(p->irq2,
-                                       NULL,
-                                       lis302dl_interrupt_thread2_8b,
-                                       IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-                                       (p->irq_flags2 & IRQF_TRIGGER_MASK),
-                                       DRIVER_NAME, &lis3_dev);
-               if (err < 0)
-                       pr_err("No second IRQ. Limited functionality\n");
-       }
-}
-
-/*
- * Initialise the accelerometer and the various subsystems.
- * Should be rather independent of the bus system.
- */
-int lis3lv02d_init_device(struct lis3lv02d *dev)
-{
-       int err;
-       irq_handler_t thread_fn;
-       int irq_flags = 0;
-
-       dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
-
-       switch (dev->whoami) {
-       case WAI_12B:
-               pr_info("12 bits sensor found\n");
-               dev->read_data = lis3lv02d_read_12;
-               dev->mdps_max_val = 2048;
-               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
-               dev->odrs = lis3_12_rates;
-               dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
-               dev->scale = LIS3_SENSITIVITY_12B;
-               dev->regs = lis3_wai12_regs;
-               dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
-               break;
-       case WAI_8B:
-               pr_info("8 bits sensor found\n");
-               dev->read_data = lis3lv02d_read_8;
-               dev->mdps_max_val = 128;
-               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-               dev->odrs = lis3_8_rates;
-               dev->odr_mask = CTRL1_DR;
-               dev->scale = LIS3_SENSITIVITY_8B;
-               dev->regs = lis3_wai8_regs;
-               dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
-               break;
-       case WAI_3DC:
-               pr_info("8 bits 3DC sensor found\n");
-               dev->read_data = lis3lv02d_read_8;
-               dev->mdps_max_val = 128;
-               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-               dev->odrs = lis3_3dc_rates;
-               dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
-               dev->scale = LIS3_SENSITIVITY_8B;
-               break;
-       default:
-               pr_err("unknown sensor type 0x%X\n", dev->whoami);
-               return -EINVAL;
-       }
-
-       dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
-                                    sizeof(lis3_wai12_regs)), GFP_KERNEL);
-
-       if (dev->reg_cache == NULL) {
-               printk(KERN_ERR DRIVER_NAME "out of memory\n");
-               return -ENOMEM;
-       }
-
-       mutex_init(&dev->mutex);
-       atomic_set(&dev->wake_thread, 0);
-
-       lis3lv02d_add_fs(dev);
-       lis3lv02d_poweron(dev);
-
-       if (dev->pm_dev) {
-               pm_runtime_set_active(dev->pm_dev);
-               pm_runtime_enable(dev->pm_dev);
-       }
-
-       if (lis3lv02d_joystick_enable())
-               pr_err("joystick initialization failed\n");
-
-       /* passing in platform specific data is purely optional and only
-        * used by the SPI transport layer at the moment */
-       if (dev->pdata) {
-               struct lis3lv02d_platform_data *p = dev->pdata;
-
-               if (dev->whoami == WAI_8B)
-                       lis3lv02d_8b_configure(dev, p);
-
-               irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
-
-               dev->irq_cfg = p->irq_cfg;
-               if (p->irq_cfg)
-                       dev->write(dev, CTRL_REG3, p->irq_cfg);
-
-               if (p->default_rate)
-                       lis3lv02d_set_odr(p->default_rate);
-       }
-
-       /* bail if we did not get an IRQ from the bus layer */
-       if (!dev->irq) {
-               pr_debug("No IRQ. Disabling /dev/freefall\n");
-               goto out;
-       }
-
-       /*
-        * The sensor can generate interrupts for free-fall and direction
-        * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
-        * the things simple and _fast_ we activate it only for free-fall, so
-        * no need to read register (very slow with ACPI). For the same reason,
-        * we forbid shared interrupts.
-        *
-        * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
-        * io-apic is not configurable (and generates a warning) but I keep it
-        * in case of support for other hardware.
-        */
-       if (dev->pdata && dev->whoami == WAI_8B)
-               thread_fn = lis302dl_interrupt_thread1_8b;
-       else
-               thread_fn = NULL;
-
-       err = request_threaded_irq(dev->irq, lis302dl_interrupt,
-                               thread_fn,
-                               IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-                               irq_flags,
-                               DRIVER_NAME, &lis3_dev);
-
-       if (err < 0) {
-               pr_err("Cannot get IRQ\n");
-               goto out;
-       }
-
-       if (misc_register(&lis3lv02d_misc_device))
-               pr_err("misc_register failed\n");
-out:
-       return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
-
-MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
deleted file mode 100644 (file)
index a193958..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008-2009 Eric Piel
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/platform_device.h>
-#include <linux/input-polldev.h>
-#include <linux/regulator/consumer.h>
-
-/*
- * This driver tries to support the "digital" accelerometer chips from
- * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
- * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
- * almost the same registers. In addition to differing on physical properties,
- * they differ on the number of axes (2/3), precision (8/12 bits), and special
- * features (freefall detection, click...). Unfortunately, not all the
- * differences can be probed via a register.
- * They can be connected either via IĀ²C or SPI.
- */
-
-#include <linux/lis3lv02d.h>
-
-enum lis3_reg {
-       WHO_AM_I        = 0x0F,
-       OFFSET_X        = 0x16,
-       OFFSET_Y        = 0x17,
-       OFFSET_Z        = 0x18,
-       GAIN_X          = 0x19,
-       GAIN_Y          = 0x1A,
-       GAIN_Z          = 0x1B,
-       CTRL_REG1       = 0x20,
-       CTRL_REG2       = 0x21,
-       CTRL_REG3       = 0x22,
-       CTRL_REG4       = 0x23,
-       HP_FILTER_RESET = 0x23,
-       STATUS_REG      = 0x27,
-       OUTX_L          = 0x28,
-       OUTX_H          = 0x29,
-       OUTX            = 0x29,
-       OUTY_L          = 0x2A,
-       OUTY_H          = 0x2B,
-       OUTY            = 0x2B,
-       OUTZ_L          = 0x2C,
-       OUTZ_H          = 0x2D,
-       OUTZ            = 0x2D,
-};
-
-enum lis302d_reg {
-       FF_WU_CFG_1     = 0x30,
-       FF_WU_SRC_1     = 0x31,
-       FF_WU_THS_1     = 0x32,
-       FF_WU_DURATION_1 = 0x33,
-       FF_WU_CFG_2     = 0x34,
-       FF_WU_SRC_2     = 0x35,
-       FF_WU_THS_2     = 0x36,
-       FF_WU_DURATION_2 = 0x37,
-       CLICK_CFG       = 0x38,
-       CLICK_SRC       = 0x39,
-       CLICK_THSY_X    = 0x3B,
-       CLICK_THSZ      = 0x3C,
-       CLICK_TIMELIMIT = 0x3D,
-       CLICK_LATENCY   = 0x3E,
-       CLICK_WINDOW    = 0x3F,
-};
-
-enum lis3lv02d_reg {
-       FF_WU_CFG       = 0x30,
-       FF_WU_SRC       = 0x31,
-       FF_WU_ACK       = 0x32,
-       FF_WU_THS_L     = 0x34,
-       FF_WU_THS_H     = 0x35,
-       FF_WU_DURATION  = 0x36,
-       DD_CFG          = 0x38,
-       DD_SRC          = 0x39,
-       DD_ACK          = 0x3A,
-       DD_THSI_L       = 0x3C,
-       DD_THSI_H       = 0x3D,
-       DD_THSE_L       = 0x3E,
-       DD_THSE_H       = 0x3F,
-};
-
-enum lis3_who_am_i {
-       WAI_3DC         = 0x33, /* 8 bits: LIS3DC, HP3DC */
-       WAI_12B         = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
-       WAI_8B          = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
-       WAI_6B          = 0x52, /* 6 bits: LIS331DLF - not supported */
-};
-
-enum lis3lv02d_ctrl1_12b {
-       CTRL1_Xen       = 0x01,
-       CTRL1_Yen       = 0x02,
-       CTRL1_Zen       = 0x04,
-       CTRL1_ST        = 0x08,
-       CTRL1_DF0       = 0x10,
-       CTRL1_DF1       = 0x20,
-       CTRL1_PD0       = 0x40,
-       CTRL1_PD1       = 0x80,
-};
-
-/* Delta to ctrl1_12b version */
-enum lis3lv02d_ctrl1_8b {
-       CTRL1_STM       = 0x08,
-       CTRL1_STP       = 0x10,
-       CTRL1_FS        = 0x20,
-       CTRL1_PD        = 0x40,
-       CTRL1_DR        = 0x80,
-};
-
-enum lis3lv02d_ctrl1_3dc {
-       CTRL1_ODR0      = 0x10,
-       CTRL1_ODR1      = 0x20,
-       CTRL1_ODR2      = 0x40,
-       CTRL1_ODR3      = 0x80,
-};
-
-enum lis3lv02d_ctrl2 {
-       CTRL2_DAS       = 0x01,
-       CTRL2_SIM       = 0x02,
-       CTRL2_DRDY      = 0x04,
-       CTRL2_IEN       = 0x08,
-       CTRL2_BOOT      = 0x10,
-       CTRL2_BLE       = 0x20,
-       CTRL2_BDU       = 0x40, /* Block Data Update */
-       CTRL2_FS        = 0x80, /* Full Scale selection */
-};
-
-enum lis3lv02d_ctrl4_3dc {
-       CTRL4_SIM       = 0x01,
-       CTRL4_ST0       = 0x02,
-       CTRL4_ST1       = 0x04,
-       CTRL4_FS0       = 0x10,
-       CTRL4_FS1       = 0x20,
-};
-
-enum lis302d_ctrl2 {
-       HP_FF_WU2       = 0x08,
-       HP_FF_WU1       = 0x04,
-       CTRL2_BOOT_8B   = 0x40,
-};
-
-enum lis3lv02d_ctrl3 {
-       CTRL3_CFS0      = 0x01,
-       CTRL3_CFS1      = 0x02,
-       CTRL3_FDS       = 0x10,
-       CTRL3_HPFF      = 0x20,
-       CTRL3_HPDD      = 0x40,
-       CTRL3_ECK       = 0x80,
-};
-
-enum lis3lv02d_status_reg {
-       STATUS_XDA      = 0x01,
-       STATUS_YDA      = 0x02,
-       STATUS_ZDA      = 0x04,
-       STATUS_XYZDA    = 0x08,
-       STATUS_XOR      = 0x10,
-       STATUS_YOR      = 0x20,
-       STATUS_ZOR      = 0x40,
-       STATUS_XYZOR    = 0x80,
-};
-
-enum lis3lv02d_ff_wu_cfg {
-       FF_WU_CFG_XLIE  = 0x01,
-       FF_WU_CFG_XHIE  = 0x02,
-       FF_WU_CFG_YLIE  = 0x04,
-       FF_WU_CFG_YHIE  = 0x08,
-       FF_WU_CFG_ZLIE  = 0x10,
-       FF_WU_CFG_ZHIE  = 0x20,
-       FF_WU_CFG_LIR   = 0x40,
-       FF_WU_CFG_AOI   = 0x80,
-};
-
-enum lis3lv02d_ff_wu_src {
-       FF_WU_SRC_XL    = 0x01,
-       FF_WU_SRC_XH    = 0x02,
-       FF_WU_SRC_YL    = 0x04,
-       FF_WU_SRC_YH    = 0x08,
-       FF_WU_SRC_ZL    = 0x10,
-       FF_WU_SRC_ZH    = 0x20,
-       FF_WU_SRC_IA    = 0x40,
-};
-
-enum lis3lv02d_dd_cfg {
-       DD_CFG_XLIE     = 0x01,
-       DD_CFG_XHIE     = 0x02,
-       DD_CFG_YLIE     = 0x04,
-       DD_CFG_YHIE     = 0x08,
-       DD_CFG_ZLIE     = 0x10,
-       DD_CFG_ZHIE     = 0x20,
-       DD_CFG_LIR      = 0x40,
-       DD_CFG_IEND     = 0x80,
-};
-
-enum lis3lv02d_dd_src {
-       DD_SRC_XL       = 0x01,
-       DD_SRC_XH       = 0x02,
-       DD_SRC_YL       = 0x04,
-       DD_SRC_YH       = 0x08,
-       DD_SRC_ZL       = 0x10,
-       DD_SRC_ZH       = 0x20,
-       DD_SRC_IA       = 0x40,
-};
-
-enum lis3lv02d_click_src_8b {
-       CLICK_SINGLE_X  = 0x01,
-       CLICK_DOUBLE_X  = 0x02,
-       CLICK_SINGLE_Y  = 0x04,
-       CLICK_DOUBLE_Y  = 0x08,
-       CLICK_SINGLE_Z  = 0x10,
-       CLICK_DOUBLE_Z  = 0x20,
-       CLICK_IA        = 0x40,
-};
-
-enum lis3lv02d_reg_state {
-       LIS3_REG_OFF    = 0x00,
-       LIS3_REG_ON     = 0x01,
-};
-
-union axis_conversion {
-       struct {
-               int x, y, z;
-       };
-       int as_array[3];
-
-};
-
-struct lis3lv02d {
-       void                    *bus_priv; /* used by the bus layer only */
-       struct device           *pm_dev; /* for pm_runtime purposes */
-       int (*init) (struct lis3lv02d *lis3);
-       int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
-       int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
-       int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
-       int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
-
-       int                     *odrs;     /* Supported output data rates */
-       u8                      *regs;     /* Regs to store / restore */
-       int                     regs_size;
-       u8                      *reg_cache;
-       bool                    regs_stored;
-       u8                      odr_mask;  /* ODR bit mask */
-       u8                      whoami;    /* indicates measurement precision */
-       s16 (*read_data) (struct lis3lv02d *lis3, int reg);
-       int                     mdps_max_val;
-       int                     pwron_delay;
-       int                     scale; /*
-                                       * relationship between 1 LBS and mG
-                                       * (1/1000th of earth gravity)
-                                       */
-
-       struct input_polled_dev *idev;     /* input device */
-       struct platform_device  *pdev;     /* platform device */
-       struct regulator_bulk_data regulators[2];
-       atomic_t                count;     /* interrupt count after last read */
-       union axis_conversion   ac;        /* hw -> logical axis */
-       int                     mapped_btns[3];
-
-       u32                     irq;       /* IRQ number */
-       struct fasync_struct    *async_queue; /* queue for the misc device */
-       wait_queue_head_t       misc_wait; /* Wait queue for the misc device */
-       unsigned long           misc_opened; /* bit0: whether the device is open */
-       int                     data_ready_count[2];
-       atomic_t                wake_thread;
-       unsigned char           irq_cfg;
-
-       struct lis3lv02d_platform_data *pdata;  /* for passing board config */
-       struct mutex            mutex;     /* Serialize poll and selftest */
-};
-
-int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
-void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
-
-extern struct lis3lv02d lis3_dev;
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
deleted file mode 100644 (file)
index 8853afc..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * drivers/hwmon/lis3lv02d_i2c.c
- *
- * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
- * Driver is based on corresponding SPI driver written by Daniel Mack
- * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
- *
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include "lis3lv02d.h"
-
-#define DRV_NAME       "lis3lv02d_i2c"
-
-static const char reg_vdd[]    = "Vdd";
-static const char reg_vdd_io[] = "Vdd_IO";
-
-static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
-{
-       int ret;
-       if (state == LIS3_REG_OFF) {
-               ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
-                                       lis3->regulators);
-       } else {
-               ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
-                                       lis3->regulators);
-               /* Chip needs time to wakeup. Not mentioned in datasheet */
-               usleep_range(10000, 20000);
-       }
-       return ret;
-}
-
-static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
-{
-       struct i2c_client *c = lis3->bus_priv;
-       return i2c_smbus_write_byte_data(c, reg, value);
-}
-
-static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-       struct i2c_client *c = lis3->bus_priv;
-       *v = i2c_smbus_read_byte_data(c, reg);
-       return 0;
-}
-
-static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
-                               u8 *v)
-{
-       struct i2c_client *c = lis3->bus_priv;
-       reg |= (1 << 7); /* 7th bit enables address auto incrementation */
-       return i2c_smbus_read_i2c_block_data(c, reg, len, v);
-}
-
-static int lis3_i2c_init(struct lis3lv02d *lis3)
-{
-       u8 reg;
-       int ret;
-
-       if (lis3->reg_ctrl)
-               lis3_reg_ctrl(lis3, LIS3_REG_ON);
-
-       lis3->read(lis3, WHO_AM_I, &reg);
-       if (reg != lis3->whoami)
-               printk(KERN_ERR "lis3: power on failure\n");
-
-       /* power up the device */
-       ret = lis3->read(lis3, CTRL_REG1, &reg);
-       if (ret < 0)
-               return ret;
-
-       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-       return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-/* Default axis mapping but it can be overwritten by platform data */
-static union axis_conversion lis3lv02d_axis_map =
-       { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
-
-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
-{
-       int ret = 0;
-       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-       if (pdata) {
-               /* Regulator control is optional */
-               if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
-                       lis3_dev.reg_ctrl = lis3_reg_ctrl;
-
-               if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
-                       (i2c_check_functionality(client->adapter,
-                                               I2C_FUNC_SMBUS_I2C_BLOCK)))
-                       lis3_dev.blkread  = lis3_i2c_blockread;
-
-               if (pdata->axis_x)
-                       lis3lv02d_axis_map.x = pdata->axis_x;
-
-               if (pdata->axis_y)
-                       lis3lv02d_axis_map.y = pdata->axis_y;
-
-               if (pdata->axis_z)
-                       lis3lv02d_axis_map.z = pdata->axis_z;
-
-               if (pdata->setup_resources)
-                       ret = pdata->setup_resources();
-
-               if (ret)
-                       goto fail;
-       }
-
-       if (lis3_dev.reg_ctrl) {
-               lis3_dev.regulators[0].supply = reg_vdd;
-               lis3_dev.regulators[1].supply = reg_vdd_io;
-               ret = regulator_bulk_get(&client->dev,
-                                       ARRAY_SIZE(lis3_dev.regulators),
-                                       lis3_dev.regulators);
-               if (ret < 0)
-                       goto fail;
-       }
-
-       lis3_dev.pdata    = pdata;
-       lis3_dev.bus_priv = client;
-       lis3_dev.init     = lis3_i2c_init;
-       lis3_dev.read     = lis3_i2c_read;
-       lis3_dev.write    = lis3_i2c_write;
-       lis3_dev.irq      = client->irq;
-       lis3_dev.ac       = lis3lv02d_axis_map;
-       lis3_dev.pm_dev   = &client->dev;
-
-       i2c_set_clientdata(client, &lis3_dev);
-
-       /* Provide power over the init call */
-       if (lis3_dev.reg_ctrl)
-               lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
-
-       ret = lis3lv02d_init_device(&lis3_dev);
-
-       if (lis3_dev.reg_ctrl)
-               lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
-
-       if (ret == 0)
-               return 0;
-fail:
-       if (pdata && pdata->release_resources)
-               pdata->release_resources();
-       return ret;
-}
-
-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
-{
-       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-       if (pdata && pdata->release_resources)
-               pdata->release_resources();
-
-       lis3lv02d_joystick_disable();
-       lis3lv02d_remove_fs(&lis3_dev);
-
-       if (lis3_dev.reg_ctrl)
-               regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
-                               lis3_dev.regulators);
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int lis3lv02d_i2c_suspend(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-               lis3lv02d_poweroff(lis3);
-       return 0;
-}
-
-static int lis3lv02d_i2c_resume(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-       /*
-        * pm_runtime documentation says that devices should always
-        * be powered on at resume. Pm_runtime turns them off after system
-        * wide resume is complete.
-        */
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
-               pm_runtime_suspended(dev))
-               lis3lv02d_poweron(lis3);
-
-       return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_PM_RUNTIME
-static int lis3_i2c_runtime_suspend(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-       lis3lv02d_poweroff(lis3);
-       return 0;
-}
-
-static int lis3_i2c_runtime_resume(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-       lis3lv02d_poweron(lis3);
-       return 0;
-}
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct i2c_device_id lis3lv02d_id[] = {
-       {"lis3lv02d", 0 },
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
-
-static const struct dev_pm_ops lis3_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
-                               lis3lv02d_i2c_resume)
-       SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
-                          lis3_i2c_runtime_resume,
-                          NULL)
-};
-
-static struct i2c_driver lis3lv02d_i2c_driver = {
-       .driver  = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-               .pm     = &lis3_pm_ops,
-       },
-       .probe  = lis3lv02d_i2c_probe,
-       .remove = __devexit_p(lis3lv02d_i2c_remove),
-       .id_table = lis3lv02d_id,
-};
-
-static int __init lis3lv02d_init(void)
-{
-       return i2c_add_driver(&lis3lv02d_i2c_driver);
-}
-
-static void __exit lis3lv02d_exit(void)
-{
-       i2c_del_driver(&lis3lv02d_i2c_driver);
-}
-
-MODULE_AUTHOR("Nokia Corporation");
-MODULE_DESCRIPTION("lis3lv02d I2C interface");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init);
-module_exit(lis3lv02d_exit);
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c
deleted file mode 100644 (file)
index c1f8a8f..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * lis3lv02d_spi - SPI glue layer for lis3lv02d
- *
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  publishhed by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-#include <linux/pm.h>
-
-#include "lis3lv02d.h"
-
-#define DRV_NAME       "lis3lv02d_spi"
-#define LIS3_SPI_READ  0x80
-
-static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-       struct spi_device *spi = lis3->bus_priv;
-       int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
-       if (ret < 0)
-               return -EINVAL;
-
-       *v = (u8) ret;
-       return 0;
-}
-
-static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-       u8 tmp[2] = { reg, val };
-       struct spi_device *spi = lis3->bus_priv;
-       return spi_write(spi, tmp, sizeof(tmp));
-}
-
-static int lis3_spi_init(struct lis3lv02d *lis3)
-{
-       u8 reg;
-       int ret;
-
-       /* power up the device */
-       ret = lis3->read(lis3, CTRL_REG1, &reg);
-       if (ret < 0)
-               return ret;
-
-       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-       return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-static union axis_conversion lis3lv02d_axis_normal =
-       { .as_array = { 1, 2, 3 } };
-
-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
-{
-       int ret;
-
-       spi->bits_per_word = 8;
-       spi->mode = SPI_MODE_0;
-       ret = spi_setup(spi);
-       if (ret < 0)
-               return ret;
-
-       lis3_dev.bus_priv       = spi;
-       lis3_dev.init           = lis3_spi_init;
-       lis3_dev.read           = lis3_spi_read;
-       lis3_dev.write          = lis3_spi_write;
-       lis3_dev.irq            = spi->irq;
-       lis3_dev.ac             = lis3lv02d_axis_normal;
-       lis3_dev.pdata          = spi->dev.platform_data;
-       spi_set_drvdata(spi, &lis3_dev);
-
-       return lis3lv02d_init_device(&lis3_dev);
-}
-
-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
-{
-       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-       lis3lv02d_joystick_disable();
-       lis3lv02d_poweroff(lis3);
-
-       return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int lis3lv02d_spi_suspend(struct device *dev)
-{
-       struct spi_device *spi = to_spi_device(dev);
-       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-               lis3lv02d_poweroff(&lis3_dev);
-
-       return 0;
-}
-
-static int lis3lv02d_spi_resume(struct device *dev)
-{
-       struct spi_device *spi = to_spi_device(dev);
-       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-               lis3lv02d_poweron(lis3);
-
-       return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
-                        lis3lv02d_spi_resume);
-
-static struct spi_driver lis302dl_spi_driver = {
-       .driver  = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-               .pm     = &lis3lv02d_spi_pm,
-       },
-       .probe  = lis302dl_spi_probe,
-       .remove = __devexit_p(lis302dl_spi_remove),
-};
-
-static int __init lis302dl_init(void)
-{
-       return spi_register_driver(&lis302dl_spi_driver);
-}
-
-static void __exit lis302dl_exit(void)
-{
-       spi_unregister_driver(&lis302dl_spi_driver);
-}
-
-module_init(lis302dl_init);
-module_exit(lis302dl_exit);
-
-MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:" DRV_NAME);
index f36eb80d227fa27c2e5d2a547465ba7f25ecc132..ef902d5d06ab9f98e610f63ed0ee709eb0f66b87 100644 (file)
@@ -232,13 +232,16 @@ static const struct i2c_device_id lm75_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, lm75_ids);
 
+#define LM75A_ID 0xA1
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm75_detect(struct i2c_client *new_client,
                       struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = new_client->adapter;
        int i;
-       int cur, conf, hyst, os;
+       int conf, hyst, os;
+       bool is_lm75a = 0;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_WORD_DATA))
@@ -250,37 +253,58 @@ static int lm75_detect(struct i2c_client *new_client,
           addresses 0x04-0x07 returning the last read value.
           The cycling+unused addresses combination is not tested,
           since it would significantly slow the detection down and would
-          hardly add any value. */
+          hardly add any value.
 
-       /* Unused addresses */
-       cur = i2c_smbus_read_word_data(new_client, 0);
-       conf = i2c_smbus_read_byte_data(new_client, 1);
-       hyst = i2c_smbus_read_word_data(new_client, 2);
-       if (i2c_smbus_read_word_data(new_client, 4) != hyst
-        || i2c_smbus_read_word_data(new_client, 5) != hyst
-        || i2c_smbus_read_word_data(new_client, 6) != hyst
-        || i2c_smbus_read_word_data(new_client, 7) != hyst)
-               return -ENODEV;
-       os = i2c_smbus_read_word_data(new_client, 3);
-       if (i2c_smbus_read_word_data(new_client, 4) != os
-        || i2c_smbus_read_word_data(new_client, 5) != os
-        || i2c_smbus_read_word_data(new_client, 6) != os
-        || i2c_smbus_read_word_data(new_client, 7) != os)
-               return -ENODEV;
+          The National Semiconductor LM75A is different than earlier
+          LM75s.  It has an ID byte of 0xaX (where X is the chip
+          revision, with 1 being the only revision in existence) in
+          register 7, and unused registers return 0xff rather than the
+          last read value. */
 
        /* Unused bits */
+       conf = i2c_smbus_read_byte_data(new_client, 1);
        if (conf & 0xe0)
                return -ENODEV;
 
+       /* First check for LM75A */
+       if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
+               /* LM75A returns 0xff on unused registers so
+                  just to be sure we check for that too. */
+               if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
+                || i2c_smbus_read_byte_data(new_client, 5) != 0xff
+                || i2c_smbus_read_byte_data(new_client, 6) != 0xff)
+                       return -ENODEV;
+               is_lm75a = 1;
+               hyst = i2c_smbus_read_byte_data(new_client, 2);
+               os = i2c_smbus_read_byte_data(new_client, 3);
+       } else { /* Traditional style LM75 detection */
+               /* Unused addresses */
+               hyst = i2c_smbus_read_byte_data(new_client, 2);
+               if (i2c_smbus_read_byte_data(new_client, 4) != hyst
+                || i2c_smbus_read_byte_data(new_client, 5) != hyst
+                || i2c_smbus_read_byte_data(new_client, 6) != hyst
+                || i2c_smbus_read_byte_data(new_client, 7) != hyst)
+                       return -ENODEV;
+               os = i2c_smbus_read_byte_data(new_client, 3);
+               if (i2c_smbus_read_byte_data(new_client, 4) != os
+                || i2c_smbus_read_byte_data(new_client, 5) != os
+                || i2c_smbus_read_byte_data(new_client, 6) != os
+                || i2c_smbus_read_byte_data(new_client, 7) != os)
+                       return -ENODEV;
+       }
+
        /* Addresses cycling */
-       for (i = 8; i < 0xff; i += 8) {
+       for (i = 8; i <= 248; i += 40) {
                if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
-                || i2c_smbus_read_word_data(new_client, i + 2) != hyst
-                || i2c_smbus_read_word_data(new_client, i + 3) != os)
+                || i2c_smbus_read_byte_data(new_client, i + 2) != hyst
+                || i2c_smbus_read_byte_data(new_client, i + 3) != os)
+                       return -ENODEV;
+               if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7)
+                               != LM75A_ID)
                        return -ENODEV;
        }
 
-       strlcpy(info->type, "lm75", I2C_NAME_SIZE);
+       strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE);
 
        return 0;
 }
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
new file mode 100644 (file)
index 0000000..9a51dcc
--- /dev/null
@@ -0,0 +1,858 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#define DRVNAME "sch5627"
+#define DEVNAME DRVNAME /* We only support one model */
+
+#define SIO_SCH5627_EM_LD      0x0C    /* Embedded Microcontroller LD */
+#define SIO_UNLOCK_KEY         0x55    /* Key to enable Super-I/O */
+#define SIO_LOCK_KEY           0xAA    /* Key to disable Super-I/O */
+
+#define SIO_REG_LDSEL          0x07    /* Logical device select */
+#define SIO_REG_DEVID          0x20    /* Device ID */
+#define SIO_REG_ENABLE         0x30    /* Logical device enable */
+#define SIO_REG_ADDR           0x66    /* Logical device address (2 bytes) */
+
+#define SIO_SCH5627_ID         0xC6    /* Chipset ID */
+
+#define REGION_LENGTH          9
+
+#define SCH5627_HWMON_ID               0xa5
+#define SCH5627_COMPANY_ID             0x5c
+#define SCH5627_PRIMARY_ID             0xa0
+
+#define SCH5627_REG_BUILD_CODE         0x39
+#define SCH5627_REG_BUILD_ID           0x3a
+#define SCH5627_REG_HWMON_ID           0x3c
+#define SCH5627_REG_HWMON_REV          0x3d
+#define SCH5627_REG_COMPANY_ID         0x3e
+#define SCH5627_REG_PRIMARY_ID         0x3f
+#define SCH5627_REG_CTRL               0x40
+
+#define SCH5627_NO_TEMPS               8
+#define SCH5627_NO_FANS                        4
+#define SCH5627_NO_IN                  5
+
+static const u16 SCH5627_REG_TEMP_MSB[SCH5627_NO_TEMPS] = {
+       0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181 };
+static const u16 SCH5627_REG_TEMP_LSN[SCH5627_NO_TEMPS] = {
+       0xE2, 0xE1, 0xE1, 0xE5, 0xE5, 0xE6, 0x182, 0x182 };
+static const u16 SCH5627_REG_TEMP_HIGH_NIBBLE[SCH5627_NO_TEMPS] = {
+       0, 0, 1, 1, 0, 0, 0, 1 };
+static const u16 SCH5627_REG_TEMP_HIGH[SCH5627_NO_TEMPS] = {
+       0x61, 0x57, 0x59, 0x5B, 0x5D, 0x5F, 0x184, 0x186 };
+static const u16 SCH5627_REG_TEMP_ABS[SCH5627_NO_TEMPS] = {
+       0x9B, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x1A8, 0x1A9 };
+
+static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = {
+       0x2C, 0x2E, 0x30, 0x32 };
+static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = {
+       0x62, 0x64, 0x66, 0x68 };
+
+static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = {
+       0x22, 0x23, 0x24, 0x25, 0x189 };
+static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = {
+       0xE4, 0xE4, 0xE3, 0xE3, 0x18A };
+static const u16 SCH5627_REG_IN_HIGH_NIBBLE[SCH5627_NO_IN] = {
+       1, 0, 1, 0, 1 };
+static const u16 SCH5627_REG_IN_FACTOR[SCH5627_NO_IN] = {
+       10745, 3660, 9765, 10745, 3660 };
+static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = {
+       "VCC", "VTT", "VBAT", "VTR", "V_IN" };
+
+struct sch5627_data {
+       unsigned short addr;
+       struct device *hwmon_dev;
+       u8 temp_max[SCH5627_NO_TEMPS];
+       u8 temp_crit[SCH5627_NO_TEMPS];
+       u16 fan_min[SCH5627_NO_FANS];
+
+       struct mutex update_lock;
+       char valid;                     /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+       u16 temp[SCH5627_NO_TEMPS];
+       u16 fan[SCH5627_NO_FANS];
+       u16 in[SCH5627_NO_IN];
+};
+
+static struct platform_device *sch5627_pdev;
+
+/* Super I/O functions */
+static inline int superio_inb(int base, int reg)
+{
+       outb(reg, base);
+       return inb(base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+       /* Don't step on other drivers' I/O space by accident */
+       if (!request_muxed_region(base, 2, DRVNAME)) {
+               pr_err("I/O address 0x%04x already in use\n", base);
+               return -EBUSY;
+       }
+
+       outb(SIO_UNLOCK_KEY, base);
+
+       return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+       outb(SIO_REG_LDSEL, base);
+       outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+       outb(SIO_LOCK_KEY, base);
+       release_region(base, 2);
+}
+
+static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
+{
+       u8 val;
+       int i;
+       /*
+        * According to SMSC for the commands we use the maximum time for
+        * the EM to respond is 15 ms, but testing shows in practice it
+        * responds within 15-32 reads, so we first busy poll, and if
+        * that fails sleep a bit and try again until we are way past
+        * the 15 ms maximum response time.
+        */
+       const int max_busy_polls = 64;
+       const int max_lazy_polls = 32;
+
+       /* (Optional) Write-Clear the EC to Host Mailbox Register */
+       val = inb(data->addr + 1);
+       outb(val, data->addr + 1);
+
+       /* Set Mailbox Address Pointer to first location in Region 1 */
+       outb(0x00, data->addr + 2);
+       outb(0x80, data->addr + 3);
+
+       /* Write Request Packet Header */
+       outb(0x02, data->addr + 4); /* Access Type: VREG read */
+       outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
+       outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
+
+       /* Write Address field */
+       outb(reg & 0xff, data->addr + 6);
+       outb(reg >> 8, data->addr + 7);
+
+       /* Execute the Random Access Command */
+       outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
+
+       /* EM Interface Polling "Algorithm" */
+       for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
+               if (i >= max_busy_polls)
+                       msleep(1);
+               /* Read Interrupt source Register */
+               val = inb(data->addr + 8);
+               /* Write Clear the interrupt source bits */
+               if (val)
+                       outb(val, data->addr + 8);
+               /* Command Completed ? */
+               if (val & 0x01)
+                       break;
+       }
+       if (i == max_busy_polls + max_lazy_polls) {
+               pr_err("Max retries exceeded reading virtual "
+                      "register 0x%04hx (%d)\n", reg, 1);
+               return -EIO;
+       }
+
+       /*
+        * According to SMSC we may need to retry this, but sofar I've always
+        * seen this succeed in 1 try.
+        */
+       for (i = 0; i < max_busy_polls; i++) {
+               /* Read EC-to-Host Register */
+               val = inb(data->addr + 1);
+               /* Command Completed ? */
+               if (val == 0x01)
+                       break;
+
+               if (i == 0)
+                       pr_warn("EC reports: 0x%02x reading virtual register "
+                               "0x%04hx\n", (unsigned int)val, reg);
+       }
+       if (i == max_busy_polls) {
+               pr_err("Max retries exceeded reading virtual "
+                      "register 0x%04hx (%d)\n", reg, 2);
+               return -EIO;
+       }
+
+       /*
+        * According to the SMSC app note we should now do:
+        *
+        * Set Mailbox Address Pointer to first location in Region 1 *
+        * outb(0x00, data->addr + 2);
+        * outb(0x80, data->addr + 3);
+        *
+        * But if we do that things don't work, so let's not.
+        */
+
+       /* Read Data from Mailbox */
+       return inb(data->addr + 4);
+}
+
+static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
+{
+       int lsb, msb;
+
+       /* Read LSB first, this will cause the matching MSB to be latched */
+       lsb = sch5627_read_virtual_reg(data, reg);
+       if (lsb < 0)
+               return lsb;
+
+       msb = sch5627_read_virtual_reg(data, reg + 1);
+       if (msb < 0)
+               return msb;
+
+       return lsb | (msb << 8);
+}
+
+static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
+                                     u16 lsn_reg, int high_nibble)
+{
+       int msb, lsn;
+
+       /* Read MSB first, this will cause the matching LSN to be latched */
+       msb = sch5627_read_virtual_reg(data, msb_reg);
+       if (msb < 0)
+               return msb;
+
+       lsn = sch5627_read_virtual_reg(data, lsn_reg);
+       if (lsn < 0)
+               return lsn;
+
+       if (high_nibble)
+               return (msb << 4) | (lsn >> 4);
+       else
+               return (msb << 4) | (lsn & 0x0f);
+}
+
+static struct sch5627_data *sch5627_update_device(struct device *dev)
+{
+       struct sch5627_data *data = dev_get_drvdata(dev);
+       struct sch5627_data *ret = data;
+       int i, val;
+
+       mutex_lock(&data->update_lock);
+
+       /* Cache the values for 1 second */
+       if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+               for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+                       val = sch5627_read_virtual_reg12(data,
+                               SCH5627_REG_TEMP_MSB[i],
+                               SCH5627_REG_TEMP_LSN[i],
+                               SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
+                       if (unlikely(val < 0)) {
+                               ret = ERR_PTR(val);
+                               goto abort;
+                       }
+                       data->temp[i] = val;
+               }
+
+               for (i = 0; i < SCH5627_NO_FANS; i++) {
+                       val = sch5627_read_virtual_reg16(data,
+                                                        SCH5627_REG_FAN[i]);
+                       if (unlikely(val < 0)) {
+                               ret = ERR_PTR(val);
+                               goto abort;
+                       }
+                       data->fan[i] = val;
+               }
+
+               for (i = 0; i < SCH5627_NO_IN; i++) {
+                       val = sch5627_read_virtual_reg12(data,
+                               SCH5627_REG_IN_MSB[i],
+                               SCH5627_REG_IN_LSN[i],
+                               SCH5627_REG_IN_HIGH_NIBBLE[i]);
+                       if (unlikely(val < 0)) {
+                               ret = ERR_PTR(val);
+                               goto abort;
+                       }
+                       data->in[i] = val;
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+abort:
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static int __devinit sch5627_read_limits(struct sch5627_data *data)
+{
+       int i, val;
+
+       for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+               /*
+                * Note what SMSC calls ABS, is what lm_sensors calls max
+                * (aka high), and HIGH is what lm_sensors calls crit.
+                */
+               val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
+               if (val < 0)
+                       return val;
+               data->temp_max[i] = val;
+
+               val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
+               if (val < 0)
+                       return val;
+               data->temp_crit[i] = val;
+       }
+       for (i = 0; i < SCH5627_NO_FANS; i++) {
+               val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
+               if (val < 0)
+                       return val;
+               data->fan_min[i] = val;
+       }
+
+       return 0;
+}
+
+static int reg_to_temp(u16 reg)
+{
+       return (reg * 625) / 10 - 64000;
+}
+
+static int reg_to_temp_limit(u8 reg)
+{
+       return (reg - 64) * 1000;
+}
+
+static int reg_to_rpm(u16 reg)
+{
+       if (reg == 0)
+               return -EIO;
+       if (reg == 0xffff)
+               return 0;
+
+       return 5400540 / reg;
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+       char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = sch5627_update_device(dev);
+       int val;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       val = reg_to_temp(data->temp[attr->index]);
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = sch5627_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = dev_get_drvdata(dev);
+       int val;
+
+       val = reg_to_temp_limit(data->temp_max[attr->index]);
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = dev_get_drvdata(dev);
+       int val;
+
+       val = reg_to_temp_limit(data->temp_crit[attr->index]);
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = sch5627_update_device(dev);
+       int val;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       val = reg_to_rpm(data->fan[attr->index]);
+       if (val < 0)
+               return val;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = sch5627_update_device(dev);
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->fan[attr->index] == 0xffff);
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = dev_get_drvdata(dev);
+       int val = reg_to_rpm(data->fan_min[attr->index]);
+       if (val < 0)
+               return val;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct sch5627_data *data = sch5627_update_device(dev);
+       int val;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       val = DIV_ROUND_CLOSEST(
+               data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index],
+               10000);
+       return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in_label(struct device *dev, struct device_attribute
+       *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       SCH5627_IN_LABELS[attr->index]);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3);
+
+static struct attribute *sch5627_attributes[] = {
+       &dev_attr_name.attr,
+
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp5_input.dev_attr.attr,
+       &sensor_dev_attr_temp6_input.dev_attr.attr,
+       &sensor_dev_attr_temp7_input.dev_attr.attr,
+       &sensor_dev_attr_temp8_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
+       &sensor_dev_attr_temp3_fault.dev_attr.attr,
+       &sensor_dev_attr_temp4_fault.dev_attr.attr,
+       &sensor_dev_attr_temp5_fault.dev_attr.attr,
+       &sensor_dev_attr_temp6_fault.dev_attr.attr,
+       &sensor_dev_attr_temp7_fault.dev_attr.attr,
+       &sensor_dev_attr_temp8_fault.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp4_max.dev_attr.attr,
+       &sensor_dev_attr_temp5_max.dev_attr.attr,
+       &sensor_dev_attr_temp6_max.dev_attr.attr,
+       &sensor_dev_attr_temp7_max.dev_attr.attr,
+       &sensor_dev_attr_temp8_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit.dev_attr.attr,
+       &sensor_dev_attr_temp4_crit.dev_attr.attr,
+       &sensor_dev_attr_temp5_crit.dev_attr.attr,
+       &sensor_dev_attr_temp6_crit.dev_attr.attr,
+       &sensor_dev_attr_temp7_crit.dev_attr.attr,
+       &sensor_dev_attr_temp8_crit.dev_attr.attr,
+
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_fault.dev_attr.attr,
+       &sensor_dev_attr_fan2_fault.dev_attr.attr,
+       &sensor_dev_attr_fan3_fault.dev_attr.attr,
+       &sensor_dev_attr_fan4_fault.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan3_min.dev_attr.attr,
+       &sensor_dev_attr_fan4_min.dev_attr.attr,
+
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in0_label.dev_attr.attr,
+       &sensor_dev_attr_in1_label.dev_attr.attr,
+       &sensor_dev_attr_in2_label.dev_attr.attr,
+       &sensor_dev_attr_in3_label.dev_attr.attr,
+       /* No in4_label as in4 is a generic input pin */
+
+       NULL
+};
+
+static const struct attribute_group sch5627_group = {
+       .attrs = sch5627_attributes,
+};
+
+static int sch5627_remove(struct platform_device *pdev)
+{
+       struct sch5627_data *data = platform_get_drvdata(pdev);
+
+       if (data->hwmon_dev)
+               hwmon_device_unregister(data->hwmon_dev);
+
+       sysfs_remove_group(&pdev->dev.kobj, &sch5627_group);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+
+       return 0;
+}
+
+static int __devinit sch5627_probe(struct platform_device *pdev)
+{
+       struct sch5627_data *data;
+       int err, build_code, build_id, hwmon_rev, val;
+
+       data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+       mutex_init(&data->update_lock);
+       platform_set_drvdata(pdev, data);
+
+       val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
+       if (val < 0) {
+               err = val;
+               goto error;
+       }
+       if (val != SCH5627_HWMON_ID) {
+               pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "hwmon",
+                      val, SCH5627_HWMON_ID);
+               err = -ENODEV;
+               goto error;
+       }
+
+       val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
+       if (val < 0) {
+               err = val;
+               goto error;
+       }
+       if (val != SCH5627_COMPANY_ID) {
+               pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "company",
+                      val, SCH5627_COMPANY_ID);
+               err = -ENODEV;
+               goto error;
+       }
+
+       val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
+       if (val < 0) {
+               err = val;
+               goto error;
+       }
+       if (val != SCH5627_PRIMARY_ID) {
+               pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "primary",
+                      val, SCH5627_PRIMARY_ID);
+               err = -ENODEV;
+               goto error;
+       }
+
+       build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
+       if (build_code < 0) {
+               err = build_code;
+               goto error;
+       }
+
+       build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
+       if (build_id < 0) {
+               err = build_id;
+               goto error;
+       }
+
+       hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
+       if (hwmon_rev < 0) {
+               err = hwmon_rev;
+               goto error;
+       }
+
+       val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
+       if (val < 0) {
+               err = val;
+               goto error;
+       }
+       if (!(val & 0x01)) {
+               pr_err("hardware monitoring not enabled\n");
+               err = -ENODEV;
+               goto error;
+       }
+
+       /*
+        * Read limits, we do this only once as reading a register on
+        * the sch5627 is quite expensive (and they don't change).
+        */
+       err = sch5627_read_limits(data);
+       if (err)
+               goto error;
+
+       pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
+               build_code, build_id, hwmon_rev);
+
+       /* Register sysfs interface files */
+       err = sysfs_create_group(&pdev->dev.kobj, &sch5627_group);
+       if (err)
+               goto error;
+
+       data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               data->hwmon_dev = NULL;
+               goto error;
+       }
+
+       return 0;
+
+error:
+       sch5627_remove(pdev);
+       return err;
+}
+
+static int __init sch5627_find(int sioaddr, unsigned short *address)
+{
+       u8 devid;
+       int err = superio_enter(sioaddr);
+       if (err)
+               return err;
+
+       devid = superio_inb(sioaddr, SIO_REG_DEVID);
+       if (devid != SIO_SCH5627_ID) {
+               pr_debug("Unsupported device id: 0x%02x\n",
+                        (unsigned int)devid);
+               err = -ENODEV;
+               goto exit;
+       }
+
+       superio_select(sioaddr, SIO_SCH5627_EM_LD);
+
+       if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+               pr_warn("Device not activated\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       /*
+        * Warning the order of the low / high byte is the other way around
+        * as on most other superio devices!!
+        */
+       *address = superio_inb(sioaddr, SIO_REG_ADDR) |
+                  superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
+       if (*address == 0) {
+               pr_warn("Base address not set\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
+exit:
+       superio_exit(sioaddr);
+       return err;
+}
+
+static int __init sch5627_device_add(unsigned short address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + REGION_LENGTH - 1,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       sch5627_pdev = platform_device_alloc(DRVNAME, address);
+       if (!sch5627_pdev)
+               return -ENOMEM;
+
+       res.name = sch5627_pdev->name;
+       err = acpi_check_resource_conflict(&res);
+       if (err)
+               goto exit_device_put;
+
+       err = platform_device_add_resources(sch5627_pdev, &res, 1);
+       if (err) {
+               pr_err("Device resource addition failed\n");
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(sch5627_pdev);
+       if (err) {
+               pr_err("Device addition failed\n");
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(sch5627_pdev);
+
+       return err;
+}
+
+static struct platform_driver sch5627_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = DRVNAME,
+       },
+       .probe          = sch5627_probe,
+       .remove         = sch5627_remove,
+};
+
+static int __init sch5627_init(void)
+{
+       int err = -ENODEV;
+       unsigned short address;
+
+       if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
+               goto exit;
+
+       err = platform_driver_register(&sch5627_driver);
+       if (err)
+               goto exit;
+
+       err = sch5627_device_add(address);
+       if (err)
+               goto exit_driver;
+
+       return 0;
+
+exit_driver:
+       platform_driver_unregister(&sch5627_driver);
+exit:
+       return err;
+}
+
+static void __exit sch5627_exit(void)
+{
+       platform_device_unregister(sch5627_pdev);
+       platform_driver_unregister(&sch5627_driver);
+}
+
+MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
+MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
+MODULE_LICENSE("GPL");
+
+module_init(sch5627_init);
+module_exit(sch5627_exit);
index a610e7880fb3e5498b5d836d456ec4e25c58e278..1a9c32d6893a83b2c6603b70c0bfa1e0428488d7 100644 (file)
@@ -333,11 +333,11 @@ static inline int sht15_calc_humid(struct sht15_data *data)
 
        const int c1 = -4;
        const int c2 = 40500; /* x 10 ^ -6 */
-       const int c3 = -2800; /* x10 ^ -9 */
+       const int c3 = -28; /* x 10 ^ -7 */
 
        RHlinear = c1*1000
                + c2 * data->val_humid/1000
-               + (data->val_humid * data->val_humid * c3)/1000000;
+               + (data->val_humid * data->val_humid * c3) / 10000;
        return (temp - 25000) * (10000 + 80 * data->val_humid)
                / 1000000 + RHlinear;
 }
@@ -610,7 +610,7 @@ static int __devexit sht15_remove(struct platform_device *pdev)
        struct sht15_data *data = platform_get_drvdata(pdev);
 
        /* Make sure any reads from the device are done and
-        * prevent new ones beginnning */
+        * prevent new ones from beginning */
        mutex_lock(&data->read_lock);
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
index 23ac61e2db398363ccb4bb742d8f07aff0aa7e60..beee6b2d361db458a1336a48bd13b5166d6d013c 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_I2C_MUX)         += i2c-mux.o
 obj-y                          += algos/ busses/ muxes/
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
+CFLAGS_i2c-core.o := -Wno-deprecated-declarations
index 230601e8853fff715a23465a507cdc054390d72b..ad415e6ec5a10aa628414ef3370c68526d58f226 100644 (file)
@@ -98,8 +98,9 @@ config I2C_I801
            EP80579 (Tolapai)
            ICH10
            5/3400 Series (PCH)
-           Cougar Point (PCH)
+           6 Series (PCH)
            Patsburg (PCH)
+           DH89xxCC (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
index 7979aef7ee7b2db822ca99937210c04346815006..ed2e0c5ea37c7b53ee1b67a20881caff26e7797d 100644 (file)
   ICH10                 0x3a30     32     hard     yes     yes     yes
   ICH10                 0x3a60     32     hard     yes     yes     yes
   5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes
-  Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes
+  6 Series (PCH)        0x1c22     32     hard     yes     yes     yes
   Patsburg (PCH)        0x1d22     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d70     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d71     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
+  DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
@@ -621,6 +622,7 @@ static const struct pci_device_id i801_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
        { 0, }
 };
 
index 7e6a63b571650b1f100c4707309f31de1af415bb..3ca2e012e78932ed8cf33339a3a0a0d404026c03 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * i2c-boardinfo.h - collect pre-declarations of I2C devices
+ * i2c-boardinfo.c - collect pre-declarations of I2C devices
  *
  * 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
index 045ba6efea48fd24cbf651115e2d86a4f87781b4..e5f76a0372fd6f6e9d1fa063b60a07ffb08fb781 100644 (file)
@@ -797,6 +797,9 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
 
        /* Let legacy drivers scan this bus for matching devices */
        if (driver->attach_adapter) {
+               dev_warn(&adap->dev, "attach_adapter method is deprecated\n");
+               dev_warn(&adap->dev, "Please use another way to instantiate "
+                        "your i2c_client\n");
                /* We ignore the return code; if it fails, too bad */
                driver->attach_adapter(adap);
        }
@@ -981,6 +984,7 @@ static int i2c_do_del_adapter(struct i2c_driver *driver,
 
        if (!driver->detach_adapter)
                return 0;
+       dev_warn(&adapter->dev, "detach_adapter method is deprecated\n");
        res = driver->detach_adapter(adapter);
        if (res)
                dev_err(&adapter->dev, "detach_adapter failed (%d) "
@@ -1091,6 +1095,18 @@ EXPORT_SYMBOL(i2c_del_adapter);
 
 /* ------------------------------------------------------------------------- */
 
+int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
+{
+       int res;
+
+       mutex_lock(&core_lock);
+       res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
+       mutex_unlock(&core_lock);
+
+       return res;
+}
+EXPORT_SYMBOL_GPL(i2c_for_each_dev);
+
 static int __process_new_driver(struct device *dev, void *data)
 {
        if (dev->type != &i2c_adapter_type)
@@ -1134,9 +1150,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 
        INIT_LIST_HEAD(&driver->clients);
        /* Walk the adapters that are already present */
-       mutex_lock(&core_lock);
-       bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
-       mutex_unlock(&core_lock);
+       i2c_for_each_dev(driver, __process_new_driver);
 
        return 0;
 }
@@ -1156,9 +1170,7 @@ static int __process_removed_driver(struct device *dev, void *data)
  */
 void i2c_del_driver(struct i2c_driver *driver)
 {
-       mutex_lock(&core_lock);
-       bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);
-       mutex_unlock(&core_lock);
+       i2c_for_each_dev(driver, __process_removed_driver);
 
        driver_unregister(&driver->driver);
        pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
@@ -1581,12 +1593,12 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 }
 EXPORT_SYMBOL_GPL(i2c_new_probed_device);
 
-struct i2c_adapter *i2c_get_adapter(int id)
+struct i2c_adapter *i2c_get_adapter(int nr)
 {
        struct i2c_adapter *adapter;
 
        mutex_lock(&core_lock);
-       adapter = idr_find(&i2c_adapter_idr, id);
+       adapter = idr_find(&i2c_adapter_idr, nr);
        if (adapter && !try_module_get(adapter->owner))
                adapter = NULL;
 
index cec0f3ba97f8b1a74d7134d3a86a61e4a79474df..c90ce50b619f7b483b85483a24457a8cab73f3c2 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/device.h>
+#include <linux/notifier.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 
-static struct i2c_driver i2cdev_driver;
-
 /*
  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
  * slave (i2c_client) with which messages will be exchanged.  It's coupled
  * with a character special file which is accessed by user mode drivers.
  *
  * The list of i2c_dev structures is parallel to the i2c_adapter lists
- * maintained by the driver model, and is updated using notifications
- * delivered to the i2cdev_driver.
+ * maintained by the driver model, and is updated using bus notifications.
  */
 struct i2c_dev {
        struct list_head list;
@@ -491,7 +490,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
                return -ENOMEM;
        }
        snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
-       client->driver = &i2cdev_driver;
 
        client->adapter = adap;
        file->private_data = client;
@@ -522,19 +520,18 @@ static const struct file_operations i2cdev_fops = {
 
 /* ------------------------------------------------------------------------- */
 
-/*
- * The legacy "i2cdev_driver" is used primarily to get notifications when
- * I2C adapters are added or removed, so that each one gets an i2c_dev
- * and is thus made available to userspace driver code.
- */
-
 static struct class *i2c_dev_class;
 
-static int i2cdev_attach_adapter(struct i2c_adapter *adap)
+static int i2cdev_attach_adapter(struct device *dev, void *dummy)
 {
+       struct i2c_adapter *adap;
        struct i2c_dev *i2c_dev;
        int res;
 
+       if (dev->type != &i2c_adapter_type)
+               return 0;
+       adap = to_i2c_adapter(dev);
+
        i2c_dev = get_free_i2c_dev(adap);
        if (IS_ERR(i2c_dev))
                return PTR_ERR(i2c_dev);
@@ -561,10 +558,15 @@ error:
        return res;
 }
 
-static int i2cdev_detach_adapter(struct i2c_adapter *adap)
+static int i2cdev_detach_adapter(struct device *dev, void *dummy)
 {
+       struct i2c_adapter *adap;
        struct i2c_dev *i2c_dev;
 
+       if (dev->type != &i2c_adapter_type)
+               return 0;
+       adap = to_i2c_adapter(dev);
+
        i2c_dev = i2c_dev_get_by_minor(adap->nr);
        if (!i2c_dev) /* attach_adapter must have failed */
                return 0;
@@ -577,12 +579,23 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
        return 0;
 }
 
-static struct i2c_driver i2cdev_driver = {
-       .driver = {
-               .name   = "dev_driver",
-       },
-       .attach_adapter = i2cdev_attach_adapter,
-       .detach_adapter = i2cdev_detach_adapter,
+int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+                        void *data)
+{
+       struct device *dev = data;
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               return i2cdev_attach_adapter(dev, NULL);
+       case BUS_NOTIFY_DEL_DEVICE:
+               return i2cdev_detach_adapter(dev, NULL);
+       }
+
+       return 0;
+}
+
+static struct notifier_block i2cdev_notifier = {
+       .notifier_call = i2cdev_notifier_call,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -607,10 +620,14 @@ static int __init i2c_dev_init(void)
                goto out_unreg_chrdev;
        }
 
-       res = i2c_add_driver(&i2cdev_driver);
+       /* Keep track of adapters which will be added or removed later */
+       res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
        if (res)
                goto out_unreg_class;
 
+       /* Bind to already existing adapters right away */
+       i2c_for_each_dev(NULL, i2cdev_attach_adapter);
+
        return 0;
 
 out_unreg_class:
@@ -624,7 +641,8 @@ out:
 
 static void __exit i2c_dev_exit(void)
 {
-       i2c_del_driver(&i2cdev_driver);
+       bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
+       i2c_for_each_dev(NULL, i2cdev_detach_adapter);
        class_destroy(i2c_dev_class);
        unregister_chrdev(I2C_MAJOR, "i2c");
 }
index 81df925f0e8b932c3e821e29dbe2e94d636a2d08..7f879b2397b0e35a535449a3e0dcca8b36f48f10 100644 (file)
@@ -2,7 +2,7 @@
 # link order is important here
 #
 
-EXTRA_CFLAGS                           += -Idrivers/ide
+ccflags-y                              := -Idrivers/ide
 
 ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
              ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
index e0e8e1a184ffa3ff7c7c02682d6fb9eb8c982330..68999137dedfe24cb7044d6de38b6e4f6f8193c5 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
 
-EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
+ccflags-y := -DDEBUG -DCONFIG_FFD
index 1903c0f5b9257d2384cec4a8763cf116c2bb904e..23e82e46656dbe08236577dd0d5fdf04ca209f61 100644 (file)
@@ -161,16 +161,6 @@ config INPUT_APMPOWER
          To compile this driver as a module, choose M here: the
          module will be called apm-power.
 
-config XEN_KBDDEV_FRONTEND
-       tristate "Xen virtual keyboard and mouse support"
-       depends on XEN_FBDEV_FRONTEND
-       default y
-       select XEN_XENBUS_FRONTEND
-       help
-         This driver implements the front-end of the Xen virtual
-         keyboard and mouse device driver.  It communicates with a back-end
-         in another domain.
-
 comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
index 09614ce74961bccded0b02ecd29815f3947533a1..0c789490e0b359d60040fd82ed6c19dfb8784d04 100644 (file)
@@ -24,5 +24,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN)       += touchscreen/
 obj-$(CONFIG_INPUT_MISC)       += misc/
 
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
-
-obj-$(CONFIG_XEN_KBDDEV_FRONTEND)      += xen-kbdfront.o
index c8471a2552e73ea28c7401e58e713b66bbc6cc33..7f42d3a454d2d6aaebdc41e0e5a8c6700d6a00df 100644 (file)
@@ -321,6 +321,9 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
        struct input_event event;
        int retval;
 
+       if (count < input_event_size())
+               return -EINVAL;
+
        retval = mutex_lock_interruptible(&evdev->mutex);
        if (retval)
                return retval;
@@ -330,17 +333,16 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
                goto out;
        }
 
-       while (retval < count) {
-
+       do {
                if (input_event_from_user(buffer + retval, &event)) {
                        retval = -EFAULT;
                        goto out;
                }
+               retval += input_event_size();
 
                input_inject_event(&evdev->handle,
                                   event.type, event.code, event.value);
-               retval += input_event_size();
-       }
+       } while (retval + input_event_size() <= count);
 
  out:
        mutex_unlock(&evdev->mutex);
index 0559e309bac9a443230e66d3f3cfff31e7963f0b..3037842a60d8a10e0533033b665aca490c10b030 100644 (file)
@@ -192,7 +192,7 @@ static struct attribute_group input_polldev_attribute_group = {
 };
 
 /**
- * input_allocate_polled_device - allocated memory polled device
+ * input_allocate_polled_device - allocate memory for polled device
  *
  * The function allocates memory for a polled device and also
  * for an input device associated with this polled device.
@@ -239,7 +239,7 @@ EXPORT_SYMBOL(input_free_polled_device);
  * with input layer. The device should be allocated with call to
  * input_allocate_polled_device(). Callers should also set up poll()
  * method and set up capabilities (id, name, phys, bits) of the
- * corresponing input_dev structure.
+ * corresponding input_dev structure.
  */
 int input_register_polled_device(struct input_polled_dev *dev)
 {
index 11905b6a30237c574825a178b16b8fde32d593dd..d6e8bd8a851c26d0e4718d10d30977451bb28009 100644 (file)
@@ -791,22 +791,9 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
        int retval;
 
        spin_lock_irqsave(&dev->event_lock, flags);
-
-       if (dev->getkeycode) {
-               /*
-                * Support for legacy drivers, that don't implement the new
-                * ioctls
-                */
-               u32 scancode = ke->index;
-
-               memcpy(ke->scancode, &scancode, sizeof(scancode));
-               ke->len = sizeof(scancode);
-               retval = dev->getkeycode(dev, scancode, &ke->keycode);
-       } else {
-               retval = dev->getkeycode_new(dev, ke);
-       }
-
+       retval = dev->getkeycode(dev, ke);
        spin_unlock_irqrestore(&dev->event_lock, flags);
+
        return retval;
 }
 EXPORT_SYMBOL(input_get_keycode);
@@ -831,35 +818,7 @@ int input_set_keycode(struct input_dev *dev,
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
-       if (dev->setkeycode) {
-               /*
-                * Support for legacy drivers, that don't implement the new
-                * ioctls
-                */
-               unsigned int scancode;
-
-               retval = input_scancode_to_scalar(ke, &scancode);
-               if (retval)
-                       goto out;
-
-               /*
-                * We need to know the old scancode, in order to generate a
-                * keyup effect, if the set operation happens successfully
-                */
-               if (!dev->getkeycode) {
-                       retval = -EINVAL;
-                       goto out;
-               }
-
-               retval = dev->getkeycode(dev, scancode, &old_keycode);
-               if (retval)
-                       goto out;
-
-               retval = dev->setkeycode(dev, scancode, ke->keycode);
-       } else {
-               retval = dev->setkeycode_new(dev, ke, &old_keycode);
-       }
-
+       retval = dev->setkeycode(dev, ke, &old_keycode);
        if (retval)
                goto out;
 
@@ -1846,11 +1805,11 @@ int input_register_device(struct input_dev *dev)
                dev->rep[REP_PERIOD] = 33;
        }
 
-       if (!dev->getkeycode && !dev->getkeycode_new)
-               dev->getkeycode_new = input_default_getkeycode;
+       if (!dev->getkeycode)
+               dev->getkeycode = input_default_getkeycode;
 
-       if (!dev->setkeycode && !dev->setkeycode_new)
-               dev->setkeycode_new = input_default_setkeycode;
+       if (!dev->setkeycode)
+               dev->setkeycode = input_default_setkeycode;
 
        dev_set_name(&dev->dev, "input%ld",
                     (unsigned long) atomic_inc_return(&input_no) - 1);
index c7a92028f450953b264ac6d8d950eeef9135c4a6..b16bed038f7245634aa3a6ffbbac45b40d168878 100644 (file)
@@ -112,6 +112,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
          right-hand column will be interpreted as the key shown in the
          left-hand column.
 
+config KEYBOARD_QT1070
+       tristate "Atmel AT42QT1070 Touch Sensor Chip"
+       depends on I2C
+       help
+         Say Y here if you want to use Atmel AT42QT1070 QTouch
+         Sensor chip as input device.
+
+         To compile this driver as a module, choose M here:
+         the module will be called qt1070
+
 config KEYBOARD_QT2160
        tristate "Atmel AT42QT2160 Touch Sensor Chip"
        depends on I2C && EXPERIMENTAL
index 468c627a28447efb78b9fb32b9a35351719d4f06..878e6c20deb0e1f231526e26846aedd1e1ce60d4 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_KEYBOARD_OMAP4)          += omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)       += opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
+obj-$(CONFIG_KEYBOARD_QT1070)           += qt1070.o
 obj-$(CONFIG_KEYBOARD_QT2160)          += qt2160.o
 obj-$(CONFIG_KEYBOARD_SAMSUNG)         += samsung-keypad.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)                += sh_keysc.o
index f7c2a166576b8cc161c1debb85639c8426906584..b732870ecc897a1465ad8645342b9ce60435beba 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/leds.h>
+#include <linux/pm.h>
 #include <linux/i2c/lm8323.h>
 #include <linux/slab.h>
 
@@ -802,8 +803,9 @@ static int __devexit lm8323_remove(struct i2c_client *client)
  * We don't need to explicitly suspend the chip, as it already switches off
  * when there's no activity.
  */
-static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lm8323_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct lm8323_chip *lm = i2c_get_clientdata(client);
        int i;
 
@@ -821,8 +823,9 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
        return 0;
 }
 
-static int lm8323_resume(struct i2c_client *client)
+static int lm8323_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct lm8323_chip *lm = i2c_get_clientdata(client);
        int i;
 
@@ -839,11 +842,10 @@ static int lm8323_resume(struct i2c_client *client)
 
        return 0;
 }
-#else
-#define lm8323_suspend NULL
-#define lm8323_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
+
 static const struct i2c_device_id lm8323_id[] = {
        { "lm8323", 0 },
        { }
@@ -852,11 +854,10 @@ static const struct i2c_device_id lm8323_id[] = {
 static struct i2c_driver lm8323_i2c_driver = {
        .driver = {
                .name   = "lm8323",
+               .pm     = &lm8323_pm_ops,
        },
        .probe          = lm8323_probe,
        .remove         = __devexit_p(lm8323_remove),
-       .suspend        = lm8323_suspend,
-       .resume         = lm8323_resume,
        .id_table       = lm8323_id,
 };
 MODULE_DEVICE_TABLE(i2c, lm8323_id);
index 9091ff5ea808b8829d7d9475f15f704532d10c5e..5afe35ad24d37b4ec3558cc5a07c20470e6f3ea8 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 
@@ -271,8 +272,10 @@ static int __devexit max7359_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int max7359_suspend(struct i2c_client *client, pm_message_t mesg)
+static int max7359_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
+
        max7359_fall_deepsleep(client);
 
        if (device_may_wakeup(&client->dev))
@@ -281,8 +284,10 @@ static int max7359_suspend(struct i2c_client *client, pm_message_t mesg)
        return 0;
 }
 
-static int max7359_resume(struct i2c_client *client)
+static int max7359_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
+
        if (device_may_wakeup(&client->dev))
                disable_irq_wake(client->irq);
 
@@ -291,11 +296,10 @@ static int max7359_resume(struct i2c_client *client)
 
        return 0;
 }
-#else
-#define max7359_suspend        NULL
-#define max7359_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
+
 static const struct i2c_device_id max7359_ids[] = {
        { "max7359", 0 },
        { }
@@ -305,11 +309,10 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids);
 static struct i2c_driver max7359_i2c_driver = {
        .driver = {
                .name = "max7359",
+               .pm   = &max7359_pm,
        },
        .probe          = max7359_probe,
        .remove         = __devexit_p(max7359_remove),
-       .suspend        = max7359_suspend,
-       .resume         = max7359_resume,
        .id_table       = max7359_ids,
 };
 
index 63b849d7e90b0fb9d2755ed6a1e9f0bf9975959f..af1aab324a4c58c0e011ea8660e483802db2ef41 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
+ * Touchkey driver for MELFAS MCS5000/5080 controller
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 /* MCS5000 Touchkey */
 #define MCS5000_TOUCHKEY_STATUS                0x04
@@ -45,6 +46,8 @@ struct mcs_touchkey_chip {
 };
 
 struct mcs_touchkey_data {
+       void (*poweron)(bool);
+
        struct i2c_client *client;
        struct input_dev *input_dev;
        struct mcs_touchkey_chip chip;
@@ -169,6 +172,11 @@ static int __devinit mcs_touchkey_probe(struct i2c_client *client,
        if (pdata->cfg_pin)
                pdata->cfg_pin();
 
+       if (pdata->poweron) {
+               data->poweron = pdata->poweron;
+               data->poweron(true);
+       }
+
        error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
                        IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
        if (error) {
@@ -196,12 +204,57 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client)
        struct mcs_touchkey_data *data = i2c_get_clientdata(client);
 
        free_irq(client->irq, data);
+       if (data->poweron)
+               data->poweron(false);
        input_unregister_device(data->input_dev);
        kfree(data);
 
        return 0;
 }
 
+static void mcs_touchkey_shutdown(struct i2c_client *client)
+{
+       struct mcs_touchkey_data *data = i2c_get_clientdata(client);
+
+       if (data->poweron)
+               data->poweron(false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mcs_touchkey_suspend(struct device *dev)
+{
+       struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+
+       /* Disable the work */
+       disable_irq(client->irq);
+
+       /* Finally turn off the power */
+       if (data->poweron)
+               data->poweron(false);
+
+       return 0;
+}
+
+static int mcs_touchkey_resume(struct device *dev)
+{
+       struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+
+       /* Enable the device first */
+       if (data->poweron)
+               data->poweron(true);
+
+       /* Enable irq again */
+       enable_irq(client->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
+                        mcs_touchkey_suspend, mcs_touchkey_resume);
+
 static const struct i2c_device_id mcs_touchkey_id[] = {
        { "mcs5000_touchkey", MCS5000_TOUCHKEY },
        { "mcs5080_touchkey", MCS5080_TOUCHKEY },
@@ -213,9 +266,11 @@ static struct i2c_driver mcs_touchkey_driver = {
        .driver = {
                .name   = "mcs_touchkey",
                .owner  = THIS_MODULE,
+               .pm     = &mcs_touchkey_pm_ops,
        },
        .probe          = mcs_touchkey_probe,
        .remove         = __devexit_p(mcs_touchkey_remove),
+       .shutdown       = mcs_touchkey_shutdown,
        .id_table       = mcs_touchkey_id,
 };
 
index 45bd0977d0066622d543a9d51cca96873536f8a9..c51a3c4a7feb52520246c332d93784a25fc70774 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/io.h>
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/omap4-keypad.h>
 
@@ -80,20 +81,6 @@ struct omap4_keypad {
        unsigned short keymap[];
 };
 
-static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
-{
-       __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
-                       keypad_data->base + OMAP4_KBD_CTRL);
-       __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
-                       keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
-       __raw_writel(OMAP4_VAL_IRQDISABLE,
-                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
-       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
-                       keypad_data->base + OMAP4_KBD_IRQENABLE);
-       __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
-                       keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
-}
-
 /* Interrupt handler */
 static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
 {
@@ -144,6 +131,49 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int omap4_keypad_open(struct input_dev *input)
+{
+       struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+       pm_runtime_get_sync(input->dev.parent);
+
+       disable_irq(keypad_data->irq);
+
+       __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
+                       keypad_data->base + OMAP4_KBD_CTRL);
+       __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
+                       keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+                       keypad_data->base + OMAP4_KBD_IRQENABLE);
+       __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
+                       keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+
+       enable_irq(keypad_data->irq);
+
+       return 0;
+}
+
+static void omap4_keypad_close(struct input_dev *input)
+{
+       struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+       disable_irq(keypad_data->irq);
+
+       /* Disable interrupts */
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                    keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+       /* clear pending interrupts */
+       __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+
+       enable_irq(keypad_data->irq);
+
+       pm_runtime_put_sync(input->dev.parent);
+}
+
 static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 {
        const struct omap4_keypad_platform_data *pdata;
@@ -225,6 +255,9 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0001;
 
+       input_dev->open = omap4_keypad_open;
+       input_dev->close = omap4_keypad_close;
+
        input_dev->keycode      = keypad_data->keymap;
        input_dev->keycodesize  = sizeof(keypad_data->keymap[0]);
        input_dev->keycodemax   = max_keys;
@@ -239,8 +272,6 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
        matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
                        input_dev->keycode, input_dev->keybit);
 
-       omap4_keypad_config(keypad_data);
-
        error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
                             IRQF_TRIGGER_RISING,
                             "omap4-keypad", keypad_data);
@@ -249,17 +280,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
                goto err_free_input;
        }
 
+       pm_runtime_enable(&pdev->dev);
+
        error = input_register_device(keypad_data->input);
        if (error < 0) {
                dev_err(&pdev->dev, "failed to register input device\n");
-               goto err_free_irq;
+               goto err_pm_disable;
        }
 
-
        platform_set_drvdata(pdev, keypad_data);
        return 0;
 
-err_free_irq:
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
        free_irq(keypad_data->irq, keypad_data);
 err_free_input:
        input_free_device(input_dev);
@@ -278,6 +311,9 @@ static int __devexit omap4_keypad_remove(struct platform_device *pdev)
        struct resource *res;
 
        free_irq(keypad_data->irq, keypad_data);
+
+       pm_runtime_disable(&pdev->dev);
+
        input_unregister_device(keypad_data->input);
 
        iounmap(keypad_data->base);
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
new file mode 100644 (file)
index 0000000..fba8404
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ *  Atmel AT42QT1070 QTouch Sensor Controller
+ *
+ *  Copyright (C) 2011 Atmel
+ *
+ *  Authors: Bo Shen <voice.shen@atmel.com>
+ *
+ *  Base on AT42QT2160 driver by:
+ *  Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *  Copyright (C) 2009
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+/* Address for each register */
+#define CHIP_ID            0x00
+#define QT1070_CHIP_ID     0x2E
+
+#define FW_VERSION         0x01
+#define QT1070_FW_VERSION  0x15
+
+#define DET_STATUS         0x02
+
+#define KEY_STATUS         0x03
+
+/* Calibrate */
+#define CALIBRATE_CMD      0x38
+#define QT1070_CAL_TIME    200
+
+/* Reset */
+#define RESET              0x39
+#define QT1070_RESET_TIME  255
+
+/* AT42QT1070 support up to 7 keys */
+static const unsigned short qt1070_key2code[] = {
+       KEY_0, KEY_1, KEY_2, KEY_3,
+       KEY_4, KEY_5, KEY_6,
+};
+
+struct qt1070_data {
+       struct i2c_client *client;
+       struct input_dev *input;
+       unsigned int irq;
+       unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)];
+       u8 last_keys;
+};
+
+static int qt1070_read(struct i2c_client *client, u8 reg)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       if (ret < 0)
+               dev_err(&client->dev,
+                       "can not read register, returned %d\n", ret);
+
+       return ret;
+}
+
+static int qt1070_write(struct i2c_client *client, u8 reg, u8 data)
+{
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(client, reg, data);
+       if (ret < 0)
+               dev_err(&client->dev,
+                       "can not write register, returned %d\n", ret);
+
+       return ret;
+}
+
+static bool __devinit qt1070_identify(struct i2c_client *client)
+{
+       int id, ver;
+
+       /* Read Chip ID */
+       id = qt1070_read(client, CHIP_ID);
+       if (id != QT1070_CHIP_ID) {
+               dev_err(&client->dev, "ID %d not supported\n", id);
+               return false;
+       }
+
+       /* Read firmware version */
+       ver = qt1070_read(client, FW_VERSION);
+       if (ver < 0) {
+               dev_err(&client->dev, "could not read the firmware version\n");
+               return false;
+       }
+
+       dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver);
+
+       return true;
+}
+
+static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
+{
+       struct qt1070_data *data = dev_id;
+       struct i2c_client *client = data->client;
+       struct input_dev *input = data->input;
+       int i;
+       u8 new_keys, keyval, mask = 0x01;
+
+       /* Read the detected status register, thus clearing interrupt */
+       qt1070_read(client, DET_STATUS);
+
+       /* Read which key changed */
+       new_keys = qt1070_read(client, KEY_STATUS);
+
+       for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+               keyval = new_keys & mask;
+               if ((data->last_keys & mask) != keyval)
+                       input_report_key(input, data->keycodes[i], keyval);
+               mask <<= 1;
+       }
+       input_sync(input);
+
+       data->last_keys = new_keys;
+       return IRQ_HANDLED;
+}
+
+static int __devinit qt1070_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct qt1070_data *data;
+       struct input_dev *input;
+       int i;
+       int err;
+
+       err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
+       if (!err) {
+               dev_err(&client->dev, "%s adapter not supported\n",
+                       dev_driver_string(&client->adapter->dev));
+               return -ENODEV;
+       }
+
+       if (!client->irq) {
+               dev_err(&client->dev, "please assign the irq to this device\n");
+               return -EINVAL;
+       }
+
+       /* Identify the qt1070 chip */
+       if (!qt1070_identify(client))
+               return -ENODEV;
+
+       data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!data || !input) {
+               dev_err(&client->dev, "insufficient memory\n");
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       data->client = client;
+       data->input = input;
+       data->irq = client->irq;
+
+       input->name = "AT42QT1070 QTouch Sensor";
+       input->dev.parent = &client->dev;
+       input->id.bustype = BUS_I2C;
+
+       /* Add the keycode */
+       input->keycode = data->keycodes;
+       input->keycodesize = sizeof(data->keycodes[0]);
+       input->keycodemax = ARRAY_SIZE(qt1070_key2code);
+
+       __set_bit(EV_KEY, input->evbit);
+
+       for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+               data->keycodes[i] = qt1070_key2code[i];
+               __set_bit(qt1070_key2code[i], input->keybit);
+       }
+
+       /* Calibrate device */
+       qt1070_write(client, CALIBRATE_CMD, 1);
+       msleep(QT1070_CAL_TIME);
+
+       /* Soft reset */
+       qt1070_write(client, RESET, 1);
+       msleep(QT1070_RESET_TIME);
+
+       err = request_threaded_irq(client->irq, NULL, qt1070_interrupt,
+               IRQF_TRIGGER_NONE, client->dev.driver->name, data);
+       if (err) {
+               dev_err(&client->dev, "fail to request irq\n");
+               goto err_free_mem;
+       }
+
+       /* Register the input device */
+       err = input_register_device(data->input);
+       if (err) {
+               dev_err(&client->dev, "Failed to register input device\n");
+               goto err_free_irq;
+       }
+
+       i2c_set_clientdata(client, data);
+
+       /* Read to clear the chang line */
+       qt1070_read(client, DET_STATUS);
+
+       return 0;
+
+err_free_irq:
+       free_irq(client->irq, data);
+err_free_mem:
+       input_free_device(input);
+       kfree(data);
+       return err;
+}
+
+static int __devexit qt1070_remove(struct i2c_client *client)
+{
+       struct qt1070_data *data = i2c_get_clientdata(client);
+
+       /* Release IRQ */
+       free_irq(client->irq, data);
+
+       input_unregister_device(data->input);
+       kfree(data);
+
+       i2c_set_clientdata(client, NULL);
+
+       return 0;
+}
+
+static const struct i2c_device_id qt1070_id[] = {
+       { "qt1070", 0 },
+       { },
+};
+
+static struct i2c_driver qt1070_driver = {
+       .driver = {
+               .name   = "qt1070",
+               .owner  = THIS_MODULE,
+       },
+       .id_table       = qt1070_id,
+       .probe          = qt1070_probe,
+       .remove         = __devexit_p(qt1070_remove),
+};
+
+static int __init qt1070_init(void)
+{
+       return i2c_add_driver(&qt1070_driver);
+}
+module_init(qt1070_init);
+
+static void __exit qt1070_exit(void)
+{
+       i2c_del_driver(&qt1070_driver);
+}
+module_exit(qt1070_exit);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor");
+MODULE_LICENSE("GPL");
index dbbe761778d28e2815182ed023bf5d196f842b27..99122f59e98822d8620cec91c2ea4942e427269b 100644 (file)
@@ -402,7 +402,7 @@ static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int tc3589x_keypad_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -439,19 +439,19 @@ static int tc3589x_keypad_resume(struct device *dev)
 
        return 0;
 }
-
-static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
-                              tc3589x_keypad_suspend, tc3589x_keypad_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+                        tc3589x_keypad_suspend, tc3589x_keypad_resume);
+
 static struct platform_driver tc3589x_keypad_driver = {
-       .driver.name  = "tc3589x-keypad",
-       .driver.owner = THIS_MODULE,
-#ifdef CONFIG_PM
-       .driver.pm = &tc3589x_keypad_dev_pm_ops,
-#endif
-       .probe = tc3589x_keypad_probe,
-       .remove = __devexit_p(tc3589x_keypad_remove),
+       .driver = {
+               .name   = "tc3589x-keypad",
+               .owner  = THIS_MODULE,
+               .pm     = &tc3589x_keypad_dev_pm_ops,
+       },
+       .probe  = tc3589x_keypad_probe,
+       .remove = __devexit_p(tc3589x_keypad_remove),
 };
 
 static int __init tc3589x_keypad_init(void)
index 800fbccf1f0fb714017cefb47320829753b0f839..3afea3f897182adba5c1439dc38e7a34126fa440 100644 (file)
@@ -297,6 +297,7 @@ static int __devinit tca6416_keypad_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, chip);
+       device_init_wakeup(&client->dev, 1);
 
        return 0;
 
@@ -326,10 +327,37 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tca6416_keypad_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(chip->irqnum);
+
+       return 0;
+}
+
+static int tca6416_keypad_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(chip->irqnum);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops,
+                        tca6416_keypad_suspend, tca6416_keypad_resume);
 
 static struct i2c_driver tca6416_keypad_driver = {
        .driver = {
                .name   = "tca6416-keypad",
+               .pm     = &tca6416_keypad_dev_pm_ops,
        },
        .probe          = tca6416_keypad_probe,
        .remove         = __devexit_p(tca6416_keypad_remove),
index b0c6772851a99496727663941e092b46f81482e3..f9cf0881b0e3cf386a3e606d462aebf4bacd5575 100644 (file)
@@ -454,4 +454,17 @@ config INPUT_CMA3000_I2C
          To compile this driver as a module, choose M here: the
          module will be called cma3000_d0x_i2c.
 
+config INPUT_XEN_KBDDEV_FRONTEND
+       tristate "Xen virtual keyboard and mouse support"
+       depends on XEN_FBDEV_FRONTEND
+       default y
+       select XEN_XENBUS_FRONTEND
+       help
+         This driver implements the front-end of the Xen virtual
+         keyboard and mouse device driver.  It communicates with a back-end
+         in another domain.
+
+         To compile this driver as a module, choose M here: the
+         module will be called xen-kbdfront.
+
 endif
index 9b4797112c9ac14955ff7afb0b84ab616e613a89..e3f7984e627427ead449de2d6e6452d3aac1c915 100644 (file)
@@ -42,5 +42,6 @@ obj-$(CONFIG_INPUT_TWL4030_VIBRA)     += twl4030-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)       += wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)          += wm831x-on.o
+obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)        += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
 
index 2bef8fa56c948e0ba4305ea0f4f22450244f79d4..e21deb1baa8abfb193d46702023540e2d09a41ca 100644 (file)
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "ad714x.h"
 
 #ifdef CONFIG_PM
-static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int ad714x_i2c_suspend(struct device *dev)
 {
-       return ad714x_disable(i2c_get_clientdata(client));
+       return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
 }
 
-static int ad714x_i2c_resume(struct i2c_client *client)
+static int ad714x_i2c_resume(struct device *dev)
 {
-       return ad714x_enable(i2c_get_clientdata(client));
+       return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev)));
 }
-#else
-# define ad714x_i2c_suspend NULL
-# define ad714x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);
+
 static int ad714x_i2c_write(struct device *dev, unsigned short reg,
                                unsigned short data)
 {
@@ -114,11 +114,10 @@ MODULE_DEVICE_TABLE(i2c, ad714x_id);
 static struct i2c_driver ad714x_i2c_driver = {
        .driver = {
                .name = "ad714x_captouch",
+               .pm   = &ad714x_i2c_pm,
        },
        .probe    = ad714x_i2c_probe,
        .remove   = __devexit_p(ad714x_i2c_remove),
-       .suspend  = ad714x_i2c_suspend,
-       .resume   = ad714x_i2c_resume,
        .id_table = ad714x_id,
 };
 
index 7f8dedfd1bfeed3db41403e560dc55b16a32f907..4120dd5493059126b272256b47eba121044e396d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/input.h>       /* BUS_I2C */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "ad714x.h"
 
 #define AD714x_SPI_READ            BIT(10)
 
 #ifdef CONFIG_PM
-static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int ad714x_spi_suspend(struct device *dev)
 {
-       return ad714x_disable(spi_get_drvdata(spi));
+       return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
 }
 
-static int ad714x_spi_resume(struct spi_device *spi)
+static int ad714x_spi_resume(struct device *dev)
 {
-       return ad714x_enable(spi_get_drvdata(spi));
+       return ad714x_enable(spi_get_drvdata(to_spi_device(dev)));
 }
-#else
-# define ad714x_spi_suspend NULL
-# define ad714x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);
+
 static int ad714x_spi_read(struct device *dev, unsigned short reg,
                unsigned short *data)
 {
@@ -79,11 +79,10 @@ static struct spi_driver ad714x_spi_driver = {
        .driver = {
                .name   = "ad714x_captouch",
                .owner  = THIS_MODULE,
+               .pm     = &ad714x_spi_pm,
        },
        .probe          = ad714x_spi_probe,
        .remove         = __devexit_p(ad714x_spi_remove),
-       .suspend        = ad714x_spi_suspend,
-       .resume         = ad714x_spi_resume,
 };
 
 static __init int ad714x_spi_init(void)
index 0779724af7e79b8f34d6857c15793f09d7080b60..ccacf2bb06a4e56c74624dab181ac6398ab56bcc 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "adxl34x.h"
 
 static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
@@ -105,8 +106,9 @@ static int __devexit adxl34x_i2c_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int adxl34x_i2c_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct adxl34x *ac = i2c_get_clientdata(client);
 
        adxl34x_suspend(ac);
@@ -114,19 +116,20 @@ static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
        return 0;
 }
 
-static int adxl34x_i2c_resume(struct i2c_client *client)
+static int adxl34x_i2c_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct adxl34x *ac = i2c_get_clientdata(client);
 
        adxl34x_resume(ac);
 
        return 0;
 }
-#else
-# define adxl34x_i2c_suspend NULL
-# define adxl34x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
+                        adxl34x_i2c_resume);
+
 static const struct i2c_device_id adxl34x_id[] = {
        { "adxl34x", 0 },
        { }
@@ -138,11 +141,10 @@ static struct i2c_driver adxl34x_driver = {
        .driver = {
                .name = "adxl34x",
                .owner = THIS_MODULE,
+               .pm = &adxl34x_i2c_pm,
        },
        .probe    = adxl34x_i2c_probe,
        .remove   = __devexit_p(adxl34x_i2c_remove),
-       .suspend  = adxl34x_i2c_suspend,
-       .resume   = adxl34x_i2c_resume,
        .id_table = adxl34x_id,
 };
 
index 782de9e898287b4905291a26305eb049a04fcac1..f29de22fdda054b7fed385ea0abe957e2cda5570 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/input.h>       /* BUS_SPI */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "adxl34x.h"
 
@@ -57,7 +58,7 @@ static int adxl34x_spi_read_block(struct device *dev,
        return (status < 0) ? status : 0;
 }
 
-static const struct adxl34x_bus_ops adx134x_spi_bops = {
+static const struct adxl34x_bus_ops adxl34x_spi_bops = {
        .bustype        = BUS_SPI,
        .write          = adxl34x_spi_write,
        .read           = adxl34x_spi_read,
@@ -76,7 +77,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi)
 
        ac = adxl34x_probe(&spi->dev, spi->irq,
                           spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY,
-                          &adx134x_spi_bops);
+                          &adxl34x_spi_bops);
 
        if (IS_ERR(ac))
                return PTR_ERR(ac);
@@ -94,8 +95,9 @@ static int __devexit adxl34x_spi_remove(struct spi_device *spi)
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int adxl34x_spi_suspend(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
        adxl34x_suspend(ac);
@@ -103,29 +105,29 @@ static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
        return 0;
 }
 
-static int adxl34x_spi_resume(struct spi_device *spi)
+static int adxl34x_spi_resume(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
        adxl34x_resume(ac);
 
        return 0;
 }
-#else
-# define adxl34x_spi_suspend NULL
-# define adxl34x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
+                        adxl34x_spi_resume);
+
 static struct spi_driver adxl34x_driver = {
        .driver = {
                .name = "adxl34x",
                .bus = &spi_bus_type,
                .owner = THIS_MODULE,
+               .pm = &adxl34x_spi_pm,
        },
        .probe   = adxl34x_spi_probe,
        .remove  = __devexit_p(adxl34x_spi_remove),
-       .suspend = adxl34x_spi_suspend,
-       .resume  = adxl34x_spi_resume,
 };
 
 static int __init adxl34x_spi_init(void)
index 0b0e9be6354215319200a8a305c9db55e8b4c3dd..9ccdb82d869a09245c80bf125a99c5fcac5cffd7 100644 (file)
@@ -612,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->open = ati_remote2_open;
        idev->close = ati_remote2_close;
 
-       idev->getkeycode_new = ati_remote2_getkeycode;
-       idev->setkeycode_new = ati_remote2_setkeycode;
+       idev->getkeycode = ati_remote2_getkeycode;
+       idev->setkeycode = ati_remote2_setkeycode;
 
        idev->name = ar2->name;
        idev->phys = ar2->phys;
index 82542a1c1098fb00c3d33769a21088f3f7eccd05..364bdf43a381d8a052c730eb38eb005c0f006c0c 100644 (file)
@@ -347,8 +347,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 {
        struct uinput_user_dev  *user_dev;
        struct input_dev        *dev;
-       char                    *name;
-       int                     i, size;
+       int                     i;
        int                     retval;
 
        if (count != sizeof(struct uinput_user_dev))
@@ -362,30 +361,25 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 
        dev = udev->dev;
 
-       user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
-       if (!user_dev)
-               return -ENOMEM;
-
-       if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
-               retval = -EFAULT;
-               goto exit;
-       }
+       user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
+       if (IS_ERR(user_dev))
+               return PTR_ERR(user_dev);
 
        udev->ff_effects_max = user_dev->ff_effects_max;
 
-       size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
-       if (!size) {
+       /* Ensure name is filled in */
+       if (!user_dev->name[0]) {
                retval = -EINVAL;
                goto exit;
        }
 
        kfree(dev->name);
-       dev->name = name = kmalloc(size, GFP_KERNEL);
-       if (!name) {
+       dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
+                            GFP_KERNEL);
+       if (!dev->name) {
                retval = -ENOMEM;
                goto exit;
        }
-       strlcpy(name, user_dev->name, size);
 
        dev->id.bustype = user_dev->id.bustype;
        dev->id.vendor  = user_dev->id.vendor;
@@ -622,7 +616,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
        struct uinput_ff_upload ff_up;
        struct uinput_ff_erase  ff_erase;
        struct uinput_request   *req;
-       int                     length;
        char                    *phys;
 
        retval = mutex_lock_interruptible(&udev->mutex);
@@ -689,24 +682,15 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
                                retval = -EINVAL;
                                goto out;
                        }
-                       length = strnlen_user(p, 1024);
-                       if (length <= 0) {
-                               retval = -EFAULT;
-                               break;
+
+                       phys = strndup_user(p, 1024);
+                       if (IS_ERR(phys)) {
+                               retval = PTR_ERR(phys);
+                               goto out;
                        }
+
                        kfree(udev->dev->phys);
-                       udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
-                       if (!phys) {
-                               retval = -ENOMEM;
-                               break;
-                       }
-                       if (copy_from_user(phys, p, length)) {
-                               udev->dev->phys = NULL;
-                               kfree(phys);
-                               retval = -EFAULT;
-                               break;
-                       }
-                       phys[length - 1] = '\0';
+                       udev->dev->phys = phys;
                        break;
 
                case UI_BEGIN_FF_UPLOAD:
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
new file mode 100644 (file)
index 0000000..7077f9b
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Xen para-virtual input device
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/kbdif.h>
+#include <xen/xenbus.h>
+
+struct xenkbd_info {
+       struct input_dev *kbd;
+       struct input_dev *ptr;
+       struct xenkbd_page *page;
+       int gref;
+       int irq;
+       struct xenbus_device *xbdev;
+       char phys[32];
+};
+
+static int xenkbd_remove(struct xenbus_device *);
+static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+/*
+ * Note: if you need to send out events, see xenfb_do_update() for how
+ * to do that.
+ */
+
+static irqreturn_t input_handler(int rq, void *dev_id)
+{
+       struct xenkbd_info *info = dev_id;
+       struct xenkbd_page *page = info->page;
+       __u32 cons, prod;
+
+       prod = page->in_prod;
+       if (prod == page->in_cons)
+               return IRQ_HANDLED;
+       rmb();                  /* ensure we see ring contents up to prod */
+       for (cons = page->in_cons; cons != prod; cons++) {
+               union xenkbd_in_event *event;
+               struct input_dev *dev;
+               event = &XENKBD_IN_RING_REF(page, cons);
+
+               dev = info->ptr;
+               switch (event->type) {
+               case XENKBD_TYPE_MOTION:
+                       input_report_rel(dev, REL_X, event->motion.rel_x);
+                       input_report_rel(dev, REL_Y, event->motion.rel_y);
+                       if (event->motion.rel_z)
+                               input_report_rel(dev, REL_WHEEL,
+                                                -event->motion.rel_z);
+                       break;
+               case XENKBD_TYPE_KEY:
+                       dev = NULL;
+                       if (test_bit(event->key.keycode, info->kbd->keybit))
+                               dev = info->kbd;
+                       if (test_bit(event->key.keycode, info->ptr->keybit))
+                               dev = info->ptr;
+                       if (dev)
+                               input_report_key(dev, event->key.keycode,
+                                                event->key.pressed);
+                       else
+                               pr_warning("unhandled keycode 0x%x\n",
+                                          event->key.keycode);
+                       break;
+               case XENKBD_TYPE_POS:
+                       input_report_abs(dev, ABS_X, event->pos.abs_x);
+                       input_report_abs(dev, ABS_Y, event->pos.abs_y);
+                       if (event->pos.rel_z)
+                               input_report_rel(dev, REL_WHEEL,
+                                                -event->pos.rel_z);
+                       break;
+               }
+               if (dev)
+                       input_sync(dev);
+       }
+       mb();                   /* ensure we got ring contents */
+       page->in_cons = cons;
+       notify_remote_via_irq(info->irq);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit xenkbd_probe(struct xenbus_device *dev,
+                                 const struct xenbus_device_id *id)
+{
+       int ret, i, abs;
+       struct xenkbd_info *info;
+       struct input_dev *kbd, *ptr;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+               return -ENOMEM;
+       }
+       dev_set_drvdata(&dev->dev, info);
+       info->xbdev = dev;
+       info->irq = -1;
+       info->gref = -1;
+       snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+
+       info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+       if (!info->page)
+               goto error_nomem;
+
+       if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
+               abs = 0;
+       if (abs)
+               xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+
+       /* keyboard */
+       kbd = input_allocate_device();
+       if (!kbd)
+               goto error_nomem;
+       kbd->name = "Xen Virtual Keyboard";
+       kbd->phys = info->phys;
+       kbd->id.bustype = BUS_PCI;
+       kbd->id.vendor = 0x5853;
+       kbd->id.product = 0xffff;
+
+       __set_bit(EV_KEY, kbd->evbit);
+       for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
+               __set_bit(i, kbd->keybit);
+       for (i = KEY_OK; i < KEY_MAX; i++)
+               __set_bit(i, kbd->keybit);
+
+       ret = input_register_device(kbd);
+       if (ret) {
+               input_free_device(kbd);
+               xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
+               goto error;
+       }
+       info->kbd = kbd;
+
+       /* pointing device */
+       ptr = input_allocate_device();
+       if (!ptr)
+               goto error_nomem;
+       ptr->name = "Xen Virtual Pointer";
+       ptr->phys = info->phys;
+       ptr->id.bustype = BUS_PCI;
+       ptr->id.vendor = 0x5853;
+       ptr->id.product = 0xfffe;
+
+       if (abs) {
+               __set_bit(EV_ABS, ptr->evbit);
+               input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+               input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+       } else {
+               input_set_capability(ptr, EV_REL, REL_X);
+               input_set_capability(ptr, EV_REL, REL_Y);
+       }
+       input_set_capability(ptr, EV_REL, REL_WHEEL);
+
+       __set_bit(EV_KEY, ptr->evbit);
+       for (i = BTN_LEFT; i <= BTN_TASK; i++)
+               __set_bit(i, ptr->keybit);
+
+       ret = input_register_device(ptr);
+       if (ret) {
+               input_free_device(ptr);
+               xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
+               goto error;
+       }
+       info->ptr = ptr;
+
+       ret = xenkbd_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+ error_nomem:
+       ret = -ENOMEM;
+       xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+       xenkbd_remove(dev);
+       return ret;
+}
+
+static int xenkbd_resume(struct xenbus_device *dev)
+{
+       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+       xenkbd_disconnect_backend(info);
+       memset(info->page, 0, PAGE_SIZE);
+       return xenkbd_connect_backend(dev, info);
+}
+
+static int xenkbd_remove(struct xenbus_device *dev)
+{
+       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+       xenkbd_disconnect_backend(info);
+       if (info->kbd)
+               input_unregister_device(info->kbd);
+       if (info->ptr)
+               input_unregister_device(info->ptr);
+       free_page((unsigned long)info->page);
+       kfree(info);
+       return 0;
+}
+
+static int xenkbd_connect_backend(struct xenbus_device *dev,
+                                 struct xenkbd_info *info)
+{
+       int ret, evtchn;
+       struct xenbus_transaction xbt;
+
+       ret = gnttab_grant_foreign_access(dev->otherend_id,
+                                         virt_to_mfn(info->page), 0);
+       if (ret < 0)
+               return ret;
+       info->gref = ret;
+
+       ret = xenbus_alloc_evtchn(dev, &evtchn);
+       if (ret)
+               goto error_grant;
+       ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
+                                       0, dev->devicetype, info);
+       if (ret < 0) {
+               xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+               goto error_evtchan;
+       }
+       info->irq = ret;
+
+ again:
+       ret = xenbus_transaction_start(&xbt);
+       if (ret) {
+               xenbus_dev_fatal(dev, ret, "starting transaction");
+               goto error_irqh;
+       }
+       ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+                           virt_to_mfn(info->page));
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+                           evtchn);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_transaction_end(xbt, 0);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       goto again;
+               xenbus_dev_fatal(dev, ret, "completing transaction");
+               goto error_irqh;
+       }
+
+       xenbus_switch_state(dev, XenbusStateInitialised);
+       return 0;
+
+ error_xenbus:
+       xenbus_transaction_end(xbt, 1);
+       xenbus_dev_fatal(dev, ret, "writing xenstore");
+ error_irqh:
+       unbind_from_irqhandler(info->irq, info);
+       info->irq = -1;
+ error_evtchan:
+       xenbus_free_evtchn(dev, evtchn);
+ error_grant:
+       gnttab_end_foreign_access_ref(info->gref, 0);
+       info->gref = -1;
+       return ret;
+}
+
+static void xenkbd_disconnect_backend(struct xenkbd_info *info)
+{
+       if (info->irq >= 0)
+               unbind_from_irqhandler(info->irq, info);
+       info->irq = -1;
+       if (info->gref >= 0)
+               gnttab_end_foreign_access_ref(info->gref, 0);
+       info->gref = -1;
+}
+
+static void xenkbd_backend_changed(struct xenbus_device *dev,
+                                  enum xenbus_state backend_state)
+{
+       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+       int val;
+
+       switch (backend_state) {
+       case XenbusStateInitialising:
+       case XenbusStateInitialised:
+       case XenbusStateReconfiguring:
+       case XenbusStateReconfigured:
+       case XenbusStateUnknown:
+       case XenbusStateClosed:
+               break;
+
+       case XenbusStateInitWait:
+InitWait:
+               xenbus_switch_state(dev, XenbusStateConnected);
+               break;
+
+       case XenbusStateConnected:
+               /*
+                * Work around xenbus race condition: If backend goes
+                * through InitWait to Connected fast enough, we can
+                * get Connected twice here.
+                */
+               if (dev->state != XenbusStateConnected)
+                       goto InitWait; /* no InitWait seen yet, fudge it */
+
+               /* Set input abs params to match backend screen res */
+               if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                "width", "%d", &val) > 0)
+                       input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
+
+               if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                "height", "%d", &val) > 0)
+                       input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
+
+               break;
+
+       case XenbusStateClosing:
+               xenbus_frontend_closed(dev);
+               break;
+       }
+}
+
+static const struct xenbus_device_id xenkbd_ids[] = {
+       { "vkbd" },
+       { "" }
+};
+
+static struct xenbus_driver xenkbd_driver = {
+       .name = "vkbd",
+       .owner = THIS_MODULE,
+       .ids = xenkbd_ids,
+       .probe = xenkbd_probe,
+       .remove = xenkbd_remove,
+       .resume = xenkbd_resume,
+       .otherend_changed = xenkbd_backend_changed,
+};
+
+static int __init xenkbd_init(void)
+{
+       if (!xen_pv_domain())
+               return -ENODEV;
+
+       /* Nothing to do if running in dom0. */
+       if (xen_initial_domain())
+               return -ENODEV;
+
+       return xenbus_register_frontend(&xenkbd_driver);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+       xenbus_unregister_driver(&xenkbd_driver);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vkbd");
index ee82851afe3ee9a660873b59d5fcb8cf39181ca7..3aead91bacc851d283458a2f48064ab36ec01320 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI  0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO   0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS   0x0244
+/* Macbook8 (unibody, March 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI   0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO    0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS    0x0247
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -96,6 +100,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
+       /* MacbookPro8 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
        /* Terminating entry */
        {}
 };
@@ -274,6 +282,18 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { DIM_X, DIM_X / SN_COORD, -4616, 5112 },
                { DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING5_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+               { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+               { DIM_X, DIM_X / SN_COORD, -4415, 5050 },
+               { DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+       },
        {}
 };
 
@@ -430,10 +450,6 @@ static int report_tp_state(struct bcm5974 *dev, int size)
                ptest = int2bound(&c->p, raw_p);
                origin = raw2int(f->origin);
 
-               /* set the integrated button if applicable */
-               if (c->tp_type == TYPE2)
-                       ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
-
                /* while tracking finger still valid, count all fingers */
                if (ptest > PRESSURE_LOW && origin) {
                        abs_p = ptest;
@@ -452,6 +468,10 @@ static int report_tp_state(struct bcm5974 *dev, int size)
                }
        }
 
+       /* set the integrated button if applicable */
+       if (c->tp_type == TYPE2)
+               ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
+
        if (dev->fingers < nmin)
                dev->fingers = nmin;
        if (dev->fingers > nmax)
index 0ae62f0bcb3216ca32c494e3a807a75a8f6753bd..f6aa26d305edd4e4922517610fbd8437aab62367 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 #define DRIVER_NAME            "synaptics_i2c"
 /* maximum product id is 15 characters */
@@ -619,8 +620,9 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int synaptics_i2c_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
        cancel_delayed_work_sync(&touch->dwork);
@@ -631,9 +633,10 @@ static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
        return 0;
 }
 
-static int synaptics_i2c_resume(struct i2c_client *client)
+static int synaptics_i2c_resume(struct device *dev)
 {
        int ret;
+       struct i2c_client *client = to_i2c_client(dev);
        struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
        ret = synaptics_i2c_reset_config(client);
@@ -645,11 +648,11 @@ static int synaptics_i2c_resume(struct i2c_client *client)
 
        return 0;
 }
-#else
-#define synaptics_i2c_suspend  NULL
-#define synaptics_i2c_resume   NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
+                        synaptics_i2c_resume);
+
 static const struct i2c_device_id synaptics_i2c_id_table[] = {
        { "synaptics_i2c", 0 },
        { },
@@ -660,13 +663,12 @@ static struct i2c_driver synaptics_i2c_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .pm     = &synaptics_i2c_pm,
        },
 
        .probe          = synaptics_i2c_probe,
        .remove         = __devexit_p(synaptics_i2c_remove),
 
-       .suspend        = synaptics_i2c_suspend,
-       .resume         = synaptics_i2c_resume,
        .id_table       = synaptics_i2c_id_table,
 };
 
index 7729e547ba65d853581e115a4ce6428883549ecd..337bf51bc984253abf9a77b558eb36c8c10deb53 100644 (file)
@@ -210,8 +210,8 @@ int sparse_keymap_setup(struct input_dev *dev,
 
        dev->keycode = map;
        dev->keycodemax = map_size;
-       dev->getkeycode_new = sparse_keymap_getkeycode;
-       dev->setkeycode_new = sparse_keymap_setkeycode;
+       dev->getkeycode = sparse_keymap_getkeycode;
+       dev->setkeycode = sparse_keymap_setkeycode;
 
        return 0;
 
index cf8fb9f5d4a8282f9405736af668d5f8cd423a4b..449c0a46dbac51ba881ba49b8cfff1c3861dfee7 100644 (file)
@@ -193,16 +193,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                        case HID_USAGE_X:
                                if (usage == WCM_DESKTOP) {
                                        if (finger) {
-                                               features->device_type = BTN_TOOL_DOUBLETAP;
+                                               features->device_type = BTN_TOOL_FINGER;
                                                if (features->type == TABLETPC2FG) {
                                                        /* need to reset back */
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
-                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->device_type = BTN_TOOL_DOUBLETAP;
                                                }
                                                if (features->type == BAMBOO_PT) {
                                                        /* need to reset back */
                                                        features->pktlen = WACOM_PKGLEN_BBTOUCH;
-                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->device_type = BTN_TOOL_DOUBLETAP;
                                                        features->x_phy =
                                                                get_unaligned_le16(&report[i + 5]);
                                                        features->x_max =
@@ -241,11 +241,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                        case HID_USAGE_Y:
                                if (usage == WCM_DESKTOP) {
                                        if (finger) {
-                                               features->device_type = BTN_TOOL_DOUBLETAP;
+                                               features->device_type = BTN_TOOL_FINGER;
                                                if (features->type == TABLETPC2FG) {
                                                        /* need to reset back */
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
-                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->device_type = BTN_TOOL_DOUBLETAP;
                                                        features->y_max =
                                                                get_unaligned_le16(&report[i + 3]);
                                                        features->y_phy =
@@ -254,7 +254,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                } else if (features->type == BAMBOO_PT) {
                                                        /* need to reset back */
                                                        features->pktlen = WACOM_PKGLEN_BBTOUCH;
-                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->device_type = BTN_TOOL_DOUBLETAP;
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 3]);
                                                        features->y_max =
index 367fa82a607e81ef8bf03d7b69c8bc231736fc65..5597637cfd41895181176f627f072ac3f0c39a77 100644 (file)
@@ -675,169 +675,87 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
        return 1;
 }
 
-
-static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
+static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       int finger = idx + 1;
-       int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff;
-       int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff;
+       unsigned char *data = wacom->data;
+       int contact_with_no_pen_down_count = 0;
+       int i;
 
-       /*
-        * Work around input core suppressing "duplicate" events since
-        * we are abusing ABS_X/ABS_Y to transmit multi-finger data.
-        * This should go away once we switch to true multitouch
-        * protocol.
-        */
-       if (wacom->last_finger != finger) {
-               if (x == input_abs_get_val(input, ABS_X))
-                       x++;
+       for (i = 0; i < 2; i++) {
+               int p = data[1] & (1 << i);
+               bool touch = p && !wacom->shared->stylus_in_proximity;
+
+               input_mt_slot(input, i);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+               if (touch) {
+                       int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
+                       int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
 
-               if (y == input_abs_get_val(input, ABS_Y))
-                       y++;
+                       input_report_abs(input, ABS_MT_POSITION_X, x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, y);
+                       contact_with_no_pen_down_count++;
+               }
        }
 
-       input_report_abs(input, ABS_X, x);
-       input_report_abs(input, ABS_Y, y);
-       input_report_abs(input, ABS_MISC, wacom->id[0]);
-       input_report_key(input, wacom->tool[finger], 1);
-       if (!idx)
-               input_report_key(input, BTN_TOUCH, 1);
-       input_event(input, EV_MSC, MSC_SERIAL, finger);
-       input_sync(input);
+       /* keep touch state for pen event */
+       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
 
-       wacom->last_finger = finger;
-}
+       input_mt_report_pointer_emulation(input, true);
 
-static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx)
-{
-       struct input_dev *input = wacom->input;
-       int finger = idx + 1;
-
-       input_report_abs(input, ABS_X, 0);
-       input_report_abs(input, ABS_Y, 0);
-       input_report_abs(input, ABS_MISC, 0);
-       input_report_key(input, wacom->tool[finger], 0);
-       if (!idx)
-               input_report_key(input, BTN_TOUCH, 0);
-       input_event(input, EV_MSC, MSC_SERIAL, finger);
-       input_sync(input);
+       return 1;
 }
 
-static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
        char *data = wacom->data;
        struct input_dev *input = wacom->input;
+       bool prox;
+       int x = 0, y = 0;
 
-       wacom->tool[1] = BTN_TOOL_DOUBLETAP;
-       wacom->id[0] = TOUCH_DEVICE_ID;
-       wacom->tool[2] = BTN_TOOL_TRIPLETAP;
-
-       if (len != WACOM_PKGLEN_TPC1FG) {
-
-               switch (data[0]) {
+       if (!wacom->shared->stylus_in_proximity) {
+               if (len == WACOM_PKGLEN_TPC1FG) {
+                       prox = data[0] & 0x01;
+                       x = get_unaligned_le16(&data[1]);
+                       y = get_unaligned_le16(&data[3]);
+               } else { /* with capacity */
+                       prox = data[1] & 0x01;
+                       x = le16_to_cpup((__le16 *)&data[2]);
+                       y = le16_to_cpup((__le16 *)&data[4]);
+               }
+       } else
+               /* force touch out when pen is in prox */
+               prox = 0;
 
-               case WACOM_REPORT_TPC1FG:
-                       input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-                       input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-                       input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
-                       input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6]));
-                       input_report_abs(input, ABS_MISC, wacom->id[0]);
-                       input_report_key(input, wacom->tool[1], 1);
-                       input_sync(input);
-                       break;
+       if (prox) {
+               input_report_abs(input, ABS_X, x);
+               input_report_abs(input, ABS_Y, y);
+       }
+       input_report_key(input, BTN_TOUCH, prox);
 
-               case WACOM_REPORT_TPC2FG:
-                       if (data[1] & 0x01)
-                               wacom_tpc_finger_in(wacom, data, 0);
-                       else if (wacom->id[1] & 0x01)
-                               wacom_tpc_touch_out(wacom, 0);
+       /* keep touch state for pen events */
+       wacom->shared->touch_down = prox;
 
-                       if (data[1] & 0x02)
-                               wacom_tpc_finger_in(wacom, data, 1);
-                       else if (wacom->id[1] & 0x02)
-                               wacom_tpc_touch_out(wacom, 1);
-                       break;
-               }
-       } else {
-               input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
-               input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
-               input_report_key(input, BTN_TOUCH, 1);
-               input_report_abs(input, ABS_MISC, wacom->id[1]);
-               input_report_key(input, wacom->tool[1], 1);
-               input_sync(input);
-       }
+       return 1;
 }
 
-static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
        struct wacom_features *features = &wacom->features;
        char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int prox = 0, pressure;
-       int retval = 0;
+       int pressure;
+       bool prox = data[1] & 0x20;
 
-       dbg("wacom_tpc_irq: received report #%d", data[0]);
-
-       if (len == WACOM_PKGLEN_TPC1FG ||                /* single touch */
-           data[0] == WACOM_REPORT_TPC1FG ||            /* single touch */
-           data[0] == WACOM_REPORT_TPC2FG) {            /* 2FG touch */
-
-               if (wacom->shared->stylus_in_proximity) {
-                       if (wacom->id[1] & 0x01)
-                               wacom_tpc_touch_out(wacom, 0);
-
-                       if (wacom->id[1] & 0x02)
-                               wacom_tpc_touch_out(wacom, 1);
-
-                       wacom->id[1] = 0;
-                       return 0;
-               }
-
-               if (len == WACOM_PKGLEN_TPC1FG) {       /* with touch */
-                       prox = data[0] & 0x01;
-               } else {  /* with capacity */
-                       if (data[0] == WACOM_REPORT_TPC1FG)
-                               /* single touch */
-                               prox = data[1] & 0x01;
-                       else
-                               /* 2FG touch data */
-                               prox = data[1] & 0x03;
-               }
-
-               if (prox) {
-                       if (!wacom->id[1])
-                               wacom->last_finger = 1;
-                       wacom_tpc_touch_in(wacom, len);
-               } else {
-                       if (data[0] == WACOM_REPORT_TPC2FG) {
-                               /* 2FGT out-prox */
-                               if (wacom->id[1] & 0x01)
-                                       wacom_tpc_touch_out(wacom, 0);
+       if (!wacom->shared->stylus_in_proximity) /* first in prox */
+               /* Going into proximity select tool */
+               wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
-                               if (wacom->id[1] & 0x02)
-                                       wacom_tpc_touch_out(wacom, 1);
-                       } else
-                               /* one finger touch */
-                               wacom_tpc_touch_out(wacom, 0);
+       /* keep pen state for touch events */
+       wacom->shared->stylus_in_proximity = prox;
 
-                       wacom->id[0] = 0;
-               }
-               /* keep prox bit to send proper out-prox event */
-               wacom->id[1] = prox;
-       } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
-               prox = data[1] & 0x20;
-
-               if (!wacom->shared->stylus_in_proximity) { /* first in prox */
-                       /* Going into proximity select tool */
-                       wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-                       if (wacom->tool[0] == BTN_TOOL_PEN)
-                               wacom->id[0] = STYLUS_DEVICE_ID;
-                       else
-                               wacom->id[0] = ERASER_DEVICE_ID;
-
-                       wacom->shared->stylus_in_proximity = true;
-               }
+       /* send pen events only when touch is up or forced out */
+       if (!wacom->shared->touch_down) {
                input_report_key(input, BTN_STYLUS, data[1] & 0x02);
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
@@ -847,15 +765,27 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
                        pressure = features->pressure_max + pressure + 1;
                input_report_abs(input, ABS_PRESSURE, pressure);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
-               if (!prox) { /* out-prox */
-                       wacom->id[0] = 0;
-                       wacom->shared->stylus_in_proximity = false;
-               }
                input_report_key(input, wacom->tool[0], prox);
-               input_report_abs(input, ABS_MISC, wacom->id[0]);
-               retval = 1;
+               return 1;
        }
-       return retval;
+
+       return 0;
+}
+
+static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+{
+       char *data = wacom->data;
+
+       dbg("wacom_tpc_irq: received report #%d", data[0]);
+
+       if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
+               return wacom_tpc_single_touch(wacom, len);
+       else if (data[0] == WACOM_REPORT_TPC2FG)
+               return wacom_tpc_mt_touch(wacom);
+       else if (data[0] == WACOM_REPORT_PENABLED)
+               return wacom_tpc_pen(wacom);
+
+       return 0;
 }
 
 static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -1078,7 +1008,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 {
 
        /* touch device found but size is not defined. use default */
-       if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+       if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
                features->x_max = 1023;
                features->y_max = 1023;
        }
@@ -1090,7 +1020,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* quirks for bamboo touch */
        if (features->type == BAMBOO_PT &&
-           features->device_type == BTN_TOOL_TRIPLETAP) {
+           features->device_type == BTN_TOOL_DOUBLETAP) {
                features->x_max <<= 5;
                features->y_max <<= 5;
                features->x_fuzz <<= 5;
@@ -1226,27 +1156,30 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                break;
 
        case TABLETPC2FG:
-               if (features->device_type == BTN_TOOL_TRIPLETAP) {
-                       __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
-                       input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
+               if (features->device_type == BTN_TOOL_DOUBLETAP) {
+
+                       input_mt_init_slots(input_dev, 2);
+                       input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+                                       0, MT_TOOL_MAX, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                                       0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                                       0, features->y_max, 0, 0);
                }
                /* fall through */
 
        case TABLETPC:
-               if (features->device_type == BTN_TOOL_DOUBLETAP ||
-                   features->device_type == BTN_TOOL_TRIPLETAP) {
+               __clear_bit(ABS_MISC, input_dev->absbit);
+
+               if (features->device_type != BTN_TOOL_PEN) {
                        input_abs_set_res(input_dev, ABS_X,
                                wacom_calculate_touch_res(features->x_max,
                                                        features->x_phy));
                        input_abs_set_res(input_dev, ABS_Y,
                                wacom_calculate_touch_res(features->y_max,
                                                        features->y_phy));
-                       __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-               }
-
-               if (features->device_type != BTN_TOOL_PEN)
                        break;  /* no need to process stylus stuff */
-
+               }
                /* fall through */
 
        case PL:
@@ -1264,7 +1197,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case BAMBOO_PT:
                __clear_bit(ABS_MISC, input_dev->absbit);
 
-               if (features->device_type == BTN_TOOL_TRIPLETAP) {
+               if (features->device_type == BTN_TOOL_DOUBLETAP) {
                        __set_bit(BTN_LEFT, input_dev->keybit);
                        __set_bit(BTN_FORWARD, input_dev->keybit);
                        __set_bit(BTN_BACK, input_dev->keybit);
index b1310ec9720c0613ab6a219cbe421d6e6eb62241..835f756b150c193fb9b46b4cd3ae6cccefa0a851 100644 (file)
@@ -88,15 +88,15 @@ struct wacom_features {
 
 struct wacom_shared {
        bool stylus_in_proximity;
+       bool touch_down;
 };
 
 struct wacom_wac {
        char name[64];
        unsigned char *data;
-       int tool[3];
-       int id[3];
+       int tool[2];
+       int id[2];
        __u32 serial[2];
-       int last_finger;
        struct wacom_features features;
        struct wacom_shared *shared;
        struct input_dev *input;
index 61834ae282e13c72be5ea2fad3dca266debc91b3..112ec55f2939733d53cc1a85c926cc4ee42618fd 100644 (file)
@@ -86,6 +86,18 @@ config TOUCHSCREEN_AD7879_SPI
          To compile this driver as a module, choose M here: the
          module will be called ad7879-spi.
 
+config TOUCHSCREEN_ATMEL_MXT
+       tristate "Atmel mXT I2C Touchscreen"
+       depends on I2C
+       help
+         Say Y here if you have Atmel mXT series I2C touchscreen,
+         such as AT42QT602240/ATMXT224, connected to your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called atmel_mxt_ts.
+
 config TOUCHSCREEN_BITSY
        tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
        depends on SA1100_BITSY
@@ -339,18 +351,6 @@ config TOUCHSCREEN_PENMOUNT
          To compile this driver as a module, choose M here: the
          module will be called penmount.
 
-config TOUCHSCREEN_QT602240
-       tristate "QT602240 I2C Touchscreen"
-       depends on I2C
-       help
-         Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen
-         connected to your system.
-
-         If unsure, say N.
-
-         To compile this driver as a module, choose M here: the
-         module will be called qt602240_ts.
-
 config TOUCHSCREEN_MIGOR
        tristate "Renesas MIGO-R touchscreen"
        depends on SH_MIGOR && I2C
@@ -423,6 +423,16 @@ config TOUCHSCREEN_UCB1400
          To compile this driver as a module, choose M here: the
          module will be called ucb1400_ts.
 
+config TOUCHSCREEN_WM831X
+       tristate "Support for WM831x touchscreen controllers"
+       depends on MFD_WM831X
+       help
+         This enables support for the touchscreen controller on the WM831x
+         series of PMICs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm831x-ts.
+
 config TOUCHSCREEN_WM97XX
        tristate "Support for WM97xx AC97 touchscreen controllers"
        depends on AC97_BUS
@@ -629,6 +639,17 @@ config TOUCHSCREEN_TOUCHIT213
          To compile this driver as a module, choose M here: the
          module will be called touchit213.
 
+config TOUCHSCREEN_TSC2005
+        tristate "TSC2005 based touchscreens"
+        depends on SPI_MASTER
+        help
+          Say Y here if you have a TSC2005 based touchscreen.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tsc2005.
+
 config TOUCHSCREEN_TSC2007
        tristate "TSC2007 based touchscreens"
        depends on I2C
index 718bcc814952cd38b82b3c2b086a05ec19ed983d..ca94098d4c92b8116815c17a9ac742e77aa622e3 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879)      += ad7879.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)   += ad7879-i2c.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)   += ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)    += atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
@@ -37,7 +38,6 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)      += htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)        += usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)         += pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)     += penmount.o
-obj-$(CONFIG_TOUCHSCREEN_QT602240)     += qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)      += s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)       += st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)                += stmpe-ts.o
@@ -45,9 +45,11 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X)  += tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)   += touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2005)      += tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)      += tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)  += wacom_w8001.o
+obj-$(CONFIG_TOUCHSCREEN_WM831X)       += wm831x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX)       += wm97xx-ts.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
index a1952fcc083e14a68694b5f69c64359588818b2c..714d4e0f9f95f546affadbdbc677d87c27152bc0 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ad7877.h>
@@ -826,39 +827,37 @@ static int __devexit ad7877_remove(struct spi_device *spi)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int ad7877_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7877_suspend(struct device *dev)
 {
-       struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        ad7877_disable(ts);
 
        return 0;
 }
 
-static int ad7877_resume(struct spi_device *spi)
+static int ad7877_resume(struct device *dev)
 {
-       struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        ad7877_enable(ts);
 
        return 0;
 }
-#else
-#define ad7877_suspend NULL
-#define ad7877_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
+
 static struct spi_driver ad7877_driver = {
        .driver = {
                .name   = "ad7877",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &ad7877_pm,
        },
        .probe          = ad7877_probe,
        .remove         = __devexit_p(ad7877_remove),
-       .suspend        = ad7877_suspend,
-       .resume         = ad7877_resume,
 };
 
 static int __init ad7877_init(void)
index 59c6e68c432507a61392993b572541dc2c8693a4..ddf732f3cafcd3021c889f435d2d1c662f627663 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/input.h>       /* BUS_SPI */
+#include <linux/pm.h>
 #include <linux/spi/spi.h>
 
 #include "ad7879.h"
 #define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
 #define AD7879_READCMD(reg)  (AD7879_CMD(reg) | AD7879_CMD_READ)
 
-#ifdef CONFIG_PM
-static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7879_spi_suspend(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct ad7879 *ts = spi_get_drvdata(spi);
 
        ad7879_suspend(ts);
@@ -30,19 +32,19 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
        return 0;
 }
 
-static int ad7879_spi_resume(struct spi_device *spi)
+static int ad7879_spi_resume(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct ad7879 *ts = spi_get_drvdata(spi);
 
        ad7879_resume(ts);
 
        return 0;
 }
-#else
-# define ad7879_spi_suspend NULL
-# define ad7879_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume);
+
 /*
  * ad7879_read/write are only used for initial setup and for sysfs controls.
  * The main traffic is done in ad7879_collect().
@@ -173,11 +175,10 @@ static struct spi_driver ad7879_spi_driver = {
                .name   = "ad7879",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &ad7879_spi_pm,
        },
        .probe          = ad7879_spi_probe,
        .remove         = __devexit_p(ad7879_spi_remove),
-       .suspend        = ad7879_spi_suspend,
-       .resume         = ad7879_spi_resume,
 };
 
 static int __init ad7879_spi_init(void)
index 4bf2316e3284b8db426e6e11d2dfda72166b1278..c24946f512564e35925d0e6c090b7fd4a6c4eccd 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -892,9 +893,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
        return IRQ_HANDLED;
 }
 
-static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ads7846_suspend(struct device *dev)
 {
-       struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
 
        mutex_lock(&ts->lock);
 
@@ -914,9 +916,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
        return 0;
 }
 
-static int ads7846_resume(struct spi_device *spi)
+static int ads7846_resume(struct device *dev)
 {
-       struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
 
        mutex_lock(&ts->lock);
 
@@ -935,6 +937,9 @@ static int ads7846_resume(struct spi_device *spi)
 
        return 0;
 }
+#endif
+
+static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
 static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
@@ -1408,11 +1413,10 @@ static struct spi_driver ads7846_driver = {
                .name   = "ads7846",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &ads7846_pm,
        },
        .probe          = ads7846_probe,
        .remove         = __devexit_p(ads7846_remove),
-       .suspend        = ads7846_suspend,
-       .resume         = ads7846_resume,
 };
 
 static int __init ads7846_init(void)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
new file mode 100644 (file)
index 0000000..4012436
--- /dev/null
@@ -0,0 +1,1211 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+/* Version */
+#define MXT_VER_20             20
+#define MXT_VER_21             21
+#define MXT_VER_22             22
+
+/* Slave addresses */
+#define MXT_APP_LOW            0x4a
+#define MXT_APP_HIGH           0x4b
+#define MXT_BOOT_LOW           0x24
+#define MXT_BOOT_HIGH          0x25
+
+/* Firmware */
+#define MXT_FW_NAME            "maxtouch.fw"
+
+/* Registers */
+#define MXT_FAMILY_ID          0x00
+#define MXT_VARIANT_ID         0x01
+#define MXT_VERSION            0x02
+#define MXT_BUILD              0x03
+#define MXT_MATRIX_X_SIZE      0x04
+#define MXT_MATRIX_Y_SIZE      0x05
+#define MXT_OBJECT_NUM         0x06
+#define MXT_OBJECT_START       0x07
+
+#define MXT_OBJECT_SIZE                6
+
+/* Object types */
+#define MXT_DEBUG_DIAGNOSTIC   37
+#define MXT_GEN_MESSAGE                5
+#define MXT_GEN_COMMAND                6
+#define MXT_GEN_POWER          7
+#define MXT_GEN_ACQUIRE                8
+#define MXT_TOUCH_MULTI                9
+#define MXT_TOUCH_KEYARRAY     15
+#define MXT_TOUCH_PROXIMITY    23
+#define MXT_PROCI_GRIPFACE     20
+#define MXT_PROCG_NOISE                22
+#define MXT_PROCI_ONETOUCH     24
+#define MXT_PROCI_TWOTOUCH     27
+#define MXT_PROCI_GRIP         40
+#define MXT_PROCI_PALM         41
+#define MXT_SPT_COMMSCONFIG    18
+#define MXT_SPT_GPIOPWM                19
+#define MXT_SPT_SELFTEST       25
+#define MXT_SPT_CTECONFIG      28
+#define MXT_SPT_USERDATA       38
+#define MXT_SPT_DIGITIZER      43
+#define MXT_SPT_MESSAGECOUNT   44
+
+/* MXT_GEN_COMMAND field */
+#define MXT_COMMAND_RESET      0
+#define MXT_COMMAND_BACKUPNV   1
+#define MXT_COMMAND_CALIBRATE  2
+#define MXT_COMMAND_REPORTALL  3
+#define MXT_COMMAND_DIAGNOSTIC 5
+
+/* MXT_GEN_POWER field */
+#define MXT_POWER_IDLEACQINT   0
+#define MXT_POWER_ACTVACQINT   1
+#define MXT_POWER_ACTV2IDLETO  2
+
+/* MXT_GEN_ACQUIRE field */
+#define MXT_ACQUIRE_CHRGTIME   0
+#define MXT_ACQUIRE_TCHDRIFT   2
+#define MXT_ACQUIRE_DRIFTST    3
+#define MXT_ACQUIRE_TCHAUTOCAL 4
+#define MXT_ACQUIRE_SYNC       5
+#define MXT_ACQUIRE_ATCHCALST  6
+#define MXT_ACQUIRE_ATCHCALSTHR        7
+
+/* MXT_TOUCH_MULTI field */
+#define MXT_TOUCH_CTRL         0
+#define MXT_TOUCH_XORIGIN      1
+#define MXT_TOUCH_YORIGIN      2
+#define MXT_TOUCH_XSIZE                3
+#define MXT_TOUCH_YSIZE                4
+#define MXT_TOUCH_BLEN         6
+#define MXT_TOUCH_TCHTHR       7
+#define MXT_TOUCH_TCHDI                8
+#define MXT_TOUCH_ORIENT       9
+#define MXT_TOUCH_MOVHYSTI     11
+#define MXT_TOUCH_MOVHYSTN     12
+#define MXT_TOUCH_NUMTOUCH     14
+#define MXT_TOUCH_MRGHYST      15
+#define MXT_TOUCH_MRGTHR       16
+#define MXT_TOUCH_AMPHYST      17
+#define MXT_TOUCH_XRANGE_LSB   18
+#define MXT_TOUCH_XRANGE_MSB   19
+#define MXT_TOUCH_YRANGE_LSB   20
+#define MXT_TOUCH_YRANGE_MSB   21
+#define MXT_TOUCH_XLOCLIP      22
+#define MXT_TOUCH_XHICLIP      23
+#define MXT_TOUCH_YLOCLIP      24
+#define MXT_TOUCH_YHICLIP      25
+#define MXT_TOUCH_XEDGECTRL    26
+#define MXT_TOUCH_XEDGEDIST    27
+#define MXT_TOUCH_YEDGECTRL    28
+#define MXT_TOUCH_YEDGEDIST    29
+#define MXT_TOUCH_JUMPLIMIT    30
+
+/* MXT_PROCI_GRIPFACE field */
+#define MXT_GRIPFACE_CTRL      0
+#define MXT_GRIPFACE_XLOGRIP   1
+#define MXT_GRIPFACE_XHIGRIP   2
+#define MXT_GRIPFACE_YLOGRIP   3
+#define MXT_GRIPFACE_YHIGRIP   4
+#define MXT_GRIPFACE_MAXTCHS   5
+#define MXT_GRIPFACE_SZTHR1    7
+#define MXT_GRIPFACE_SZTHR2    8
+#define MXT_GRIPFACE_SHPTHR1   9
+#define MXT_GRIPFACE_SHPTHR2   10
+#define MXT_GRIPFACE_SUPEXTTO  11
+
+/* MXT_PROCI_NOISE field */
+#define MXT_NOISE_CTRL         0
+#define MXT_NOISE_OUTFLEN      1
+#define MXT_NOISE_GCAFUL_LSB   3
+#define MXT_NOISE_GCAFUL_MSB   4
+#define MXT_NOISE_GCAFLL_LSB   5
+#define MXT_NOISE_GCAFLL_MSB   6
+#define MXT_NOISE_ACTVGCAFVALID        7
+#define MXT_NOISE_NOISETHR     8
+#define MXT_NOISE_FREQHOPSCALE 10
+#define MXT_NOISE_FREQ0                11
+#define MXT_NOISE_FREQ1                12
+#define MXT_NOISE_FREQ2                13
+#define MXT_NOISE_FREQ3                14
+#define MXT_NOISE_FREQ4                15
+#define MXT_NOISE_IDLEGCAFVALID        16
+
+/* MXT_SPT_COMMSCONFIG */
+#define MXT_COMMS_CTRL         0
+#define MXT_COMMS_CMD          1
+
+/* MXT_SPT_CTECONFIG field */
+#define MXT_CTE_CTRL           0
+#define MXT_CTE_CMD            1
+#define MXT_CTE_MODE           2
+#define MXT_CTE_IDLEGCAFDEPTH  3
+#define MXT_CTE_ACTVGCAFDEPTH  4
+#define MXT_CTE_VOLTAGE                5
+
+#define MXT_VOLTAGE_DEFAULT    2700000
+#define MXT_VOLTAGE_STEP       10000
+
+/* Define for MXT_GEN_COMMAND */
+#define MXT_BOOT_VALUE         0xa5
+#define MXT_BACKUP_VALUE       0x55
+#define MXT_BACKUP_TIME                25      /* msec */
+#define MXT_RESET_TIME         65      /* msec */
+
+#define MXT_FWRESET_TIME       175     /* msec */
+
+/* Command to unlock bootloader */
+#define MXT_UNLOCK_CMD_MSB     0xaa
+#define MXT_UNLOCK_CMD_LSB     0xdc
+
+/* Bootloader mode status */
+#define MXT_WAITING_BOOTLOAD_CMD       0xc0    /* valid 7 6 bit only */
+#define MXT_WAITING_FRAME_DATA 0x80    /* valid 7 6 bit only */
+#define MXT_FRAME_CRC_CHECK    0x02
+#define MXT_FRAME_CRC_FAIL     0x03
+#define MXT_FRAME_CRC_PASS     0x04
+#define MXT_APP_CRC_FAIL       0x40    /* valid 7 8 bit only */
+#define MXT_BOOT_STATUS_MASK   0x3f
+
+/* Touch status */
+#define MXT_SUPPRESS           (1 << 1)
+#define MXT_AMP                        (1 << 2)
+#define MXT_VECTOR             (1 << 3)
+#define MXT_MOVE               (1 << 4)
+#define MXT_RELEASE            (1 << 5)
+#define MXT_PRESS              (1 << 6)
+#define MXT_DETECT             (1 << 7)
+
+/* Touchscreen absolute values */
+#define MXT_MAX_XC             0x3ff
+#define MXT_MAX_YC             0x3ff
+#define MXT_MAX_AREA           0xff
+
+#define MXT_MAX_FINGER         10
+
+struct mxt_info {
+       u8 family_id;
+       u8 variant_id;
+       u8 version;
+       u8 build;
+       u8 matrix_xsize;
+       u8 matrix_ysize;
+       u8 object_num;
+};
+
+struct mxt_object {
+       u8 type;
+       u16 start_address;
+       u8 size;
+       u8 instances;
+       u8 num_report_ids;
+
+       /* to map object and message */
+       u8 max_reportid;
+};
+
+struct mxt_message {
+       u8 reportid;
+       u8 message[7];
+       u8 checksum;
+};
+
+struct mxt_finger {
+       int status;
+       int x;
+       int y;
+       int area;
+};
+
+/* Each client has this additional data */
+struct mxt_data {
+       struct i2c_client *client;
+       struct input_dev *input_dev;
+       const struct mxt_platform_data *pdata;
+       struct mxt_object *object_table;
+       struct mxt_info info;
+       struct mxt_finger finger[MXT_MAX_FINGER];
+       unsigned int irq;
+};
+
+static bool mxt_object_readable(unsigned int type)
+{
+       switch (type) {
+       case MXT_GEN_MESSAGE:
+       case MXT_GEN_COMMAND:
+       case MXT_GEN_POWER:
+       case MXT_GEN_ACQUIRE:
+       case MXT_TOUCH_MULTI:
+       case MXT_TOUCH_KEYARRAY:
+       case MXT_TOUCH_PROXIMITY:
+       case MXT_PROCI_GRIPFACE:
+       case MXT_PROCG_NOISE:
+       case MXT_PROCI_ONETOUCH:
+       case MXT_PROCI_TWOTOUCH:
+       case MXT_PROCI_GRIP:
+       case MXT_PROCI_PALM:
+       case MXT_SPT_COMMSCONFIG:
+       case MXT_SPT_GPIOPWM:
+       case MXT_SPT_SELFTEST:
+       case MXT_SPT_CTECONFIG:
+       case MXT_SPT_USERDATA:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool mxt_object_writable(unsigned int type)
+{
+       switch (type) {
+       case MXT_GEN_COMMAND:
+       case MXT_GEN_POWER:
+       case MXT_GEN_ACQUIRE:
+       case MXT_TOUCH_MULTI:
+       case MXT_TOUCH_KEYARRAY:
+       case MXT_TOUCH_PROXIMITY:
+       case MXT_PROCI_GRIPFACE:
+       case MXT_PROCG_NOISE:
+       case MXT_PROCI_ONETOUCH:
+       case MXT_PROCI_TWOTOUCH:
+       case MXT_PROCI_GRIP:
+       case MXT_PROCI_PALM:
+       case MXT_SPT_GPIOPWM:
+       case MXT_SPT_SELFTEST:
+       case MXT_SPT_CTECONFIG:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void mxt_dump_message(struct device *dev,
+                                 struct mxt_message *message)
+{
+       dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
+       dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
+       dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
+       dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
+       dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
+       dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
+       dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
+       dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
+       dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
+}
+
+static int mxt_check_bootloader(struct i2c_client *client,
+                                    unsigned int state)
+{
+       u8 val;
+
+recheck:
+       if (i2c_master_recv(client, &val, 1) != 1) {
+               dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
+               return -EIO;
+       }
+
+       switch (state) {
+       case MXT_WAITING_BOOTLOAD_CMD:
+       case MXT_WAITING_FRAME_DATA:
+               val &= ~MXT_BOOT_STATUS_MASK;
+               break;
+       case MXT_FRAME_CRC_PASS:
+               if (val == MXT_FRAME_CRC_CHECK)
+                       goto recheck;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (val != state) {
+               dev_err(&client->dev, "Unvalid bootloader mode state\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mxt_unlock_bootloader(struct i2c_client *client)
+{
+       u8 buf[2];
+
+       buf[0] = MXT_UNLOCK_CMD_LSB;
+       buf[1] = MXT_UNLOCK_CMD_MSB;
+
+       if (i2c_master_send(client, buf, 2) != 2) {
+               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mxt_fw_write(struct i2c_client *client,
+                            const u8 *data, unsigned int frame_size)
+{
+       if (i2c_master_send(client, data, frame_size) != frame_size) {
+               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int __mxt_read_reg(struct i2c_client *client,
+                              u16 reg, u16 len, void *val)
+{
+       struct i2c_msg xfer[2];
+       u8 buf[2];
+
+       buf[0] = reg & 0xff;
+       buf[1] = (reg >> 8) & 0xff;
+
+       /* Write register */
+       xfer[0].addr = client->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 2;
+       xfer[0].buf = buf;
+
+       /* Read data */
+       xfer[1].addr = client->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = len;
+       xfer[1].buf = val;
+
+       if (i2c_transfer(client->adapter, xfer, 2) != 2) {
+               dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+{
+       return __mxt_read_reg(client, reg, 1, val);
+}
+
+static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
+{
+       u8 buf[3];
+
+       buf[0] = reg & 0xff;
+       buf[1] = (reg >> 8) & 0xff;
+       buf[2] = val;
+
+       if (i2c_master_send(client, buf, 3) != 3) {
+               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mxt_read_object_table(struct i2c_client *client,
+                                     u16 reg, u8 *object_buf)
+{
+       return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
+                                  object_buf);
+}
+
+static struct mxt_object *
+mxt_get_object(struct mxt_data *data, u8 type)
+{
+       struct mxt_object *object;
+       int i;
+
+       for (i = 0; i < data->info.object_num; i++) {
+               object = data->object_table + i;
+               if (object->type == type)
+                       return object;
+       }
+
+       dev_err(&data->client->dev, "Invalid object type\n");
+       return NULL;
+}
+
+static int mxt_read_message(struct mxt_data *data,
+                                struct mxt_message *message)
+{
+       struct mxt_object *object;
+       u16 reg;
+
+       object = mxt_get_object(data, MXT_GEN_MESSAGE);
+       if (!object)
+               return -EINVAL;
+
+       reg = object->start_address;
+       return __mxt_read_reg(data->client, reg,
+                       sizeof(struct mxt_message), message);
+}
+
+static int mxt_read_object(struct mxt_data *data,
+                               u8 type, u8 offset, u8 *val)
+{
+       struct mxt_object *object;
+       u16 reg;
+
+       object = mxt_get_object(data, type);
+       if (!object)
+               return -EINVAL;
+
+       reg = object->start_address;
+       return __mxt_read_reg(data->client, reg + offset, 1, val);
+}
+
+static int mxt_write_object(struct mxt_data *data,
+                                u8 type, u8 offset, u8 val)
+{
+       struct mxt_object *object;
+       u16 reg;
+
+       object = mxt_get_object(data, type);
+       if (!object)
+               return -EINVAL;
+
+       reg = object->start_address;
+       return mxt_write_reg(data->client, reg + offset, val);
+}
+
+static void mxt_input_report(struct mxt_data *data, int single_id)
+{
+       struct mxt_finger *finger = data->finger;
+       struct input_dev *input_dev = data->input_dev;
+       int status = finger[single_id].status;
+       int finger_num = 0;
+       int id;
+
+       for (id = 0; id < MXT_MAX_FINGER; id++) {
+               if (!finger[id].status)
+                       continue;
+
+               input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+                               finger[id].status != MXT_RELEASE ?
+                               finger[id].area : 0);
+               input_report_abs(input_dev, ABS_MT_POSITION_X,
+                               finger[id].x);
+               input_report_abs(input_dev, ABS_MT_POSITION_Y,
+                               finger[id].y);
+               input_mt_sync(input_dev);
+
+               if (finger[id].status == MXT_RELEASE)
+                       finger[id].status = 0;
+               else
+                       finger_num++;
+       }
+
+       input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
+
+       if (status != MXT_RELEASE) {
+               input_report_abs(input_dev, ABS_X, finger[single_id].x);
+               input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+       }
+
+       input_sync(input_dev);
+}
+
+static void mxt_input_touchevent(struct mxt_data *data,
+                                     struct mxt_message *message, int id)
+{
+       struct mxt_finger *finger = data->finger;
+       struct device *dev = &data->client->dev;
+       u8 status = message->message[0];
+       int x;
+       int y;
+       int area;
+
+       /* Check the touch is present on the screen */
+       if (!(status & MXT_DETECT)) {
+               if (status & MXT_RELEASE) {
+                       dev_dbg(dev, "[%d] released\n", id);
+
+                       finger[id].status = MXT_RELEASE;
+                       mxt_input_report(data, id);
+               }
+               return;
+       }
+
+       /* Check only AMP detection */
+       if (!(status & (MXT_PRESS | MXT_MOVE)))
+               return;
+
+       x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
+       y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
+       area = message->message[4];
+
+       dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
+               status & MXT_MOVE ? "moved" : "pressed",
+               x, y, area);
+
+       finger[id].status = status & MXT_MOVE ?
+                               MXT_MOVE : MXT_PRESS;
+       finger[id].x = x;
+       finger[id].y = y;
+       finger[id].area = area;
+
+       mxt_input_report(data, id);
+}
+
+static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+{
+       struct mxt_data *data = dev_id;
+       struct mxt_message message;
+       struct mxt_object *object;
+       struct device *dev = &data->client->dev;
+       int id;
+       u8 reportid;
+       u8 max_reportid;
+       u8 min_reportid;
+
+       do {
+               if (mxt_read_message(data, &message)) {
+                       dev_err(dev, "Failed to read message\n");
+                       goto end;
+               }
+
+               reportid = message.reportid;
+
+               /* whether reportid is thing of MXT_TOUCH_MULTI */
+               object = mxt_get_object(data, MXT_TOUCH_MULTI);
+               if (!object)
+                       goto end;
+
+               max_reportid = object->max_reportid;
+               min_reportid = max_reportid - object->num_report_ids + 1;
+               id = reportid - min_reportid;
+
+               if (reportid >= min_reportid && reportid <= max_reportid)
+                       mxt_input_touchevent(data, &message, id);
+               else
+                       mxt_dump_message(dev, &message);
+       } while (reportid != 0xff);
+
+end:
+       return IRQ_HANDLED;
+}
+
+static int mxt_check_reg_init(struct mxt_data *data)
+{
+       const struct mxt_platform_data *pdata = data->pdata;
+       struct mxt_object *object;
+       struct device *dev = &data->client->dev;
+       int index = 0;
+       int i, j, config_offset;
+
+       if (!pdata->config) {
+               dev_dbg(dev, "No cfg data defined, skipping reg init\n");
+               return 0;
+       }
+
+       for (i = 0; i < data->info.object_num; i++) {
+               object = data->object_table + i;
+
+               if (!mxt_object_writable(object->type))
+                       continue;
+
+               for (j = 0; j < object->size + 1; j++) {
+                       config_offset = index + j;
+                       if (config_offset > pdata->config_length) {
+                               dev_err(dev, "Not enough config data!\n");
+                               return -EINVAL;
+                       }
+                       mxt_write_object(data, object->type, j,
+                                        pdata->config[config_offset]);
+               }
+               index += object->size + 1;
+       }
+
+       return 0;
+}
+
+static int mxt_make_highchg(struct mxt_data *data)
+{
+       struct device *dev = &data->client->dev;
+       struct mxt_message message;
+       int count = 10;
+       int error;
+
+       /* Read dummy message to make high CHG pin */
+       do {
+               error = mxt_read_message(data, &message);
+               if (error)
+                       return error;
+       } while (message.reportid != 0xff && --count);
+
+       if (!count) {
+               dev_err(dev, "CHG pin isn't cleared\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static void mxt_handle_pdata(struct mxt_data *data)
+{
+       const struct mxt_platform_data *pdata = data->pdata;
+       u8 voltage;
+
+       /* Set touchscreen lines */
+       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+                       pdata->x_line);
+       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+                       pdata->y_line);
+
+       /* Set touchscreen orient */
+       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+                       pdata->orient);
+
+       /* Set touchscreen burst length */
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_BLEN, pdata->blen);
+
+       /* Set touchscreen threshold */
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_TCHTHR, pdata->threshold);
+
+       /* Set touchscreen resolution */
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
+       mxt_write_object(data, MXT_TOUCH_MULTI,
+                       MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
+
+       /* Set touchscreen voltage */
+       if (pdata->voltage) {
+               if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
+                       voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
+                               MXT_VOLTAGE_STEP;
+                       voltage = 0xff - voltage + 1;
+               } else
+                       voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
+                               MXT_VOLTAGE_STEP;
+
+               mxt_write_object(data, MXT_SPT_CTECONFIG,
+                               MXT_CTE_VOLTAGE, voltage);
+       }
+}
+
+static int mxt_get_info(struct mxt_data *data)
+{
+       struct i2c_client *client = data->client;
+       struct mxt_info *info = &data->info;
+       int error;
+       u8 val;
+
+       error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
+       if (error)
+               return error;
+       info->family_id = val;
+
+       error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
+       if (error)
+               return error;
+       info->variant_id = val;
+
+       error = mxt_read_reg(client, MXT_VERSION, &val);
+       if (error)
+               return error;
+       info->version = val;
+
+       error = mxt_read_reg(client, MXT_BUILD, &val);
+       if (error)
+               return error;
+       info->build = val;
+
+       error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
+       if (error)
+               return error;
+       info->object_num = val;
+
+       return 0;
+}
+
+static int mxt_get_object_table(struct mxt_data *data)
+{
+       int error;
+       int i;
+       u16 reg;
+       u8 reportid = 0;
+       u8 buf[MXT_OBJECT_SIZE];
+
+       for (i = 0; i < data->info.object_num; i++) {
+               struct mxt_object *object = data->object_table + i;
+
+               reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
+               error = mxt_read_object_table(data->client, reg, buf);
+               if (error)
+                       return error;
+
+               object->type = buf[0];
+               object->start_address = (buf[2] << 8) | buf[1];
+               object->size = buf[3];
+               object->instances = buf[4];
+               object->num_report_ids = buf[5];
+
+               if (object->num_report_ids) {
+                       reportid += object->num_report_ids *
+                                       (object->instances + 1);
+                       object->max_reportid = reportid;
+               }
+       }
+
+       return 0;
+}
+
+static int mxt_initialize(struct mxt_data *data)
+{
+       struct i2c_client *client = data->client;
+       struct mxt_info *info = &data->info;
+       int error;
+       u8 val;
+
+       error = mxt_get_info(data);
+       if (error)
+               return error;
+
+       data->object_table = kcalloc(info->object_num,
+                                    sizeof(struct mxt_object),
+                                    GFP_KERNEL);
+       if (!data->object_table) {
+               dev_err(&client->dev, "Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       /* Get object table information */
+       error = mxt_get_object_table(data);
+       if (error)
+               return error;
+
+       /* Check register init values */
+       error = mxt_check_reg_init(data);
+       if (error)
+               return error;
+
+       error = mxt_make_highchg(data);
+       if (error)
+               return error;
+
+       mxt_handle_pdata(data);
+
+       /* Backup to memory */
+       mxt_write_object(data, MXT_GEN_COMMAND,
+                       MXT_COMMAND_BACKUPNV,
+                       MXT_BACKUP_VALUE);
+       msleep(MXT_BACKUP_TIME);
+
+       /* Soft reset */
+       mxt_write_object(data, MXT_GEN_COMMAND,
+                       MXT_COMMAND_RESET, 1);
+       msleep(MXT_RESET_TIME);
+
+       /* Update matrix size at info struct */
+       error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
+       if (error)
+               return error;
+       info->matrix_xsize = val;
+
+       error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
+       if (error)
+               return error;
+       info->matrix_ysize = val;
+
+       dev_info(&client->dev,
+                       "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
+                       info->family_id, info->variant_id, info->version,
+                       info->build);
+
+       dev_info(&client->dev,
+                       "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
+                       info->matrix_xsize, info->matrix_ysize,
+                       info->object_num);
+
+       return 0;
+}
+
+static ssize_t mxt_object_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct mxt_data *data = dev_get_drvdata(dev);
+       struct mxt_object *object;
+       int count = 0;
+       int i, j;
+       int error;
+       u8 val;
+
+       for (i = 0; i < data->info.object_num; i++) {
+               object = data->object_table + i;
+
+               count += sprintf(buf + count,
+                               "Object Table Element %d(Type %d)\n",
+                               i + 1, object->type);
+
+               if (!mxt_object_readable(object->type)) {
+                       count += sprintf(buf + count, "\n");
+                       continue;
+               }
+
+               for (j = 0; j < object->size + 1; j++) {
+                       error = mxt_read_object(data,
+                                               object->type, j, &val);
+                       if (error)
+                               return error;
+
+                       count += sprintf(buf + count,
+                                       "  Byte %d: 0x%x (%d)\n", j, val, val);
+               }
+
+               count += sprintf(buf + count, "\n");
+       }
+
+       return count;
+}
+
+static int mxt_load_fw(struct device *dev, const char *fn)
+{
+       struct mxt_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+       const struct firmware *fw = NULL;
+       unsigned int frame_size;
+       unsigned int pos = 0;
+       int ret;
+
+       ret = request_firmware(&fw, fn, dev);
+       if (ret) {
+               dev_err(dev, "Unable to open firmware %s\n", fn);
+               return ret;
+       }
+
+       /* Change to the bootloader mode */
+       mxt_write_object(data, MXT_GEN_COMMAND,
+                       MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+       msleep(MXT_RESET_TIME);
+
+       /* Change to slave address of bootloader */
+       if (client->addr == MXT_APP_LOW)
+               client->addr = MXT_BOOT_LOW;
+       else
+               client->addr = MXT_BOOT_HIGH;
+
+       ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+       if (ret)
+               goto out;
+
+       /* Unlock bootloader */
+       mxt_unlock_bootloader(client);
+
+       while (pos < fw->size) {
+               ret = mxt_check_bootloader(client,
+                                               MXT_WAITING_FRAME_DATA);
+               if (ret)
+                       goto out;
+
+               frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+
+               /* We should add 2 at frame size as the the firmware data is not
+                * included the CRC bytes.
+                */
+               frame_size += 2;
+
+               /* Write one frame to device */
+               mxt_fw_write(client, fw->data + pos, frame_size);
+
+               ret = mxt_check_bootloader(client,
+                                               MXT_FRAME_CRC_PASS);
+               if (ret)
+                       goto out;
+
+               pos += frame_size;
+
+               dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+       }
+
+out:
+       release_firmware(fw);
+
+       /* Change to slave address of application */
+       if (client->addr == MXT_BOOT_LOW)
+               client->addr = MXT_APP_LOW;
+       else
+               client->addr = MXT_APP_HIGH;
+
+       return ret;
+}
+
+static ssize_t mxt_update_fw_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct mxt_data *data = dev_get_drvdata(dev);
+       int error;
+
+       disable_irq(data->irq);
+
+       error = mxt_load_fw(dev, MXT_FW_NAME);
+       if (error) {
+               dev_err(dev, "The firmware update failed(%d)\n", error);
+               count = error;
+       } else {
+               dev_dbg(dev, "The firmware update succeeded\n");
+
+               /* Wait for reset */
+               msleep(MXT_FWRESET_TIME);
+
+               kfree(data->object_table);
+               data->object_table = NULL;
+
+               mxt_initialize(data);
+       }
+
+       enable_irq(data->irq);
+
+       return count;
+}
+
+static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
+static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+
+static struct attribute *mxt_attrs[] = {
+       &dev_attr_object.attr,
+       &dev_attr_update_fw.attr,
+       NULL
+};
+
+static const struct attribute_group mxt_attr_group = {
+       .attrs = mxt_attrs,
+};
+
+static void mxt_start(struct mxt_data *data)
+{
+       /* Touch enable */
+       mxt_write_object(data,
+                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+}
+
+static void mxt_stop(struct mxt_data *data)
+{
+       /* Touch disable */
+       mxt_write_object(data,
+                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
+}
+
+static int mxt_input_open(struct input_dev *dev)
+{
+       struct mxt_data *data = input_get_drvdata(dev);
+
+       mxt_start(data);
+
+       return 0;
+}
+
+static void mxt_input_close(struct input_dev *dev)
+{
+       struct mxt_data *data = input_get_drvdata(dev);
+
+       mxt_stop(data);
+}
+
+static int __devinit mxt_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       const struct mxt_platform_data *pdata = client->dev.platform_data;
+       struct mxt_data *data;
+       struct input_dev *input_dev;
+       int error;
+
+       if (!pdata)
+               return -EINVAL;
+
+       data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!data || !input_dev) {
+               dev_err(&client->dev, "Failed to allocate memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       input_dev->name = "Atmel maXTouch Touchscreen";
+       input_dev->id.bustype = BUS_I2C;
+       input_dev->dev.parent = &client->dev;
+       input_dev->open = mxt_input_open;
+       input_dev->close = mxt_input_close;
+
+       __set_bit(EV_ABS, input_dev->evbit);
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
+
+       /* For single touch */
+       input_set_abs_params(input_dev, ABS_X,
+                            0, MXT_MAX_XC, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y,
+                            0, MXT_MAX_YC, 0, 0);
+
+       /* For multi touch */
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+                            0, MXT_MAX_AREA, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                            0, MXT_MAX_XC, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                            0, MXT_MAX_YC, 0, 0);
+
+       input_set_drvdata(input_dev, data);
+
+       data->client = client;
+       data->input_dev = input_dev;
+       data->pdata = pdata;
+       data->irq = client->irq;
+
+       i2c_set_clientdata(client, data);
+
+       error = mxt_initialize(data);
+       if (error)
+               goto err_free_object;
+
+       error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+                       pdata->irqflags, client->dev.driver->name, data);
+       if (error) {
+               dev_err(&client->dev, "Failed to register interrupt\n");
+               goto err_free_object;
+       }
+
+       error = input_register_device(input_dev);
+       if (error)
+               goto err_free_irq;
+
+       error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+       if (error)
+               goto err_unregister_device;
+
+       return 0;
+
+err_unregister_device:
+       input_unregister_device(input_dev);
+       input_dev = NULL;
+err_free_irq:
+       free_irq(client->irq, data);
+err_free_object:
+       kfree(data->object_table);
+err_free_mem:
+       input_free_device(input_dev);
+       kfree(data);
+       return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+       struct mxt_data *data = i2c_get_clientdata(client);
+
+       sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+       free_irq(data->irq, data);
+       input_unregister_device(data->input_dev);
+       kfree(data->object_table);
+       kfree(data);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxt_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct mxt_data *data = i2c_get_clientdata(client);
+       struct input_dev *input_dev = data->input_dev;
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               mxt_stop(data);
+
+       mutex_unlock(&input_dev->mutex);
+
+       return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct mxt_data *data = i2c_get_clientdata(client);
+       struct input_dev *input_dev = data->input_dev;
+
+       /* Soft reset */
+       mxt_write_object(data, MXT_GEN_COMMAND,
+                       MXT_COMMAND_RESET, 1);
+
+       msleep(MXT_RESET_TIME);
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               mxt_start(data);
+
+       mutex_unlock(&input_dev->mutex);
+
+       return 0;
+}
+
+static const struct dev_pm_ops mxt_pm_ops = {
+       .suspend        = mxt_suspend,
+       .resume         = mxt_resume,
+};
+#endif
+
+static const struct i2c_device_id mxt_id[] = {
+       { "qt602240_ts", 0 },
+       { "atmel_mxt_ts", 0 },
+       { "mXT224", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mxt_id);
+
+static struct i2c_driver mxt_driver = {
+       .driver = {
+               .name   = "atmel_mxt_ts",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &mxt_pm_ops,
+#endif
+       },
+       .probe          = mxt_probe,
+       .remove         = __devexit_p(mxt_remove),
+       .id_table       = mxt_id,
+};
+
+static int __init mxt_init(void)
+{
+       return i2c_add_driver(&mxt_driver);
+}
+
+static void __exit mxt_exit(void)
+{
+       i2c_del_driver(&mxt_driver);
+}
+
+module_init(mxt_init);
+module_exit(mxt_exit);
+
+/* Module information */
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/qt602240_ts.c
deleted file mode 100644 (file)
index 4dcb0e8..0000000
+++ /dev/null
@@ -1,1406 +0,0 @@
-/*
- * AT42QT602240/ATMXT224 Touchscreen driver
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/i2c/qt602240_ts.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-/* Version */
-#define QT602240_VER_20                        20
-#define QT602240_VER_21                        21
-#define QT602240_VER_22                        22
-
-/* Slave addresses */
-#define QT602240_APP_LOW               0x4a
-#define QT602240_APP_HIGH              0x4b
-#define QT602240_BOOT_LOW              0x24
-#define QT602240_BOOT_HIGH             0x25
-
-/* Firmware */
-#define QT602240_FW_NAME               "qt602240.fw"
-
-/* Registers */
-#define QT602240_FAMILY_ID             0x00
-#define QT602240_VARIANT_ID            0x01
-#define QT602240_VERSION               0x02
-#define QT602240_BUILD                 0x03
-#define QT602240_MATRIX_X_SIZE         0x04
-#define QT602240_MATRIX_Y_SIZE         0x05
-#define QT602240_OBJECT_NUM            0x06
-#define QT602240_OBJECT_START          0x07
-
-#define QT602240_OBJECT_SIZE           6
-
-/* Object types */
-#define QT602240_DEBUG_DIAGNOSTIC      37
-#define QT602240_GEN_MESSAGE           5
-#define QT602240_GEN_COMMAND           6
-#define QT602240_GEN_POWER             7
-#define QT602240_GEN_ACQUIRE           8
-#define QT602240_TOUCH_MULTI           9
-#define QT602240_TOUCH_KEYARRAY                15
-#define QT602240_TOUCH_PROXIMITY       23
-#define QT602240_PROCI_GRIPFACE                20
-#define QT602240_PROCG_NOISE           22
-#define QT602240_PROCI_ONETOUCH                24
-#define QT602240_PROCI_TWOTOUCH                27
-#define QT602240_SPT_COMMSCONFIG       18      /* firmware ver 21 over */
-#define QT602240_SPT_GPIOPWM           19
-#define QT602240_SPT_SELFTEST          25
-#define QT602240_SPT_CTECONFIG         28
-#define QT602240_SPT_USERDATA          38      /* firmware ver 21 over */
-
-/* QT602240_GEN_COMMAND field */
-#define QT602240_COMMAND_RESET         0
-#define QT602240_COMMAND_BACKUPNV      1
-#define QT602240_COMMAND_CALIBRATE     2
-#define QT602240_COMMAND_REPORTALL     3
-#define QT602240_COMMAND_DIAGNOSTIC    5
-
-/* QT602240_GEN_POWER field */
-#define QT602240_POWER_IDLEACQINT      0
-#define QT602240_POWER_ACTVACQINT      1
-#define QT602240_POWER_ACTV2IDLETO     2
-
-/* QT602240_GEN_ACQUIRE field */
-#define QT602240_ACQUIRE_CHRGTIME      0
-#define QT602240_ACQUIRE_TCHDRIFT      2
-#define QT602240_ACQUIRE_DRIFTST       3
-#define QT602240_ACQUIRE_TCHAUTOCAL    4
-#define QT602240_ACQUIRE_SYNC          5
-#define QT602240_ACQUIRE_ATCHCALST     6
-#define QT602240_ACQUIRE_ATCHCALSTHR   7
-
-/* QT602240_TOUCH_MULTI field */
-#define QT602240_TOUCH_CTRL            0
-#define QT602240_TOUCH_XORIGIN         1
-#define QT602240_TOUCH_YORIGIN         2
-#define QT602240_TOUCH_XSIZE           3
-#define QT602240_TOUCH_YSIZE           4
-#define QT602240_TOUCH_BLEN            6
-#define QT602240_TOUCH_TCHTHR          7
-#define QT602240_TOUCH_TCHDI           8
-#define QT602240_TOUCH_ORIENT          9
-#define QT602240_TOUCH_MOVHYSTI                11
-#define QT602240_TOUCH_MOVHYSTN                12
-#define QT602240_TOUCH_NUMTOUCH                14
-#define QT602240_TOUCH_MRGHYST         15
-#define QT602240_TOUCH_MRGTHR          16
-#define QT602240_TOUCH_AMPHYST         17
-#define QT602240_TOUCH_XRANGE_LSB      18
-#define QT602240_TOUCH_XRANGE_MSB      19
-#define QT602240_TOUCH_YRANGE_LSB      20
-#define QT602240_TOUCH_YRANGE_MSB      21
-#define QT602240_TOUCH_XLOCLIP         22
-#define QT602240_TOUCH_XHICLIP         23
-#define QT602240_TOUCH_YLOCLIP         24
-#define QT602240_TOUCH_YHICLIP         25
-#define QT602240_TOUCH_XEDGECTRL       26
-#define QT602240_TOUCH_XEDGEDIST       27
-#define QT602240_TOUCH_YEDGECTRL       28
-#define QT602240_TOUCH_YEDGEDIST       29
-#define QT602240_TOUCH_JUMPLIMIT       30      /* firmware ver 22 over */
-
-/* QT602240_PROCI_GRIPFACE field */
-#define QT602240_GRIPFACE_CTRL         0
-#define QT602240_GRIPFACE_XLOGRIP      1
-#define QT602240_GRIPFACE_XHIGRIP      2
-#define QT602240_GRIPFACE_YLOGRIP      3
-#define QT602240_GRIPFACE_YHIGRIP      4
-#define QT602240_GRIPFACE_MAXTCHS      5
-#define QT602240_GRIPFACE_SZTHR1       7
-#define QT602240_GRIPFACE_SZTHR2       8
-#define QT602240_GRIPFACE_SHPTHR1      9
-#define QT602240_GRIPFACE_SHPTHR2      10
-#define QT602240_GRIPFACE_SUPEXTTO     11
-
-/* QT602240_PROCI_NOISE field */
-#define QT602240_NOISE_CTRL            0
-#define QT602240_NOISE_OUTFLEN         1
-#define QT602240_NOISE_GCAFUL_LSB      3
-#define QT602240_NOISE_GCAFUL_MSB      4
-#define QT602240_NOISE_GCAFLL_LSB      5
-#define QT602240_NOISE_GCAFLL_MSB      6
-#define QT602240_NOISE_ACTVGCAFVALID   7
-#define QT602240_NOISE_NOISETHR                8
-#define QT602240_NOISE_FREQHOPSCALE    10
-#define QT602240_NOISE_FREQ0           11
-#define QT602240_NOISE_FREQ1           12
-#define QT602240_NOISE_FREQ2           13
-#define QT602240_NOISE_FREQ3           14
-#define QT602240_NOISE_FREQ4           15
-#define QT602240_NOISE_IDLEGCAFVALID   16
-
-/* QT602240_SPT_COMMSCONFIG */
-#define QT602240_COMMS_CTRL            0
-#define QT602240_COMMS_CMD             1
-
-/* QT602240_SPT_CTECONFIG field */
-#define QT602240_CTE_CTRL              0
-#define QT602240_CTE_CMD               1
-#define QT602240_CTE_MODE              2
-#define QT602240_CTE_IDLEGCAFDEPTH     3
-#define QT602240_CTE_ACTVGCAFDEPTH     4
-#define QT602240_CTE_VOLTAGE           5       /* firmware ver 21 over */
-
-#define QT602240_VOLTAGE_DEFAULT       2700000
-#define QT602240_VOLTAGE_STEP          10000
-
-/* Define for QT602240_GEN_COMMAND */
-#define QT602240_BOOT_VALUE            0xa5
-#define QT602240_BACKUP_VALUE          0x55
-#define QT602240_BACKUP_TIME           25      /* msec */
-#define QT602240_RESET_TIME            65      /* msec */
-
-#define QT602240_FWRESET_TIME          175     /* msec */
-
-/* Command to unlock bootloader */
-#define QT602240_UNLOCK_CMD_MSB                0xaa
-#define QT602240_UNLOCK_CMD_LSB                0xdc
-
-/* Bootloader mode status */
-#define QT602240_WAITING_BOOTLOAD_CMD  0xc0    /* valid 7 6 bit only */
-#define QT602240_WAITING_FRAME_DATA    0x80    /* valid 7 6 bit only */
-#define QT602240_FRAME_CRC_CHECK       0x02
-#define QT602240_FRAME_CRC_FAIL                0x03
-#define QT602240_FRAME_CRC_PASS                0x04
-#define QT602240_APP_CRC_FAIL          0x40    /* valid 7 8 bit only */
-#define QT602240_BOOT_STATUS_MASK      0x3f
-
-/* Touch status */
-#define QT602240_SUPPRESS              (1 << 1)
-#define QT602240_AMP                   (1 << 2)
-#define QT602240_VECTOR                        (1 << 3)
-#define QT602240_MOVE                  (1 << 4)
-#define QT602240_RELEASE               (1 << 5)
-#define QT602240_PRESS                 (1 << 6)
-#define QT602240_DETECT                        (1 << 7)
-
-/* Touchscreen absolute values */
-#define QT602240_MAX_XC                        0x3ff
-#define QT602240_MAX_YC                        0x3ff
-#define QT602240_MAX_AREA              0xff
-
-#define QT602240_MAX_FINGER            10
-
-/* Initial register values recommended from chip vendor */
-static const u8 init_vals_ver_20[] = {
-       /* QT602240_GEN_COMMAND(6) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_GEN_POWER(7) */
-       0x20, 0xff, 0x32,
-       /* QT602240_GEN_ACQUIRE(8) */
-       0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14,
-       /* QT602240_TOUCH_MULTI(9) */
-       0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00,
-       0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64,
-       /* QT602240_TOUCH_KEYARRAY(15) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00,
-       /* QT602240_SPT_GPIOPWM(19) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       /* QT602240_PROCI_GRIPFACE(20) */
-       0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04,
-       0x1e, 0x00,
-       /* QT602240_PROCG_NOISE(22) */
-       0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00,
-       0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8,
-       /* QT602240_TOUCH_PROXIMITY(23) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00,
-       /* QT602240_PROCI_ONETOUCH(24) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_SELFTEST(25) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_TWOTOUCH(27) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_CTECONFIG(28) */
-       0x00, 0x00, 0x00, 0x04, 0x08,
-};
-
-static const u8 init_vals_ver_21[] = {
-       /* QT602240_GEN_COMMAND(6) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_GEN_POWER(7) */
-       0x20, 0xff, 0x32,
-       /* QT602240_GEN_ACQUIRE(8) */
-       0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-       /* QT602240_TOUCH_MULTI(9) */
-       0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-       0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_TOUCH_KEYARRAY(15) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00,
-       /* QT602240_SPT_GPIOPWM(19) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_GRIPFACE(20) */
-       0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-       0x0f, 0x0a,
-       /* QT602240_PROCG_NOISE(22) */
-       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-       0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-       /* QT602240_TOUCH_PROXIMITY(23) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00,
-       /* QT602240_PROCI_ONETOUCH(24) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_SELFTEST(25) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_TWOTOUCH(27) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_CTECONFIG(28) */
-       0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-static const u8 init_vals_ver_22[] = {
-       /* QT602240_GEN_COMMAND(6) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_GEN_POWER(7) */
-       0x20, 0xff, 0x32,
-       /* QT602240_GEN_ACQUIRE(8) */
-       0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-       /* QT602240_TOUCH_MULTI(9) */
-       0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-       0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00,
-       /* QT602240_TOUCH_KEYARRAY(15) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00,
-       /* QT602240_SPT_GPIOPWM(19) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_GRIPFACE(20) */
-       0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-       0x0f, 0x0a,
-       /* QT602240_PROCG_NOISE(22) */
-       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-       0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-       /* QT602240_TOUCH_PROXIMITY(23) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_ONETOUCH(24) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_SELFTEST(25) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       /* QT602240_PROCI_TWOTOUCH(27) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* QT602240_SPT_CTECONFIG(28) */
-       0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-struct qt602240_info {
-       u8 family_id;
-       u8 variant_id;
-       u8 version;
-       u8 build;
-       u8 matrix_xsize;
-       u8 matrix_ysize;
-       u8 object_num;
-};
-
-struct qt602240_object {
-       u8 type;
-       u16 start_address;
-       u8 size;
-       u8 instances;
-       u8 num_report_ids;
-
-       /* to map object and message */
-       u8 max_reportid;
-};
-
-struct qt602240_message {
-       u8 reportid;
-       u8 message[7];
-       u8 checksum;
-};
-
-struct qt602240_finger {
-       int status;
-       int x;
-       int y;
-       int area;
-};
-
-/* Each client has this additional data */
-struct qt602240_data {
-       struct i2c_client *client;
-       struct input_dev *input_dev;
-       const struct qt602240_platform_data *pdata;
-       struct qt602240_object *object_table;
-       struct qt602240_info info;
-       struct qt602240_finger finger[QT602240_MAX_FINGER];
-       unsigned int irq;
-};
-
-static bool qt602240_object_readable(unsigned int type)
-{
-       switch (type) {
-       case QT602240_GEN_MESSAGE:
-       case QT602240_GEN_COMMAND:
-       case QT602240_GEN_POWER:
-       case QT602240_GEN_ACQUIRE:
-       case QT602240_TOUCH_MULTI:
-       case QT602240_TOUCH_KEYARRAY:
-       case QT602240_TOUCH_PROXIMITY:
-       case QT602240_PROCI_GRIPFACE:
-       case QT602240_PROCG_NOISE:
-       case QT602240_PROCI_ONETOUCH:
-       case QT602240_PROCI_TWOTOUCH:
-       case QT602240_SPT_COMMSCONFIG:
-       case QT602240_SPT_GPIOPWM:
-       case QT602240_SPT_SELFTEST:
-       case QT602240_SPT_CTECONFIG:
-       case QT602240_SPT_USERDATA:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static bool qt602240_object_writable(unsigned int type)
-{
-       switch (type) {
-       case QT602240_GEN_COMMAND:
-       case QT602240_GEN_POWER:
-       case QT602240_GEN_ACQUIRE:
-       case QT602240_TOUCH_MULTI:
-       case QT602240_TOUCH_KEYARRAY:
-       case QT602240_TOUCH_PROXIMITY:
-       case QT602240_PROCI_GRIPFACE:
-       case QT602240_PROCG_NOISE:
-       case QT602240_PROCI_ONETOUCH:
-       case QT602240_PROCI_TWOTOUCH:
-       case QT602240_SPT_GPIOPWM:
-       case QT602240_SPT_SELFTEST:
-       case QT602240_SPT_CTECONFIG:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static void qt602240_dump_message(struct device *dev,
-                                 struct qt602240_message *message)
-{
-       dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
-       dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
-       dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
-       dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
-       dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
-       dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
-       dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
-       dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
-       dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
-}
-
-static int qt602240_check_bootloader(struct i2c_client *client,
-                                    unsigned int state)
-{
-       u8 val;
-
-recheck:
-       if (i2c_master_recv(client, &val, 1) != 1) {
-               dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
-               return -EIO;
-       }
-
-       switch (state) {
-       case QT602240_WAITING_BOOTLOAD_CMD:
-       case QT602240_WAITING_FRAME_DATA:
-               val &= ~QT602240_BOOT_STATUS_MASK;
-               break;
-       case QT602240_FRAME_CRC_PASS:
-               if (val == QT602240_FRAME_CRC_CHECK)
-                       goto recheck;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (val != state) {
-               dev_err(&client->dev, "Unvalid bootloader mode state\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int qt602240_unlock_bootloader(struct i2c_client *client)
-{
-       u8 buf[2];
-
-       buf[0] = QT602240_UNLOCK_CMD_LSB;
-       buf[1] = QT602240_UNLOCK_CMD_MSB;
-
-       if (i2c_master_send(client, buf, 2) != 2) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int qt602240_fw_write(struct i2c_client *client,
-                            const u8 *data, unsigned int frame_size)
-{
-       if (i2c_master_send(client, data, frame_size) != frame_size) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int __qt602240_read_reg(struct i2c_client *client,
-                              u16 reg, u16 len, void *val)
-{
-       struct i2c_msg xfer[2];
-       u8 buf[2];
-
-       buf[0] = reg & 0xff;
-       buf[1] = (reg >> 8) & 0xff;
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 2;
-       xfer[0].buf = buf;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = len;
-       xfer[1].buf = val;
-
-       if (i2c_transfer(client->adapter, xfer, 2) != 2) {
-               dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int qt602240_read_reg(struct i2c_client *client, u16 reg, u8 *val)
-{
-       return __qt602240_read_reg(client, reg, 1, val);
-}
-
-static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val)
-{
-       u8 buf[3];
-
-       buf[0] = reg & 0xff;
-       buf[1] = (reg >> 8) & 0xff;
-       buf[2] = val;
-
-       if (i2c_master_send(client, buf, 3) != 3) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int qt602240_read_object_table(struct i2c_client *client,
-                                     u16 reg, u8 *object_buf)
-{
-       return __qt602240_read_reg(client, reg, QT602240_OBJECT_SIZE,
-                                  object_buf);
-}
-
-static struct qt602240_object *
-qt602240_get_object(struct qt602240_data *data, u8 type)
-{
-       struct qt602240_object *object;
-       int i;
-
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
-               if (object->type == type)
-                       return object;
-       }
-
-       dev_err(&data->client->dev, "Invalid object type\n");
-       return NULL;
-}
-
-static int qt602240_read_message(struct qt602240_data *data,
-                                struct qt602240_message *message)
-{
-       struct qt602240_object *object;
-       u16 reg;
-
-       object = qt602240_get_object(data, QT602240_GEN_MESSAGE);
-       if (!object)
-               return -EINVAL;
-
-       reg = object->start_address;
-       return __qt602240_read_reg(data->client, reg,
-                       sizeof(struct qt602240_message), message);
-}
-
-static int qt602240_read_object(struct qt602240_data *data,
-                               u8 type, u8 offset, u8 *val)
-{
-       struct qt602240_object *object;
-       u16 reg;
-
-       object = qt602240_get_object(data, type);
-       if (!object)
-               return -EINVAL;
-
-       reg = object->start_address;
-       return __qt602240_read_reg(data->client, reg + offset, 1, val);
-}
-
-static int qt602240_write_object(struct qt602240_data *data,
-                                u8 type, u8 offset, u8 val)
-{
-       struct qt602240_object *object;
-       u16 reg;
-
-       object = qt602240_get_object(data, type);
-       if (!object)
-               return -EINVAL;
-
-       reg = object->start_address;
-       return qt602240_write_reg(data->client, reg + offset, val);
-}
-
-static void qt602240_input_report(struct qt602240_data *data, int single_id)
-{
-       struct qt602240_finger *finger = data->finger;
-       struct input_dev *input_dev = data->input_dev;
-       int status = finger[single_id].status;
-       int finger_num = 0;
-       int id;
-
-       for (id = 0; id < QT602240_MAX_FINGER; id++) {
-               if (!finger[id].status)
-                       continue;
-
-               input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-                               finger[id].status != QT602240_RELEASE ?
-                               finger[id].area : 0);
-               input_report_abs(input_dev, ABS_MT_POSITION_X,
-                               finger[id].x);
-               input_report_abs(input_dev, ABS_MT_POSITION_Y,
-                               finger[id].y);
-               input_mt_sync(input_dev);
-
-               if (finger[id].status == QT602240_RELEASE)
-                       finger[id].status = 0;
-               else
-                       finger_num++;
-       }
-
-       input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
-
-       if (status != QT602240_RELEASE) {
-               input_report_abs(input_dev, ABS_X, finger[single_id].x);
-               input_report_abs(input_dev, ABS_Y, finger[single_id].y);
-       }
-
-       input_sync(input_dev);
-}
-
-static void qt602240_input_touchevent(struct qt602240_data *data,
-                                     struct qt602240_message *message, int id)
-{
-       struct qt602240_finger *finger = data->finger;
-       struct device *dev = &data->client->dev;
-       u8 status = message->message[0];
-       int x;
-       int y;
-       int area;
-
-       /* Check the touch is present on the screen */
-       if (!(status & QT602240_DETECT)) {
-               if (status & QT602240_RELEASE) {
-                       dev_dbg(dev, "[%d] released\n", id);
-
-                       finger[id].status = QT602240_RELEASE;
-                       qt602240_input_report(data, id);
-               }
-               return;
-       }
-
-       /* Check only AMP detection */
-       if (!(status & (QT602240_PRESS | QT602240_MOVE)))
-               return;
-
-       x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
-       y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
-       area = message->message[4];
-
-       dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
-               status & QT602240_MOVE ? "moved" : "pressed",
-               x, y, area);
-
-       finger[id].status = status & QT602240_MOVE ?
-                               QT602240_MOVE : QT602240_PRESS;
-       finger[id].x = x;
-       finger[id].y = y;
-       finger[id].area = area;
-
-       qt602240_input_report(data, id);
-}
-
-static irqreturn_t qt602240_interrupt(int irq, void *dev_id)
-{
-       struct qt602240_data *data = dev_id;
-       struct qt602240_message message;
-       struct qt602240_object *object;
-       struct device *dev = &data->client->dev;
-       int id;
-       u8 reportid;
-       u8 max_reportid;
-       u8 min_reportid;
-
-       do {
-               if (qt602240_read_message(data, &message)) {
-                       dev_err(dev, "Failed to read message\n");
-                       goto end;
-               }
-
-               reportid = message.reportid;
-
-               /* whether reportid is thing of QT602240_TOUCH_MULTI */
-               object = qt602240_get_object(data, QT602240_TOUCH_MULTI);
-               if (!object)
-                       goto end;
-
-               max_reportid = object->max_reportid;
-               min_reportid = max_reportid - object->num_report_ids + 1;
-               id = reportid - min_reportid;
-
-               if (reportid >= min_reportid && reportid <= max_reportid)
-                       qt602240_input_touchevent(data, &message, id);
-               else
-                       qt602240_dump_message(dev, &message);
-       } while (reportid != 0xff);
-
-end:
-       return IRQ_HANDLED;
-}
-
-static int qt602240_check_reg_init(struct qt602240_data *data)
-{
-       struct qt602240_object *object;
-       struct device *dev = &data->client->dev;
-       int index = 0;
-       int i, j;
-       u8 version = data->info.version;
-       u8 *init_vals;
-
-       switch (version) {
-       case QT602240_VER_20:
-               init_vals = (u8 *)init_vals_ver_20;
-               break;
-       case QT602240_VER_21:
-               init_vals = (u8 *)init_vals_ver_21;
-               break;
-       case QT602240_VER_22:
-               init_vals = (u8 *)init_vals_ver_22;
-               break;
-       default:
-               dev_err(dev, "Firmware version %d doesn't support\n", version);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
-
-               if (!qt602240_object_writable(object->type))
-                       continue;
-
-               for (j = 0; j < object->size + 1; j++)
-                       qt602240_write_object(data, object->type, j,
-                                       init_vals[index + j]);
-
-               index += object->size + 1;
-       }
-
-       return 0;
-}
-
-static int qt602240_check_matrix_size(struct qt602240_data *data)
-{
-       const struct qt602240_platform_data *pdata = data->pdata;
-       struct device *dev = &data->client->dev;
-       int mode = -1;
-       int error;
-       u8 val;
-
-       dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line);
-       dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line);
-
-       switch (pdata->x_line) {
-       case 0 ... 15:
-               if (pdata->y_line <= 14)
-                       mode = 0;
-               break;
-       case 16:
-               if (pdata->y_line <= 12)
-                       mode = 1;
-               if (pdata->y_line == 13 || pdata->y_line == 14)
-                       mode = 0;
-               break;
-       case 17:
-               if (pdata->y_line <= 11)
-                       mode = 2;
-               if (pdata->y_line == 12 || pdata->y_line == 13)
-                       mode = 1;
-               break;
-       case 18:
-               if (pdata->y_line <= 10)
-                       mode = 3;
-               if (pdata->y_line == 11 || pdata->y_line == 12)
-                       mode = 2;
-               break;
-       case 19:
-               if (pdata->y_line <= 9)
-                       mode = 4;
-               if (pdata->y_line == 10 || pdata->y_line == 11)
-                       mode = 3;
-               break;
-       case 20:
-               mode = 4;
-       }
-
-       if (mode < 0) {
-               dev_err(dev, "Invalid X/Y lines\n");
-               return -EINVAL;
-       }
-
-       error = qt602240_read_object(data, QT602240_SPT_CTECONFIG,
-                               QT602240_CTE_MODE, &val);
-       if (error)
-               return error;
-
-       if (mode == val)
-               return 0;
-
-       /* Change the CTE configuration */
-       qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-                       QT602240_CTE_CTRL, 1);
-       qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-                       QT602240_CTE_MODE, mode);
-       qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-                       QT602240_CTE_CTRL, 0);
-
-       return 0;
-}
-
-static int qt602240_make_highchg(struct qt602240_data *data)
-{
-       struct device *dev = &data->client->dev;
-       int count = 10;
-       int error;
-       u8 val;
-
-       /* Read dummy message to make high CHG pin */
-       do {
-               error = qt602240_read_object(data, QT602240_GEN_MESSAGE, 0, &val);
-               if (error)
-                       return error;
-       } while ((val != 0xff) && --count);
-
-       if (!count) {
-               dev_err(dev, "CHG pin isn't cleared\n");
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static void qt602240_handle_pdata(struct qt602240_data *data)
-{
-       const struct qt602240_platform_data *pdata = data->pdata;
-       u8 voltage;
-
-       /* Set touchscreen lines */
-       qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_XSIZE,
-                       pdata->x_line);
-       qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_YSIZE,
-                       pdata->y_line);
-
-       /* Set touchscreen orient */
-       qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_ORIENT,
-                       pdata->orient);
-
-       /* Set touchscreen burst length */
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_BLEN, pdata->blen);
-
-       /* Set touchscreen threshold */
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_TCHTHR, pdata->threshold);
-
-       /* Set touchscreen resolution */
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-       qt602240_write_object(data, QT602240_TOUCH_MULTI,
-                       QT602240_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
-
-       /* Set touchscreen voltage */
-       if (data->info.version >= QT602240_VER_21 && pdata->voltage) {
-               if (pdata->voltage < QT602240_VOLTAGE_DEFAULT) {
-                       voltage = (QT602240_VOLTAGE_DEFAULT - pdata->voltage) /
-                               QT602240_VOLTAGE_STEP;
-                       voltage = 0xff - voltage + 1;
-               } else
-                       voltage = (pdata->voltage - QT602240_VOLTAGE_DEFAULT) /
-                               QT602240_VOLTAGE_STEP;
-
-               qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-                               QT602240_CTE_VOLTAGE, voltage);
-       }
-}
-
-static int qt602240_get_info(struct qt602240_data *data)
-{
-       struct i2c_client *client = data->client;
-       struct qt602240_info *info = &data->info;
-       int error;
-       u8 val;
-
-       error = qt602240_read_reg(client, QT602240_FAMILY_ID, &val);
-       if (error)
-               return error;
-       info->family_id = val;
-
-       error = qt602240_read_reg(client, QT602240_VARIANT_ID, &val);
-       if (error)
-               return error;
-       info->variant_id = val;
-
-       error = qt602240_read_reg(client, QT602240_VERSION, &val);
-       if (error)
-               return error;
-       info->version = val;
-
-       error = qt602240_read_reg(client, QT602240_BUILD, &val);
-       if (error)
-               return error;
-       info->build = val;
-
-       error = qt602240_read_reg(client, QT602240_OBJECT_NUM, &val);
-       if (error)
-               return error;
-       info->object_num = val;
-
-       return 0;
-}
-
-static int qt602240_get_object_table(struct qt602240_data *data)
-{
-       int error;
-       int i;
-       u16 reg;
-       u8 reportid = 0;
-       u8 buf[QT602240_OBJECT_SIZE];
-
-       for (i = 0; i < data->info.object_num; i++) {
-               struct qt602240_object *object = data->object_table + i;
-
-               reg = QT602240_OBJECT_START + QT602240_OBJECT_SIZE * i;
-               error = qt602240_read_object_table(data->client, reg, buf);
-               if (error)
-                       return error;
-
-               object->type = buf[0];
-               object->start_address = (buf[2] << 8) | buf[1];
-               object->size = buf[3];
-               object->instances = buf[4];
-               object->num_report_ids = buf[5];
-
-               if (object->num_report_ids) {
-                       reportid += object->num_report_ids *
-                                       (object->instances + 1);
-                       object->max_reportid = reportid;
-               }
-       }
-
-       return 0;
-}
-
-static int qt602240_initialize(struct qt602240_data *data)
-{
-       struct i2c_client *client = data->client;
-       struct qt602240_info *info = &data->info;
-       int error;
-       u8 val;
-
-       error = qt602240_get_info(data);
-       if (error)
-               return error;
-
-       data->object_table = kcalloc(info->object_num,
-                                    sizeof(struct qt602240_object),
-                                    GFP_KERNEL);
-       if (!data->object_table) {
-               dev_err(&client->dev, "Failed to allocate memory\n");
-               return -ENOMEM;
-       }
-
-       /* Get object table information */
-       error = qt602240_get_object_table(data);
-       if (error)
-               return error;
-
-       /* Check register init values */
-       error = qt602240_check_reg_init(data);
-       if (error)
-               return error;
-
-       /* Check X/Y matrix size */
-       error = qt602240_check_matrix_size(data);
-       if (error)
-               return error;
-
-       error = qt602240_make_highchg(data);
-       if (error)
-               return error;
-
-       qt602240_handle_pdata(data);
-
-       /* Backup to memory */
-       qt602240_write_object(data, QT602240_GEN_COMMAND,
-                       QT602240_COMMAND_BACKUPNV,
-                       QT602240_BACKUP_VALUE);
-       msleep(QT602240_BACKUP_TIME);
-
-       /* Soft reset */
-       qt602240_write_object(data, QT602240_GEN_COMMAND,
-                       QT602240_COMMAND_RESET, 1);
-       msleep(QT602240_RESET_TIME);
-
-       /* Update matrix size at info struct */
-       error = qt602240_read_reg(client, QT602240_MATRIX_X_SIZE, &val);
-       if (error)
-               return error;
-       info->matrix_xsize = val;
-
-       error = qt602240_read_reg(client, QT602240_MATRIX_Y_SIZE, &val);
-       if (error)
-               return error;
-       info->matrix_ysize = val;
-
-       dev_info(&client->dev,
-                       "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
-                       info->family_id, info->variant_id, info->version,
-                       info->build);
-
-       dev_info(&client->dev,
-                       "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
-                       info->matrix_xsize, info->matrix_ysize,
-                       info->object_num);
-
-       return 0;
-}
-
-static ssize_t qt602240_object_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       struct qt602240_data *data = dev_get_drvdata(dev);
-       struct qt602240_object *object;
-       int count = 0;
-       int i, j;
-       int error;
-       u8 val;
-
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
-
-               count += sprintf(buf + count,
-                               "Object Table Element %d(Type %d)\n",
-                               i + 1, object->type);
-
-               if (!qt602240_object_readable(object->type)) {
-                       count += sprintf(buf + count, "\n");
-                       continue;
-               }
-
-               for (j = 0; j < object->size + 1; j++) {
-                       error = qt602240_read_object(data,
-                                               object->type, j, &val);
-                       if (error)
-                               return error;
-
-                       count += sprintf(buf + count,
-                                       "  Byte %d: 0x%x (%d)\n", j, val, val);
-               }
-
-               count += sprintf(buf + count, "\n");
-       }
-
-       return count;
-}
-
-static int qt602240_load_fw(struct device *dev, const char *fn)
-{
-       struct qt602240_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = data->client;
-       const struct firmware *fw = NULL;
-       unsigned int frame_size;
-       unsigned int pos = 0;
-       int ret;
-
-       ret = request_firmware(&fw, fn, dev);
-       if (ret) {
-               dev_err(dev, "Unable to open firmware %s\n", fn);
-               return ret;
-       }
-
-       /* Change to the bootloader mode */
-       qt602240_write_object(data, QT602240_GEN_COMMAND,
-                       QT602240_COMMAND_RESET, QT602240_BOOT_VALUE);
-       msleep(QT602240_RESET_TIME);
-
-       /* Change to slave address of bootloader */
-       if (client->addr == QT602240_APP_LOW)
-               client->addr = QT602240_BOOT_LOW;
-       else
-               client->addr = QT602240_BOOT_HIGH;
-
-       ret = qt602240_check_bootloader(client, QT602240_WAITING_BOOTLOAD_CMD);
-       if (ret)
-               goto out;
-
-       /* Unlock bootloader */
-       qt602240_unlock_bootloader(client);
-
-       while (pos < fw->size) {
-               ret = qt602240_check_bootloader(client,
-                                               QT602240_WAITING_FRAME_DATA);
-               if (ret)
-                       goto out;
-
-               frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
-
-               /* We should add 2 at frame size as the the firmware data is not
-                * included the CRC bytes.
-                */
-               frame_size += 2;
-
-               /* Write one frame to device */
-               qt602240_fw_write(client, fw->data + pos, frame_size);
-
-               ret = qt602240_check_bootloader(client,
-                                               QT602240_FRAME_CRC_PASS);
-               if (ret)
-                       goto out;
-
-               pos += frame_size;
-
-               dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
-       }
-
-out:
-       release_firmware(fw);
-
-       /* Change to slave address of application */
-       if (client->addr == QT602240_BOOT_LOW)
-               client->addr = QT602240_APP_LOW;
-       else
-               client->addr = QT602240_APP_HIGH;
-
-       return ret;
-}
-
-static ssize_t qt602240_update_fw_store(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t count)
-{
-       struct qt602240_data *data = dev_get_drvdata(dev);
-       unsigned int version;
-       int error;
-
-       if (sscanf(buf, "%u", &version) != 1) {
-               dev_err(dev, "Invalid values\n");
-               return -EINVAL;
-       }
-
-       if (data->info.version < QT602240_VER_21 || version < QT602240_VER_21) {
-               dev_err(dev, "FW update supported starting with version 21\n");
-               return -EINVAL;
-       }
-
-       disable_irq(data->irq);
-
-       error = qt602240_load_fw(dev, QT602240_FW_NAME);
-       if (error) {
-               dev_err(dev, "The firmware update failed(%d)\n", error);
-               count = error;
-       } else {
-               dev_dbg(dev, "The firmware update succeeded\n");
-
-               /* Wait for reset */
-               msleep(QT602240_FWRESET_TIME);
-
-               kfree(data->object_table);
-               data->object_table = NULL;
-
-               qt602240_initialize(data);
-       }
-
-       enable_irq(data->irq);
-
-       return count;
-}
-
-static DEVICE_ATTR(object, 0444, qt602240_object_show, NULL);
-static DEVICE_ATTR(update_fw, 0664, NULL, qt602240_update_fw_store);
-
-static struct attribute *qt602240_attrs[] = {
-       &dev_attr_object.attr,
-       &dev_attr_update_fw.attr,
-       NULL
-};
-
-static const struct attribute_group qt602240_attr_group = {
-       .attrs = qt602240_attrs,
-};
-
-static void qt602240_start(struct qt602240_data *data)
-{
-       /* Touch enable */
-       qt602240_write_object(data,
-                       QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0x83);
-}
-
-static void qt602240_stop(struct qt602240_data *data)
-{
-       /* Touch disable */
-       qt602240_write_object(data,
-                       QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0);
-}
-
-static int qt602240_input_open(struct input_dev *dev)
-{
-       struct qt602240_data *data = input_get_drvdata(dev);
-
-       qt602240_start(data);
-
-       return 0;
-}
-
-static void qt602240_input_close(struct input_dev *dev)
-{
-       struct qt602240_data *data = input_get_drvdata(dev);
-
-       qt602240_stop(data);
-}
-
-static int __devinit qt602240_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       struct qt602240_data *data;
-       struct input_dev *input_dev;
-       int error;
-
-       if (!client->dev.platform_data)
-               return -EINVAL;
-
-       data = kzalloc(sizeof(struct qt602240_data), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!data || !input_dev) {
-               dev_err(&client->dev, "Failed to allocate memory\n");
-               error = -ENOMEM;
-               goto err_free_mem;
-       }
-
-       input_dev->name = "AT42QT602240/ATMXT224 Touchscreen";
-       input_dev->id.bustype = BUS_I2C;
-       input_dev->dev.parent = &client->dev;
-       input_dev->open = qt602240_input_open;
-       input_dev->close = qt602240_input_close;
-
-       __set_bit(EV_ABS, input_dev->evbit);
-       __set_bit(EV_KEY, input_dev->evbit);
-       __set_bit(BTN_TOUCH, input_dev->keybit);
-
-       /* For single touch */
-       input_set_abs_params(input_dev, ABS_X,
-                            0, QT602240_MAX_XC, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y,
-                            0, QT602240_MAX_YC, 0, 0);
-
-       /* For multi touch */
-       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-                            0, QT602240_MAX_AREA, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-                            0, QT602240_MAX_XC, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-                            0, QT602240_MAX_YC, 0, 0);
-
-       input_set_drvdata(input_dev, data);
-
-       data->client = client;
-       data->input_dev = input_dev;
-       data->pdata = client->dev.platform_data;
-       data->irq = client->irq;
-
-       i2c_set_clientdata(client, data);
-
-       error = qt602240_initialize(data);
-       if (error)
-               goto err_free_object;
-
-       error = request_threaded_irq(client->irq, NULL, qt602240_interrupt,
-                       IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
-       if (error) {
-               dev_err(&client->dev, "Failed to register interrupt\n");
-               goto err_free_object;
-       }
-
-       error = input_register_device(input_dev);
-       if (error)
-               goto err_free_irq;
-
-       error = sysfs_create_group(&client->dev.kobj, &qt602240_attr_group);
-       if (error)
-               goto err_unregister_device;
-
-       return 0;
-
-err_unregister_device:
-       input_unregister_device(input_dev);
-       input_dev = NULL;
-err_free_irq:
-       free_irq(client->irq, data);
-err_free_object:
-       kfree(data->object_table);
-err_free_mem:
-       input_free_device(input_dev);
-       kfree(data);
-       return error;
-}
-
-static int __devexit qt602240_remove(struct i2c_client *client)
-{
-       struct qt602240_data *data = i2c_get_clientdata(client);
-
-       sysfs_remove_group(&client->dev.kobj, &qt602240_attr_group);
-       free_irq(data->irq, data);
-       input_unregister_device(data->input_dev);
-       kfree(data->object_table);
-       kfree(data);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int qt602240_suspend(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct qt602240_data *data = i2c_get_clientdata(client);
-       struct input_dev *input_dev = data->input_dev;
-
-       mutex_lock(&input_dev->mutex);
-
-       if (input_dev->users)
-               qt602240_stop(data);
-
-       mutex_unlock(&input_dev->mutex);
-
-       return 0;
-}
-
-static int qt602240_resume(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct qt602240_data *data = i2c_get_clientdata(client);
-       struct input_dev *input_dev = data->input_dev;
-
-       /* Soft reset */
-       qt602240_write_object(data, QT602240_GEN_COMMAND,
-                       QT602240_COMMAND_RESET, 1);
-
-       msleep(QT602240_RESET_TIME);
-
-       mutex_lock(&input_dev->mutex);
-
-       if (input_dev->users)
-               qt602240_start(data);
-
-       mutex_unlock(&input_dev->mutex);
-
-       return 0;
-}
-
-static const struct dev_pm_ops qt602240_pm_ops = {
-       .suspend        = qt602240_suspend,
-       .resume         = qt602240_resume,
-};
-#endif
-
-static const struct i2c_device_id qt602240_id[] = {
-       { "qt602240_ts", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, qt602240_id);
-
-static struct i2c_driver qt602240_driver = {
-       .driver = {
-               .name   = "qt602240_ts",
-               .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
-               .pm     = &qt602240_pm_ops,
-#endif
-       },
-       .probe          = qt602240_probe,
-       .remove         = __devexit_p(qt602240_remove),
-       .id_table       = qt602240_id,
-};
-
-static int __init qt602240_init(void)
-{
-       return i2c_add_driver(&qt602240_driver);
-}
-
-static void __exit qt602240_exit(void)
-{
-       i2c_del_driver(&qt602240_driver);
-}
-
-module_init(qt602240_init);
-module_exit(qt602240_exit);
-
-/* Module information */
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_DESCRIPTION("AT42QT602240/ATMXT224 Touchscreen driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
new file mode 100644 (file)
index 0000000..8742061
--- /dev/null
@@ -0,0 +1,756 @@
+/*
+ * TSC2005 touchscreen driver
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ *
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/tsc2005.h>
+
+/*
+ * The touchscreen interface operates as follows:
+ *
+ * 1) Pen is pressed against the touchscreen.
+ * 2) TSC2005 performs AD conversion.
+ * 3) After the conversion is done TSC2005 drives DAV line down.
+ * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
+ * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
+ *    values.
+ * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
+ *    tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
+ * 7) When the penup timer expires, there have not been touch or DAV interrupts
+ *    during the last 40ms which means the pen has been lifted.
+ *
+ * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
+ * after a configurable period (in ms) of activity. If esd_timeout is 0, the
+ * watchdog is disabled.
+ */
+
+/* control byte 1 */
+#define TSC2005_CMD                    0x80
+#define TSC2005_CMD_NORMAL             0x00
+#define TSC2005_CMD_STOP               0x01
+#define TSC2005_CMD_12BIT              0x04
+
+/* control byte 0 */
+#define TSC2005_REG_READ               0x0001
+#define TSC2005_REG_PND0               0x0002
+#define TSC2005_REG_X                  0x0000
+#define TSC2005_REG_Y                  0x0008
+#define TSC2005_REG_Z1                 0x0010
+#define TSC2005_REG_Z2                 0x0018
+#define TSC2005_REG_TEMP_HIGH          0x0050
+#define TSC2005_REG_CFR0               0x0060
+#define TSC2005_REG_CFR1               0x0068
+#define TSC2005_REG_CFR2               0x0070
+
+/* configuration register 0 */
+#define TSC2005_CFR0_PRECHARGE_276US   0x0040
+#define TSC2005_CFR0_STABTIME_1MS      0x0300
+#define TSC2005_CFR0_CLOCK_1MHZ                0x1000
+#define TSC2005_CFR0_RESOLUTION12      0x2000
+#define TSC2005_CFR0_PENMODE           0x8000
+#define TSC2005_CFR0_INITVALUE         (TSC2005_CFR0_STABTIME_1MS    | \
+                                        TSC2005_CFR0_CLOCK_1MHZ      | \
+                                        TSC2005_CFR0_RESOLUTION12    | \
+                                        TSC2005_CFR0_PRECHARGE_276US | \
+                                        TSC2005_CFR0_PENMODE)
+
+/* bits common to both read and write of configuration register 0 */
+#define        TSC2005_CFR0_RW_MASK            0x3fff
+
+/* configuration register 1 */
+#define TSC2005_CFR1_BATCHDELAY_4MS    0x0003
+#define TSC2005_CFR1_INITVALUE         TSC2005_CFR1_BATCHDELAY_4MS
+
+/* configuration register 2 */
+#define TSC2005_CFR2_MAVE_Z            0x0004
+#define TSC2005_CFR2_MAVE_Y            0x0008
+#define TSC2005_CFR2_MAVE_X            0x0010
+#define TSC2005_CFR2_AVG_7             0x0800
+#define TSC2005_CFR2_MEDIUM_15         0x3000
+#define TSC2005_CFR2_INITVALUE         (TSC2005_CFR2_MAVE_X    | \
+                                        TSC2005_CFR2_MAVE_Y    | \
+                                        TSC2005_CFR2_MAVE_Z    | \
+                                        TSC2005_CFR2_MEDIUM_15 | \
+                                        TSC2005_CFR2_AVG_7)
+
+#define MAX_12BIT                      0xfff
+#define TSC2005_SPI_MAX_SPEED_HZ       10000000
+#define TSC2005_PENUP_TIME_MS          40
+
+struct tsc2005_spi_rd {
+       struct spi_transfer     spi_xfer;
+       u32                     spi_tx;
+       u32                     spi_rx;
+};
+
+struct tsc2005 {
+       struct spi_device       *spi;
+
+       struct spi_message      spi_read_msg;
+       struct tsc2005_spi_rd   spi_x;
+       struct tsc2005_spi_rd   spi_y;
+       struct tsc2005_spi_rd   spi_z1;
+       struct tsc2005_spi_rd   spi_z2;
+
+       struct input_dev        *idev;
+       char                    phys[32];
+
+       struct mutex            mutex;
+
+       /* raw copy of previous x,y,z */
+       int                     in_x;
+       int                     in_y;
+       int                     in_z1;
+       int                     in_z2;
+
+       spinlock_t              lock;
+       struct timer_list       penup_timer;
+
+       unsigned int            esd_timeout;
+       struct delayed_work     esd_work;
+       unsigned long           last_valid_interrupt;
+
+       unsigned int            x_plate_ohm;
+
+       bool                    opened;
+       bool                    suspended;
+
+       bool                    pen_down;
+
+       void                    (*set_reset)(bool enable);
+};
+
+static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
+{
+       u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
+       struct spi_transfer xfer = {
+               .tx_buf         = &tx,
+               .len            = 1,
+               .bits_per_word  = 8,
+       };
+       struct spi_message msg;
+       int error;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       error = spi_sync(ts->spi, &msg);
+       if (error) {
+               dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
+                       __func__, cmd, error);
+               return error;
+       }
+
+       return 0;
+}
+
+static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value)
+{
+       u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value;
+       struct spi_transfer xfer = {
+               .tx_buf         = &tx,
+               .len            = 4,
+               .bits_per_word  = 24,
+       };
+       struct spi_message msg;
+       int error;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       error = spi_sync(ts->spi, &msg);
+       if (error) {
+               dev_err(&ts->spi->dev,
+                       "%s: failed, register: %x, value: %x, error: %d\n",
+                       __func__, reg, value, error);
+               return error;
+       }
+
+       return 0;
+}
+
+static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last)
+{
+       memset(rd, 0, sizeof(*rd));
+
+       rd->spi_tx                 = (reg | TSC2005_REG_READ) << 16;
+       rd->spi_xfer.tx_buf        = &rd->spi_tx;
+       rd->spi_xfer.rx_buf        = &rd->spi_rx;
+       rd->spi_xfer.len           = 4;
+       rd->spi_xfer.bits_per_word = 24;
+       rd->spi_xfer.cs_change     = !last;
+}
+
+static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value)
+{
+       struct tsc2005_spi_rd spi_rd;
+       struct spi_message msg;
+       int error;
+
+       tsc2005_setup_read(&spi_rd, reg, true);
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&spi_rd.spi_xfer, &msg);
+
+       error = spi_sync(ts->spi, &msg);
+       if (error)
+               return error;
+
+       *value = spi_rd.spi_rx;
+       return 0;
+}
+
+static void tsc2005_update_pen_state(struct tsc2005 *ts,
+                                    int x, int y, int pressure)
+{
+       if (pressure) {
+               input_report_abs(ts->idev, ABS_X, x);
+               input_report_abs(ts->idev, ABS_Y, y);
+               input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+               if (!ts->pen_down) {
+                       input_report_key(ts->idev, BTN_TOUCH, !!pressure);
+                       ts->pen_down = true;
+               }
+       } else {
+               input_report_abs(ts->idev, ABS_PRESSURE, 0);
+               if (ts->pen_down) {
+                       input_report_key(ts->idev, BTN_TOUCH, 0);
+                       ts->pen_down = false;
+               }
+       }
+       input_sync(ts->idev);
+       dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
+               pressure);
+}
+
+static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
+{
+       struct tsc2005 *ts = _ts;
+       unsigned long flags;
+       unsigned int pressure;
+       u32 x, y;
+       u32 z1, z2;
+       int error;
+
+       /* read the coordinates */
+       error = spi_sync(ts->spi, &ts->spi_read_msg);
+       if (unlikely(error))
+               goto out;
+
+       x = ts->spi_x.spi_rx;
+       y = ts->spi_y.spi_rx;
+       z1 = ts->spi_z1.spi_rx;
+       z2 = ts->spi_z2.spi_rx;
+
+       /* validate position */
+       if (unlikely(x > MAX_12BIT || y > MAX_12BIT))
+               goto out;
+
+       /* Skip reading if the pressure components are out of range */
+       if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2))
+               goto out;
+
+       /*
+       * Skip point if this is a pen down with the exact same values as
+       * the value before pen-up - that implies SPI fed us stale data
+       */
+       if (!ts->pen_down &&
+           ts->in_x == x && ts->in_y == y &&
+           ts->in_z1 == z1 && ts->in_z2 == z2) {
+               goto out;
+       }
+
+       /*
+        * At this point we are happy we have a valid and useful reading.
+        * Remember it for later comparisons. We may now begin downsampling.
+        */
+       ts->in_x = x;
+       ts->in_y = y;
+       ts->in_z1 = z1;
+       ts->in_z2 = z2;
+
+       /* Compute touch pressure resistance using equation #1 */
+       pressure = x * (z2 - z1) / z1;
+       pressure = pressure * ts->x_plate_ohm / 4096;
+       if (unlikely(pressure > MAX_12BIT))
+               goto out;
+
+       spin_lock_irqsave(&ts->lock, flags);
+
+       tsc2005_update_pen_state(ts, x, y, pressure);
+       mod_timer(&ts->penup_timer,
+                 jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
+
+       spin_unlock_irqrestore(&ts->lock, flags);
+
+       ts->last_valid_interrupt = jiffies;
+out:
+       return IRQ_HANDLED;
+}
+
+static void tsc2005_penup_timer(unsigned long data)
+{
+       struct tsc2005 *ts = (struct tsc2005 *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ts->lock, flags);
+       tsc2005_update_pen_state(ts, 0, 0, 0);
+       spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void tsc2005_start_scan(struct tsc2005 *ts)
+{
+       tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
+       tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
+       tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
+       tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
+}
+
+static void tsc2005_stop_scan(struct tsc2005 *ts)
+{
+       tsc2005_cmd(ts, TSC2005_CMD_STOP);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_disable(struct tsc2005 *ts)
+{
+       tsc2005_stop_scan(ts);
+
+       disable_irq(ts->spi->irq);
+       del_timer_sync(&ts->penup_timer);
+
+       cancel_delayed_work_sync(&ts->esd_work);
+
+       enable_irq(ts->spi->irq);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_enable(struct tsc2005 *ts)
+{
+       tsc2005_start_scan(ts);
+
+       if (ts->esd_timeout && ts->set_reset) {
+               ts->last_valid_interrupt = jiffies;
+               schedule_delayed_work(&ts->esd_work,
+                               round_jiffies(jiffies +
+                                       msecs_to_jiffies(ts->esd_timeout)));
+       }
+
+}
+
+static ssize_t tsc2005_selftest_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct tsc2005 *ts = spi_get_drvdata(spi);
+       u16 temp_high;
+       u16 temp_high_orig;
+       u16 temp_high_test;
+       bool success = true;
+       int error;
+
+       mutex_lock(&ts->mutex);
+
+       /*
+        * Test TSC2005 communications via temp high register.
+        */
+       __tsc2005_disable(ts);
+
+       error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d\n", error);
+               success = false;
+               goto out;
+       }
+
+       temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
+
+       error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test);
+       if (error) {
+               dev_warn(dev, "selftest failed: write error %d\n", error);
+               success = false;
+               goto out;
+       }
+
+       error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d after write\n",
+                        error);
+               success = false;
+               goto out;
+       }
+
+       if (temp_high != temp_high_test) {
+               dev_warn(dev, "selftest failed: %d != %d\n",
+                        temp_high, temp_high_test);
+               success = false;
+       }
+
+       /* hardware reset */
+       ts->set_reset(false);
+       usleep_range(100, 500); /* only 10us required */
+       ts->set_reset(true);
+
+       if (!success)
+               goto out;
+
+       /* test that the reset really happened */
+       error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d after reset\n",
+                        error);
+               success = false;
+               goto out;
+       }
+
+       if (temp_high != temp_high_orig) {
+               dev_warn(dev, "selftest failed after reset: %d != %d\n",
+                        temp_high, temp_high_orig);
+               success = false;
+       }
+
+out:
+       __tsc2005_enable(ts);
+       mutex_unlock(&ts->mutex);
+
+       return sprintf(buf, "%d\n", success);
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
+
+static struct attribute *tsc2005_attrs[] = {
+       &dev_attr_selftest.attr,
+       NULL
+};
+
+static mode_t tsc2005_attr_is_visible(struct kobject *kobj,
+                                     struct attribute *attr, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct spi_device *spi = to_spi_device(dev);
+       struct tsc2005 *ts = spi_get_drvdata(spi);
+       mode_t mode = attr->mode;
+
+       if (attr == &dev_attr_selftest.attr) {
+               if (!ts->set_reset)
+                       mode = 0;
+       }
+
+       return mode;
+}
+
+static const struct attribute_group tsc2005_attr_group = {
+       .is_visible     = tsc2005_attr_is_visible,
+       .attrs          = tsc2005_attrs,
+};
+
+static void tsc2005_esd_work(struct work_struct *work)
+{
+       struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
+       int error;
+       u16 r;
+
+       mutex_lock(&ts->mutex);
+
+       if (time_is_after_jiffies(ts->last_valid_interrupt +
+                                 msecs_to_jiffies(ts->esd_timeout)))
+               goto out;
+
+       /* We should be able to read register without disabling interrupts. */
+       error = tsc2005_read(ts, TSC2005_REG_CFR0, &r);
+       if (!error &&
+           !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
+               goto out;
+       }
+
+       /*
+        * If we could not read our known value from configuration register 0
+        * then we should reset the controller as if from power-up and start
+        * scanning again.
+        */
+       dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
+
+       disable_irq(ts->spi->irq);
+       del_timer_sync(&ts->penup_timer);
+
+       tsc2005_update_pen_state(ts, 0, 0, 0);
+
+       ts->set_reset(false);
+       usleep_range(100, 500); /* only 10us required */
+       ts->set_reset(true);
+
+       enable_irq(ts->spi->irq);
+       tsc2005_start_scan(ts);
+
+out:
+       /* re-arm the watchdog */
+       schedule_delayed_work(&ts->esd_work,
+                             round_jiffies(jiffies +
+                                       msecs_to_jiffies(ts->esd_timeout)));
+       mutex_unlock(&ts->mutex);
+}
+
+static int tsc2005_open(struct input_dev *input)
+{
+       struct tsc2005 *ts = input_get_drvdata(input);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended)
+               __tsc2005_enable(ts);
+
+       ts->opened = true;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+
+static void tsc2005_close(struct input_dev *input)
+{
+       struct tsc2005 *ts = input_get_drvdata(input);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended)
+               __tsc2005_disable(ts);
+
+       ts->opened = false;
+
+       mutex_unlock(&ts->mutex);
+}
+
+static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+{
+       tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false);
+       tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false);
+       tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, false);
+       tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, true);
+
+       spi_message_init(&ts->spi_read_msg);
+       spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg);
+       spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg);
+       spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg);
+       spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
+}
+
+static int __devinit tsc2005_probe(struct spi_device *spi)
+{
+       const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
+       struct tsc2005 *ts;
+       struct input_dev *input_dev;
+       unsigned int max_x, max_y, max_p;
+       unsigned int fudge_x, fudge_y, fudge_p;
+       int error;
+
+       if (!pdata) {
+               dev_dbg(&spi->dev, "no platform data\n");
+               return -ENODEV;
+       }
+
+       fudge_x = pdata->ts_x_fudge        ? : 4;
+       fudge_y = pdata->ts_y_fudge        ? : 8;
+       fudge_p = pdata->ts_pressure_fudge ? : 2;
+       max_x   = pdata->ts_x_max          ? : MAX_12BIT;
+       max_y   = pdata->ts_y_max          ? : MAX_12BIT;
+       max_p   = pdata->ts_pressure_max   ? : MAX_12BIT;
+
+       if (spi->irq <= 0) {
+               dev_dbg(&spi->dev, "no irq\n");
+               return -ENODEV;
+       }
+
+       spi->mode = SPI_MODE_0;
+       spi->bits_per_word = 8;
+       if (!spi->max_speed_hz)
+               spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
+
+       error = spi_setup(spi);
+       if (error)
+               return error;
+
+       ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!ts || !input_dev) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       ts->spi = spi;
+       ts->idev = input_dev;
+
+       ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280;
+       ts->esd_timeout = pdata->esd_timeout_ms;
+       ts->set_reset   = pdata->set_reset;
+
+       mutex_init(&ts->mutex);
+
+       spin_lock_init(&ts->lock);
+       setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
+
+       INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
+
+       tsc2005_setup_spi_xfer(ts);
+
+       snprintf(ts->phys, sizeof(ts->phys),
+                "%s/input-ts", dev_name(&spi->dev));
+
+       input_dev->name = "TSC2005 touchscreen";
+       input_dev->phys = ts->phys;
+       input_dev->id.bustype = BUS_SPI;
+       input_dev->dev.parent = &spi->dev;
+       input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
+
+       input_dev->open = tsc2005_open;
+       input_dev->close = tsc2005_close;
+
+       input_set_drvdata(input_dev, ts);
+
+       /* Ensure the touchscreen is off */
+       tsc2005_stop_scan(ts);
+
+       error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread,
+                                    IRQF_TRIGGER_RISING, "tsc2005", ts);
+       if (error) {
+               dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
+               goto err_free_mem;
+       }
+
+       spi_set_drvdata(spi, ts);
+       error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
+       if (error) {
+               dev_err(&spi->dev,
+                       "Failed to create sysfs attributes, err: %d\n", error);
+               goto err_clear_drvdata;
+       }
+
+       error = input_register_device(ts->idev);
+       if (error) {
+               dev_err(&spi->dev,
+                       "Failed to register input device, err: %d\n", error);
+               goto err_remove_sysfs;
+       }
+
+       set_irq_wake(spi->irq, 1);
+       return 0;
+
+err_remove_sysfs:
+       sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
+err_clear_drvdata:
+       spi_set_drvdata(spi, NULL);
+       free_irq(spi->irq, ts);
+err_free_mem:
+       input_free_device(input_dev);
+       kfree(ts);
+       return error;
+}
+
+static int __devexit tsc2005_remove(struct spi_device *spi)
+{
+       struct tsc2005 *ts = spi_get_drvdata(spi);
+
+       sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
+
+       free_irq(ts->spi->irq, ts);
+       input_unregister_device(ts->idev);
+       kfree(ts);
+
+       spi_set_drvdata(spi, NULL);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tsc2005_suspend(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct tsc2005 *ts = spi_get_drvdata(spi);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended && ts->opened)
+               __tsc2005_disable(ts);
+
+       ts->suspended = true;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+
+static int tsc2005_resume(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct tsc2005 *ts = spi_get_drvdata(spi);
+
+       mutex_lock(&ts->mutex);
+
+       if (ts->suspended && ts->opened)
+               __tsc2005_enable(ts);
+
+       ts->suspended = false;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
+
+static struct spi_driver tsc2005_driver = {
+       .driver = {
+               .name   = "tsc2005",
+               .owner  = THIS_MODULE,
+               .pm     = &tsc2005_pm_ops,
+       },
+       .probe  = tsc2005_probe,
+       .remove = __devexit_p(tsc2005_remove),
+};
+
+static int __init tsc2005_init(void)
+{
+       return spi_register_driver(&tsc2005_driver);
+}
+module_init(tsc2005_init);
+
+static void __exit tsc2005_exit(void)
+{
+       spi_unregister_driver(&tsc2005_driver);
+}
+module_exit(tsc2005_exit);
+
+MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
new file mode 100644 (file)
index 0000000..6ae054f
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Touchscreen driver for WM831x PMICs
+ *
+ * Copyright 2011 Wolfson Microelectronics plc.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/*
+ * R16424 (0x4028) - Touch Control 1
+ */
+#define WM831X_TCH_ENA                          0x8000  /* TCH_ENA */
+#define WM831X_TCH_CVT_ENA                      0x4000  /* TCH_CVT_ENA */
+#define WM831X_TCH_SLPENA                       0x1000  /* TCH_SLPENA */
+#define WM831X_TCH_Z_ENA                        0x0400  /* TCH_Z_ENA */
+#define WM831X_TCH_Y_ENA                        0x0200  /* TCH_Y_ENA */
+#define WM831X_TCH_X_ENA                        0x0100  /* TCH_X_ENA */
+#define WM831X_TCH_DELAY_MASK                   0x00E0  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_SHIFT                       5  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_WIDTH                       3  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_RATE_MASK                    0x001F  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_SHIFT                        0  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_WIDTH                        5  /* TCH_RATE - [4:0] */
+
+/*
+ * R16425 (0x4029) - Touch Control 2
+ */
+#define WM831X_TCH_PD_WK                        0x2000  /* TCH_PD_WK */
+#define WM831X_TCH_5WIRE                        0x1000  /* TCH_5WIRE */
+#define WM831X_TCH_PDONLY                       0x0800  /* TCH_PDONLY */
+#define WM831X_TCH_ISEL                         0x0100  /* TCH_ISEL */
+#define WM831X_TCH_RPU_MASK                     0x000F  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_SHIFT                         0  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_WIDTH                         4  /* TCH_RPU - [3:0] */
+
+/*
+ * R16426-8 (0x402A-C) - Touch Data X/Y/X
+ */
+#define WM831X_TCH_PD                           0x8000  /* TCH_PD1 */
+#define WM831X_TCH_DATA_MASK                    0x0FFF  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_SHIFT                        0  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_WIDTH                       12  /* TCH_DATA - [11:0] */
+
+struct wm831x_ts {
+       struct input_dev *input_dev;
+       struct wm831x *wm831x;
+       unsigned int data_irq;
+       unsigned int pd_irq;
+       bool pressure;
+       bool pen_down;
+};
+
+static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
+{
+       struct wm831x_ts *wm831x_ts = irq_data;
+       struct wm831x *wm831x = wm831x_ts->wm831x;
+       static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE };
+       u16 data[3];
+       int count;
+       int i, ret;
+
+       if (wm831x_ts->pressure)
+               count = 3;
+       else
+               count = 2;
+
+       wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+                       WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+       ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count,
+                              data);
+       if (ret != 0) {
+               dev_err(wm831x->dev, "Failed to read touch data: %d\n",
+                       ret);
+               return IRQ_NONE;
+       }
+
+       /*
+        * We get a pen down reading on every reading, report pen up if any
+        * individual reading does so.
+        */
+       wm831x_ts->pen_down = true;
+       for (i = 0; i < count; i++) {
+               if (!(data[i] & WM831X_TCH_PD)) {
+                       wm831x_ts->pen_down = false;
+                       continue;
+               }
+               input_report_abs(wm831x_ts->input_dev, data_types[i],
+                                data[i] & WM831X_TCH_DATA_MASK);
+       }
+
+       if (!wm831x_ts->pen_down) {
+               disable_irq_nosync(wm831x_ts->data_irq);
+
+               /* Don't need data any more */
+               wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                               WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+                               WM831X_TCH_Z_ENA, 0);
+
+               /* Flush any final samples that arrived while reading */
+               wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+                               WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+               wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data);
+
+               if (wm831x_ts->pressure)
+                       input_report_abs(wm831x_ts->input_dev,
+                                        ABS_PRESSURE, 0);
+
+               input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
+       }
+
+       input_sync(wm831x_ts->input_dev);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
+{
+       struct wm831x_ts *wm831x_ts = irq_data;
+       struct wm831x *wm831x = wm831x_ts->wm831x;
+       int ena = 0;
+
+       /* Start collecting data */
+       if (wm831x_ts->pressure)
+               ena |= WM831X_TCH_Z_ENA;
+
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
+                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
+
+       input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
+       input_sync(wm831x_ts->input_dev);
+
+       wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+                       WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
+
+       wm831x_ts->pen_down = true;
+       enable_irq(wm831x_ts->data_irq);
+
+       return IRQ_HANDLED;
+}
+
+static int wm831x_ts_input_open(struct input_dev *idev)
+{
+       struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+       struct wm831x *wm831x = wm831x_ts->wm831x;
+
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                       WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
+                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+                       WM831X_TCH_Z_ENA, WM831X_TCH_ENA);
+
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                       WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA);
+
+       return 0;
+}
+
+static void wm831x_ts_input_close(struct input_dev *idev)
+{
+       struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+       struct wm831x *wm831x = wm831x_ts->wm831x;
+
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                       WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
+                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+                       WM831X_TCH_Z_ENA, 0);
+
+       if (wm831x_ts->pen_down)
+               disable_irq(wm831x_ts->data_irq);
+}
+
+static __devinit int wm831x_ts_probe(struct platform_device *pdev)
+{
+       struct wm831x_ts *wm831x_ts;
+       struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+       struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
+       struct wm831x_touch_pdata *pdata = NULL;
+       struct input_dev *input_dev;
+       int error;
+
+       if (core_pdata)
+               pdata = core_pdata->touch;
+
+       wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!wm831x_ts || !input_dev) {
+               error = -ENOMEM;
+               goto err_alloc;
+       }
+
+       wm831x_ts->wm831x = wm831x;
+       wm831x_ts->input_dev = input_dev;
+
+       /*
+        * If we have a direct IRQ use it, otherwise use the interrupt
+        * from the WM831x IRQ controller.
+        */
+       if (pdata && pdata->data_irq)
+               wm831x_ts->data_irq = pdata->data_irq;
+       else
+               wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");
+
+       if (pdata && pdata->pd_irq)
+               wm831x_ts->pd_irq = pdata->pd_irq;
+       else
+               wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");
+
+       if (pdata)
+               wm831x_ts->pressure = pdata->pressure;
+       else
+               wm831x_ts->pressure = true;
+
+       /* Five wire touchscreens can't report pressure */
+       if (pdata && pdata->fivewire) {
+               wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+                               WM831X_TCH_5WIRE, WM831X_TCH_5WIRE);
+
+               /* Pressure measurements are not possible for five wire mode */
+               WARN_ON(pdata->pressure && pdata->fivewire);
+               wm831x_ts->pressure = false;
+       } else {
+               wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+                               WM831X_TCH_5WIRE, 0);
+       }
+
+       if (pdata) {
+               switch (pdata->isel) {
+               default:
+                       dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n",
+                               pdata->isel);
+                       /* Fall through */
+               case 200:
+               case 0:
+                       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+                                       WM831X_TCH_ISEL, 0);
+                       break;
+               case 400:
+                       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+                                       WM831X_TCH_ISEL, WM831X_TCH_ISEL);
+                       break;
+               }
+       }
+
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+                       WM831X_TCH_PDONLY, 0);
+
+       /* Default to 96 samples/sec */
+       wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+                       WM831X_TCH_RATE_MASK, 6);
+
+       error = request_threaded_irq(wm831x_ts->data_irq,
+                                    NULL, wm831x_ts_data_irq,
+                                    IRQF_ONESHOT,
+                                    "Touchscreen data", wm831x_ts);
+       if (error) {
+               dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
+                       wm831x_ts->data_irq, error);
+               goto err_alloc;
+       }
+       disable_irq(wm831x_ts->data_irq);
+
+       error = request_threaded_irq(wm831x_ts->pd_irq,
+                                    NULL, wm831x_ts_pen_down_irq,
+                                    IRQF_ONESHOT,
+                                    "Touchscreen pen down", wm831x_ts);
+       if (error) {
+               dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
+                       wm831x_ts->pd_irq, error);
+               goto err_data_irq;
+       }
+
+       /* set up touch configuration */
+       input_dev->name = "WM831x touchscreen";
+       input_dev->phys = "wm831x";
+       input_dev->open = wm831x_ts_input_open;
+       input_dev->close = wm831x_ts_input_close;
+
+       __set_bit(EV_ABS, input_dev->evbit);
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
+
+       input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
+       if (wm831x_ts->pressure)
+               input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
+
+       input_set_drvdata(input_dev, wm831x_ts);
+       input_dev->dev.parent = &pdev->dev;
+
+       error = input_register_device(input_dev);
+       if (error)
+               goto err_pd_irq;
+
+       platform_set_drvdata(pdev, wm831x_ts);
+       return 0;
+
+err_pd_irq:
+       free_irq(wm831x_ts->pd_irq, wm831x_ts);
+err_data_irq:
+       free_irq(wm831x_ts->data_irq, wm831x_ts);
+err_alloc:
+       input_free_device(input_dev);
+       kfree(wm831x_ts);
+
+       return error;
+}
+
+static __devexit int wm831x_ts_remove(struct platform_device *pdev)
+{
+       struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
+
+       free_irq(wm831x_ts->pd_irq, wm831x_ts);
+       free_irq(wm831x_ts->data_irq, wm831x_ts);
+       input_unregister_device(wm831x_ts->input_dev);
+       kfree(wm831x_ts);
+
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver wm831x_ts_driver = {
+       .driver = {
+               .name = "wm831x-touch",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm831x_ts_probe,
+       .remove = __devexit_p(wm831x_ts_remove),
+};
+
+static int __init wm831x_ts_init(void)
+{
+       return platform_driver_register(&wm831x_ts_driver);
+}
+module_init(wm831x_ts_init);
+
+static void __exit wm831x_ts_exit(void)
+{
+       platform_driver_unregister(&wm831x_ts_driver);
+}
+module_exit(wm831x_ts_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-touch");
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
deleted file mode 100644 (file)
index 7f85a86..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Xen para-virtual input device
- *
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- *
- *  Based on linux/drivers/input/mouse/sermouse.c
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-/*
- * TODO:
- *
- * Switch to grant tables together with xen-fbfront.c.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/xen.h>
-#include <xen/events.h>
-#include <xen/page.h>
-#include <xen/interface/io/fbif.h>
-#include <xen/interface/io/kbdif.h>
-#include <xen/xenbus.h>
-
-struct xenkbd_info {
-       struct input_dev *kbd;
-       struct input_dev *ptr;
-       struct xenkbd_page *page;
-       int irq;
-       struct xenbus_device *xbdev;
-       char phys[32];
-};
-
-static int xenkbd_remove(struct xenbus_device *);
-static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
-static void xenkbd_disconnect_backend(struct xenkbd_info *);
-
-/*
- * Note: if you need to send out events, see xenfb_do_update() for how
- * to do that.
- */
-
-static irqreturn_t input_handler(int rq, void *dev_id)
-{
-       struct xenkbd_info *info = dev_id;
-       struct xenkbd_page *page = info->page;
-       __u32 cons, prod;
-
-       prod = page->in_prod;
-       if (prod == page->in_cons)
-               return IRQ_HANDLED;
-       rmb();                  /* ensure we see ring contents up to prod */
-       for (cons = page->in_cons; cons != prod; cons++) {
-               union xenkbd_in_event *event;
-               struct input_dev *dev;
-               event = &XENKBD_IN_RING_REF(page, cons);
-
-               dev = info->ptr;
-               switch (event->type) {
-               case XENKBD_TYPE_MOTION:
-                       input_report_rel(dev, REL_X, event->motion.rel_x);
-                       input_report_rel(dev, REL_Y, event->motion.rel_y);
-                       if (event->motion.rel_z)
-                               input_report_rel(dev, REL_WHEEL,
-                                                -event->motion.rel_z);
-                       break;
-               case XENKBD_TYPE_KEY:
-                       dev = NULL;
-                       if (test_bit(event->key.keycode, info->kbd->keybit))
-                               dev = info->kbd;
-                       if (test_bit(event->key.keycode, info->ptr->keybit))
-                               dev = info->ptr;
-                       if (dev)
-                               input_report_key(dev, event->key.keycode,
-                                                event->key.pressed);
-                       else
-                               pr_warning("unhandled keycode 0x%x\n",
-                                          event->key.keycode);
-                       break;
-               case XENKBD_TYPE_POS:
-                       input_report_abs(dev, ABS_X, event->pos.abs_x);
-                       input_report_abs(dev, ABS_Y, event->pos.abs_y);
-                       if (event->pos.rel_z)
-                               input_report_rel(dev, REL_WHEEL,
-                                                -event->pos.rel_z);
-                       break;
-               }
-               if (dev)
-                       input_sync(dev);
-       }
-       mb();                   /* ensure we got ring contents */
-       page->in_cons = cons;
-       notify_remote_via_irq(info->irq);
-
-       return IRQ_HANDLED;
-}
-
-static int __devinit xenkbd_probe(struct xenbus_device *dev,
-                                 const struct xenbus_device_id *id)
-{
-       int ret, i;
-       struct xenkbd_info *info;
-       struct input_dev *kbd, *ptr;
-
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
-               return -ENOMEM;
-       }
-       dev_set_drvdata(&dev->dev, info);
-       info->xbdev = dev;
-       info->irq = -1;
-       snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
-
-       info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-       if (!info->page)
-               goto error_nomem;
-
-       /* keyboard */
-       kbd = input_allocate_device();
-       if (!kbd)
-               goto error_nomem;
-       kbd->name = "Xen Virtual Keyboard";
-       kbd->phys = info->phys;
-       kbd->id.bustype = BUS_PCI;
-       kbd->id.vendor = 0x5853;
-       kbd->id.product = 0xffff;
-       kbd->evbit[0] = BIT(EV_KEY);
-       for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
-               set_bit(i, kbd->keybit);
-       for (i = KEY_OK; i < KEY_MAX; i++)
-               set_bit(i, kbd->keybit);
-
-       ret = input_register_device(kbd);
-       if (ret) {
-               input_free_device(kbd);
-               xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
-               goto error;
-       }
-       info->kbd = kbd;
-
-       /* pointing device */
-       ptr = input_allocate_device();
-       if (!ptr)
-               goto error_nomem;
-       ptr->name = "Xen Virtual Pointer";
-       ptr->phys = info->phys;
-       ptr->id.bustype = BUS_PCI;
-       ptr->id.vendor = 0x5853;
-       ptr->id.product = 0xfffe;
-       ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
-       for (i = BTN_LEFT; i <= BTN_TASK; i++)
-               set_bit(i, ptr->keybit);
-       ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-       input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
-       input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
-
-       ret = input_register_device(ptr);
-       if (ret) {
-               input_free_device(ptr);
-               xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
-               goto error;
-       }
-       info->ptr = ptr;
-
-       ret = xenkbd_connect_backend(dev, info);
-       if (ret < 0)
-               goto error;
-
-       return 0;
-
- error_nomem:
-       ret = -ENOMEM;
-       xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
-       xenkbd_remove(dev);
-       return ret;
-}
-
-static int xenkbd_resume(struct xenbus_device *dev)
-{
-       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-       xenkbd_disconnect_backend(info);
-       memset(info->page, 0, PAGE_SIZE);
-       return xenkbd_connect_backend(dev, info);
-}
-
-static int xenkbd_remove(struct xenbus_device *dev)
-{
-       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-       xenkbd_disconnect_backend(info);
-       if (info->kbd)
-               input_unregister_device(info->kbd);
-       if (info->ptr)
-               input_unregister_device(info->ptr);
-       free_page((unsigned long)info->page);
-       kfree(info);
-       return 0;
-}
-
-static int xenkbd_connect_backend(struct xenbus_device *dev,
-                                 struct xenkbd_info *info)
-{
-       int ret, evtchn;
-       struct xenbus_transaction xbt;
-
-       ret = xenbus_alloc_evtchn(dev, &evtchn);
-       if (ret)
-               return ret;
-       ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
-                                       0, dev->devicetype, info);
-       if (ret < 0) {
-               xenbus_free_evtchn(dev, evtchn);
-               xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
-               return ret;
-       }
-       info->irq = ret;
-
- again:
-       ret = xenbus_transaction_start(&xbt);
-       if (ret) {
-               xenbus_dev_fatal(dev, ret, "starting transaction");
-               return ret;
-       }
-       ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
-                           virt_to_mfn(info->page));
-       if (ret)
-               goto error_xenbus;
-       ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
-                           evtchn);
-       if (ret)
-               goto error_xenbus;
-       ret = xenbus_transaction_end(xbt, 0);
-       if (ret) {
-               if (ret == -EAGAIN)
-                       goto again;
-               xenbus_dev_fatal(dev, ret, "completing transaction");
-               return ret;
-       }
-
-       xenbus_switch_state(dev, XenbusStateInitialised);
-       return 0;
-
- error_xenbus:
-       xenbus_transaction_end(xbt, 1);
-       xenbus_dev_fatal(dev, ret, "writing xenstore");
-       return ret;
-}
-
-static void xenkbd_disconnect_backend(struct xenkbd_info *info)
-{
-       if (info->irq >= 0)
-               unbind_from_irqhandler(info->irq, info);
-       info->irq = -1;
-}
-
-static void xenkbd_backend_changed(struct xenbus_device *dev,
-                                  enum xenbus_state backend_state)
-{
-       struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-       int ret, val;
-
-       switch (backend_state) {
-       case XenbusStateInitialising:
-       case XenbusStateInitialised:
-       case XenbusStateReconfiguring:
-       case XenbusStateReconfigured:
-       case XenbusStateUnknown:
-       case XenbusStateClosed:
-               break;
-
-       case XenbusStateInitWait:
-InitWait:
-               ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-                                  "feature-abs-pointer", "%d", &val);
-               if (ret < 0)
-                       val = 0;
-               if (val) {
-                       ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
-                                           "request-abs-pointer", "1");
-                       if (ret)
-                               pr_warning("can't request abs-pointer\n");
-               }
-               xenbus_switch_state(dev, XenbusStateConnected);
-               break;
-
-       case XenbusStateConnected:
-               /*
-                * Work around xenbus race condition: If backend goes
-                * through InitWait to Connected fast enough, we can
-                * get Connected twice here.
-                */
-               if (dev->state != XenbusStateConnected)
-                       goto InitWait; /* no InitWait seen yet, fudge it */
-
-               /* Set input abs params to match backend screen res */
-               if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-                                "width", "%d", &val) > 0)
-                       input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
-
-               if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-                                "height", "%d", &val) > 0)
-                       input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
-
-               break;
-
-       case XenbusStateClosing:
-               xenbus_frontend_closed(dev);
-               break;
-       }
-}
-
-static const struct xenbus_device_id xenkbd_ids[] = {
-       { "vkbd" },
-       { "" }
-};
-
-static struct xenbus_driver xenkbd_driver = {
-       .name = "vkbd",
-       .owner = THIS_MODULE,
-       .ids = xenkbd_ids,
-       .probe = xenkbd_probe,
-       .remove = xenkbd_remove,
-       .resume = xenkbd_resume,
-       .otherend_changed = xenkbd_backend_changed,
-};
-
-static int __init xenkbd_init(void)
-{
-       if (!xen_pv_domain())
-               return -ENODEV;
-
-       /* Nothing to do if running in dom0. */
-       if (xen_initial_domain())
-               return -ENODEV;
-
-       return xenbus_register_frontend(&xenkbd_driver);
-}
-
-static void __exit xenkbd_cleanup(void)
-{
-       xenbus_unregister_driver(&xenkbd_driver);
-}
-
-module_init(xenkbd_init);
-module_exit(xenkbd_cleanup);
-
-MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("xen:vkbd");
index ab638b083df9cfffb79071b7a313a5c2663eab4b..646368fe41c94a7a6444b3ce8023663c79cf0308 100644 (file)
@@ -4,7 +4,7 @@
 
 # Define maximum number of cards
 
-EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+ccflags-y      := -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
 
 obj-$(CONFIG_ISDN_DRV_HISAX)           += hisax.o
 obj-$(CONFIG_HISAX_SEDLBAUER_CS)       += sedlbauer_cs.o
index 23005b3cf30bedaea413a1afba3627fe28d0d400..b2b9415d874d02142a9944c283c0f613cda1e9b6 100644 (file)
@@ -8,60 +8,71 @@
 #include "dvb-usb-common.h"
 #include <linux/usb/input.h>
 
+static unsigned int
+legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
+                               struct rc_map_table *keymap,
+                               unsigned int keymap_size)
+{
+       unsigned int index;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+       } else {
+               if (input_scancode_to_scalar(ke, &scancode))
+                       return keymap_size;
+
+               /* See if we can match the raw key code. */
+               for (index = 0; index < keymap_size; index++)
+                       if (keymap[index].scancode == scancode)
+                               break;
+
+               /* See if there is an unused hole in the map */
+               if (index >= keymap_size) {
+                       for (index = 0; index < keymap_size; index++) {
+                               if (keymap[index].keycode == KEY_RESERVED ||
+                                   keymap[index].keycode == KEY_UNKNOWN) {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       return index;
+}
+
 static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int *keycode)
+                                    struct input_keymap_entry *ke)
 {
        struct dvb_usb_device *d = input_get_drvdata(dev);
-
        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-       int i;
+       unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+       unsigned int index;
 
-       /* See if we can match the raw key code. */
-       for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-               if (keymap[i].scancode == scancode) {
-                       *keycode = keymap[i].keycode;
-                       return 0;
-               }
+       index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
+       if (index >= keymap_size)
+               return -EINVAL;
 
-       /*
-        * If is there extra space, returns KEY_RESERVED,
-        * otherwise, input core won't let legacy_dvb_usb_setkeycode
-        * to work
-        */
-       for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-               if (keymap[i].keycode == KEY_RESERVED ||
-                   keymap[i].keycode == KEY_UNKNOWN) {
-                       *keycode = KEY_RESERVED;
-                       return 0;
-               }
+       ke->keycode = keymap[index].keycode;
+       if (ke->keycode == KEY_UNKNOWN)
+               ke->keycode = KEY_RESERVED;
+       ke->len = sizeof(keymap[index].scancode);
+       memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
+       ke->index = index;
 
-       return -EINVAL;
+       return 0;
 }
 
 static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int keycode)
+                                    const struct input_keymap_entry *ke,
+                                    unsigned int *old_keycode)
 {
        struct dvb_usb_device *d = input_get_drvdata(dev);
-
        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-       int i;
-
-       /* Search if it is replacing an existing keycode */
-       for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-               if (keymap[i].scancode == scancode) {
-                       keymap[i].keycode = keycode;
-                       return 0;
-               }
-
-       /* Search if is there a clean entry. If so, use it */
-       for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-               if (keymap[i].keycode == KEY_RESERVED ||
-                   keymap[i].keycode == KEY_UNKNOWN) {
-                       keymap[i].scancode = scancode;
-                       keymap[i].keycode = keycode;
-                       return 0;
-               }
+       unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+       unsigned int index;
 
+       index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
        /*
         * FIXME: Currently, it is not possible to increase the size of
         * scancode table. For it to happen, one possibility
@@ -69,8 +80,24 @@ static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
         * copying data, appending the new key on it, and freeing
         * the old one - or maybe just allocating some spare space
         */
+       if (index >= keymap_size)
+               return -EINVAL;
+
+       *old_keycode = keymap[index].keycode;
+       keymap->keycode = ke->keycode;
+       __set_bit(ke->keycode, dev->keybit);
+
+       if (*old_keycode != KEY_RESERVED) {
+               __clear_bit(*old_keycode, dev->keybit);
+               for (index = 0; index < keymap_size; index++) {
+                       if (keymap[index].keycode == *old_keycode) {
+                               __set_bit(*old_keycode, dev->keybit);
+                               break;
+                       }
+               }
+       }
 
-       return -EINVAL;
+       return 0;
 }
 
 /* Remote-control poll function - called every dib->rc_query_interval ms to see
index 5b4422ef4e6d4705566bc8f45a23cf6a9e9719fc..5ac1baf45c8e8514a2a4c12e29bb26f30bb3b0d7 100644 (file)
@@ -966,8 +966,8 @@ struct rc_dev *rc_allocate_device(void)
                return NULL;
        }
 
-       dev->input_dev->getkeycode_new = ir_getkeycode;
-       dev->input_dev->setkeycode_new = ir_setkeycode;
+       dev->input_dev->getkeycode = ir_getkeycode;
+       dev->input_dev->setkeycode = ir_setkeycode;
        input_set_drvdata(dev->input_dev, dev);
 
        spin_lock_init(&dev->rc_map.lock);
index dc160fb435150ceeab480513919086a896077d29..98623590c7fe048d727f477f1f6d6ecf42d91ed2 100644 (file)
@@ -2,9 +2,7 @@
 # Makefile for the kernel MemoryStick device drivers.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-       EXTRA_CFLAGS            += -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_MEMSTICK_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_MEMSTICK)         += core/
 obj-$(CONFIG_MEMSTICK)         += host/
index 8b2b5293877e0f1fd7da1766765f72d46d6bf24f..ecd0299377386fee7e062a87c9209a5ad36f22f1 100644 (file)
@@ -2,10 +2,6 @@
 # Makefile for the kernel MemoryStick core.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-       EXTRA_CFLAGS            += -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK)         += memstick.o
 
 obj-$(CONFIG_MSPRO_BLOCK)      += mspro_block.o
index 12530e4311d31143dcab38c1405d92b02418c8de..a1815e9dd0193f49c700ec78c734b203d38bdfa4 100644 (file)
@@ -2,9 +2,5 @@
 # Makefile for MemoryStick host controller drivers
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-       EXTRA_CFLAGS                    += -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK_TIFM_MS)         += tifm_ms.o
 obj-$(CONFIG_MEMSTICK_JMICRON_38X)     += jmb38x_ms.o
index 95c9532cb07ca693cd39a6f37a49c9debe3db9d6..d182a24b31955cbf1c9b3fe0c4353d7f962ad968 100644 (file)
@@ -2,7 +2,7 @@
 
 # enable verbose logging
 # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig
-#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE
+#ccflags-y := -DMPT_DEBUG_VERBOSE
 
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
index b7d5ef234ac942f00358abdf700ee2ed21770c5f..203500d9b8483ac8bb412480460d674b84cd3010 100644 (file)
@@ -2,6 +2,14 @@
 # Misc strange devices
 #
 
+# This one has to live outside of the MISC_DEVICES conditional,
+# because it may be selected by drivers/platform/x86/hp_accel.
+config SENSORS_LIS3LV02D
+       tristate
+       depends on INPUT
+       select INPUT_POLLDEV
+       default n
+
 menuconfig MISC_DEVICES
        bool "Misc devices"
        ---help---
@@ -462,5 +470,6 @@ source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
 source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
+source "drivers/misc/lis3lv02d/Kconfig"
 
 endif # MISC_DEVICES
index 98009cc20cb9c6c887a200bfe96c85948a311be5..804f421bc079432bddc9e4120629d2d037809a22 100644 (file)
@@ -42,3 +42,4 @@ obj-$(CONFIG_ARM_CHARLCD)     += arm-charlcd.o
 obj-$(CONFIG_PCH_PHUB)         += pch_phub.o
 obj-y                          += ti-st/
 obj-$(CONFIG_AB8500_PWM)       += ab8500-pwm.o
+obj-y                          += lis3lv02d/
index 7b80cbf1a609b75f710d9b308a45e66d2bd9deef..467c8e9ca3c94d6b7f54998133a70ec5c88a9403 100644 (file)
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CB710_DEBUG),y)
-       EXTRA_CFLAGS            += -DDEBUG
-endif
+ccflags-$(CONFIG_CB710_DEBUG)  := -DDEBUG
 
 obj-$(CONFIG_CB710_CORE)       += cb710.o
 
diff --git a/drivers/misc/lis3lv02d/Kconfig b/drivers/misc/lis3lv02d/Kconfig
new file mode 100644 (file)
index 0000000..8f474e6
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+config SENSORS_LIS3_SPI
+       tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
+       depends on !ACPI && SPI_MASTER && INPUT
+       select SENSORS_LIS3LV02D
+       default n
+       help
+         This driver provides support for the LIS3LV02Dx accelerometer connected
+         via SPI. The accelerometer data is readable via
+         /sys/devices/platform/lis3lv02d.
+
+         This driver also provides an absolute input class device, allowing
+         the laptop to act as a pinball machine-esque joystick.
+
+         This driver can also be built as modules.  If so, the core module
+         will be called lis3lv02d and a specific module for the SPI transport
+         is called lis3lv02d_spi.
+
+config SENSORS_LIS3_I2C
+       tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
+       depends on I2C && INPUT
+       select SENSORS_LIS3LV02D
+       default n
+       help
+         This driver provides support for the LIS3LV02Dx accelerometer connected
+         via I2C. The accelerometer data is readable via
+         /sys/devices/platform/lis3lv02d.
+
+         This driver also provides an absolute input class device, allowing
+         the device to act as a pinball machine-esque joystick.
+
+         This driver can also be built as modules.  If so, the core module
+         will be called lis3lv02d and a specific module for the I2C transport
+         is called lis3lv02d_i2c.
diff --git a/drivers/misc/lis3lv02d/Makefile b/drivers/misc/lis3lv02d/Makefile
new file mode 100644 (file)
index 0000000..4bf58b1
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o
+obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d_spi.o
+obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d_i2c.o
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
new file mode 100644 (file)
index 0000000..b928bc1
--- /dev/null
@@ -0,0 +1,999 @@
+/*
+ *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  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/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input-polldev.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
+#include <linux/atomic.h>
+#include "lis3lv02d.h"
+
+#define DRIVER_NAME     "lis3lv02d"
+
+/* joystick device poll interval in milliseconds */
+#define MDPS_POLL_INTERVAL 50
+#define MDPS_POLL_MIN     0
+#define MDPS_POLL_MAX     2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK           0
+#define SELFTEST_FAIL         -1
+#define SELFTEST_IRQ          -2
+
+#define IRQ_LINE0             0
+#define IRQ_LINE1             1
+
+/*
+ * The sensor can also generate interrupts (DRDY) but it's pretty pointless
+ * because they are generated even if the data do not change. So it's better
+ * to keep the interrupt for the free-fall event. The values are updated at
+ * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
+ * some low processor, we poll the sensor only at 20Hz... enough for the
+ * joystick.
+ */
+
+#define LIS3_PWRON_DELAY_WAI_12B       (5000)
+#define LIS3_PWRON_DELAY_WAI_8B                (3000)
+
+/*
+ * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
+ * LIS302D spec says: 18 mG / digit
+ * LIS3_ACCURACY is used to increase accuracy of the intermediate
+ * calculation results.
+ */
+#define LIS3_ACCURACY                  1024
+/* Sensitivity values for -2G +2G scale */
+#define LIS3_SENSITIVITY_12B           ((LIS3_ACCURACY * 1000) / 1024)
+#define LIS3_SENSITIVITY_8B            (18 * LIS3_ACCURACY)
+
+#define LIS3_DEFAULT_FUZZ_12B          3
+#define LIS3_DEFAULT_FLAT_12B          3
+#define LIS3_DEFAULT_FUZZ_8B           1
+#define LIS3_DEFAULT_FLAT_8B           1
+
+struct lis3lv02d lis3_dev = {
+       .misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
+};
+EXPORT_SYMBOL_GPL(lis3_dev);
+
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       if (!ret) {
+               int val = *(int *)kp->arg;
+               if (val < 0)
+                       val = -val;
+               if (!val || val > 3)
+                       return -EINVAL;
+       }
+       return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+       .set = param_set_axis,
+       .get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
+static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
+{
+       s8 lo;
+       if (lis3->read(lis3, reg, &lo) < 0)
+               return 0;
+
+       return lo;
+}
+
+static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
+{
+       u8 lo, hi;
+
+       lis3->read(lis3, reg - 1, &lo);
+       lis3->read(lis3, reg, &hi);
+       /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+       return (s16)((hi << 8) | lo);
+}
+
+/**
+ * lis3lv02d_get_axis - For the given axis, give the value converted
+ * @axis:      1,2,3 - can also be negative
+ * @hw_values: raw values returned by the hardware
+ *
+ * Returns the converted value.
+ */
+static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
+{
+       if (axis > 0)
+               return hw_values[axis - 1];
+       else
+               return -hw_values[-axis - 1];
+}
+
+/**
+ * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
+ * @lis3: pointer to the device struct
+ * @x:    where to store the X axis value
+ * @y:    where to store the Y axis value
+ * @z:    where to store the Z axis value
+ *
+ * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
+ */
+static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
+{
+       int position[3];
+       int i;
+
+       if (lis3->blkread) {
+               if (lis3_dev.whoami == WAI_12B) {
+                       u16 data[3];
+                       lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s16)le16_to_cpu(data[i]);
+               } else {
+                       u8 data[5];
+                       /* Data: x, dummy, y, dummy, z */
+                       lis3->blkread(lis3, OUTX, 5, data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s8)data[i * 2];
+               }
+       } else {
+               position[0] = lis3->read_data(lis3, OUTX);
+               position[1] = lis3->read_data(lis3, OUTY);
+               position[2] = lis3->read_data(lis3, OUTZ);
+       }
+
+       for (i = 0; i < 3; i++)
+               position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
+
+       *x = lis3lv02d_get_axis(lis3->ac.x, position);
+       *y = lis3lv02d_get_axis(lis3->ac.y, position);
+       *z = lis3lv02d_get_axis(lis3->ac.z, position);
+}
+
+/* conversion btw sampling rate and the register values */
+static int lis3_12_rates[4] = {40, 160, 640, 2560};
+static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
+
+/* ODR is Output Data Rate */
+static int lis3lv02d_get_odr(void)
+{
+       u8 ctrl;
+       int shift;
+
+       lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+       ctrl &= lis3_dev.odr_mask;
+       shift = ffs(lis3_dev.odr_mask) - 1;
+       return lis3_dev.odrs[(ctrl >> shift)];
+}
+
+static int lis3lv02d_set_odr(int rate)
+{
+       u8 ctrl;
+       int i, len, shift;
+
+       if (!rate)
+               return -EINVAL;
+
+       lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+       ctrl &= ~lis3_dev.odr_mask;
+       len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
+       shift = ffs(lis3_dev.odr_mask) - 1;
+
+       for (i = 0; i < len; i++)
+               if (lis3_dev.odrs[i] == rate) {
+                       lis3_dev.write(&lis3_dev, CTRL_REG1,
+                                       ctrl | (i << shift));
+                       return 0;
+               }
+       return -EINVAL;
+}
+
+static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
+{
+       u8 ctlreg, reg;
+       s16 x, y, z;
+       u8 selftest;
+       int ret;
+       u8 ctrl_reg_data;
+       unsigned char irq_cfg;
+
+       mutex_lock(&lis3->mutex);
+
+       irq_cfg = lis3->irq_cfg;
+       if (lis3_dev.whoami == WAI_8B) {
+               lis3->data_ready_count[IRQ_LINE0] = 0;
+               lis3->data_ready_count[IRQ_LINE1] = 0;
+
+               /* Change interrupt cfg to data ready for selftest */
+               atomic_inc(&lis3_dev.wake_thread);
+               lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+               lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+               lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+                               ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+                               (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+       }
+
+       if (lis3_dev.whoami == WAI_3DC) {
+               ctlreg = CTRL_REG4;
+               selftest = CTRL4_ST0;
+       } else {
+               ctlreg = CTRL_REG1;
+               if (lis3_dev.whoami == WAI_12B)
+                       selftest = CTRL1_ST;
+               else
+                       selftest = CTRL1_STP;
+       }
+
+       lis3->read(lis3, ctlreg, &reg);
+       lis3->write(lis3, ctlreg, (reg | selftest));
+       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+       /* Read directly to avoid axis remap */
+       x = lis3->read_data(lis3, OUTX);
+       y = lis3->read_data(lis3, OUTY);
+       z = lis3->read_data(lis3, OUTZ);
+
+       /* back to normal settings */
+       lis3->write(lis3, ctlreg, reg);
+       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+       results[0] = x - lis3->read_data(lis3, OUTX);
+       results[1] = y - lis3->read_data(lis3, OUTY);
+       results[2] = z - lis3->read_data(lis3, OUTZ);
+
+       ret = 0;
+
+       if (lis3_dev.whoami == WAI_8B) {
+               /* Restore original interrupt configuration */
+               atomic_dec(&lis3_dev.wake_thread);
+               lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+               lis3->irq_cfg = irq_cfg;
+
+               if ((irq_cfg & LIS3_IRQ1_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE0] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+
+               if ((irq_cfg & LIS3_IRQ2_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE1] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+       }
+
+       if (lis3->pdata) {
+               int i;
+               for (i = 0; i < 3; i++) {
+                       /* Check against selftest acceptance limits */
+                       if ((results[i] < lis3->pdata->st_min_limits[i]) ||
+                           (results[i] > lis3->pdata->st_max_limits[i])) {
+                               ret = SELFTEST_FAIL;
+                               goto fail;
+                       }
+               }
+       }
+
+       /* test passed */
+fail:
+       mutex_unlock(&lis3->mutex);
+       return ret;
+}
+
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+                              FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+                              CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+                              CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+                              CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+                              FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+                              DD_THSE_L, DD_THSE_H,
+                              CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+       int i;
+       for (i = 0; i < lis3->regs_size; i++)
+               lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+       lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+       int i;
+       if (lis3->regs_stored)
+               for (i = 0; i < lis3->regs_size; i++)
+                       lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
+void lis3lv02d_poweroff(struct lis3lv02d *lis3)
+{
+       if (lis3->reg_ctrl)
+               lis3_context_save(lis3);
+       /* disable X,Y,Z axis and power down */
+       lis3->write(lis3, CTRL_REG1, 0x00);
+       if (lis3->reg_ctrl)
+               lis3->reg_ctrl(lis3, LIS3_REG_OFF);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
+
+void lis3lv02d_poweron(struct lis3lv02d *lis3)
+{
+       u8 reg;
+
+       lis3->init(lis3);
+
+       /*
+        * Common configuration
+        * BDU: (12 bits sensors only) LSB and MSB values are not updated until
+        *      both have been read. So the value read will always be correct.
+        * Set BOOT bit to refresh factory tuning values.
+        */
+       lis3->read(lis3, CTRL_REG2, &reg);
+       if (lis3->whoami ==  WAI_12B)
+               reg |= CTRL2_BDU | CTRL2_BOOT;
+       else
+               reg |= CTRL2_BOOT_8B;
+       lis3->write(lis3, CTRL_REG2, reg);
+
+       /* LIS3 power on delay is quite long */
+       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+       if (lis3->reg_ctrl)
+               lis3_context_restore(lis3);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
+
+
+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
+{
+       int x, y, z;
+
+       mutex_lock(&lis3_dev.mutex);
+       lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+       input_report_abs(pidev->input, ABS_X, x);
+       input_report_abs(pidev->input, ABS_Y, y);
+       input_report_abs(pidev->input, ABS_Z, z);
+       input_sync(pidev->input);
+       mutex_unlock(&lis3_dev.mutex);
+}
+
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
+       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+               atomic_set(&lis3_dev.wake_thread, 1);
+       /*
+        * Update coordinates for the case where poll interval is 0 and
+        * the chip in running purely under interrupt control
+        */
+       lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+       atomic_set(&lis3_dev.wake_thread, 0);
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
+}
+
+static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+{
+       if (!test_bit(0, &lis3_dev.misc_opened))
+               goto out;
+
+       /*
+        * Be careful: on some HP laptops the bios force DD when on battery and
+        * the lid is closed. This leads to interrupts as soon as a little move
+        * is done.
+        */
+       atomic_inc(&lis3_dev.count);
+
+       wake_up_interruptible(&lis3_dev.misc_wait);
+       kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+out:
+       if (atomic_read(&lis3_dev.wake_thread))
+               return IRQ_WAKE_THREAD;
+       return IRQ_HANDLED;
+}
+
+static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
+{
+       struct input_dev *dev = lis3->idev->input;
+       u8 click_src;
+
+       mutex_lock(&lis3->mutex);
+       lis3->read(lis3, CLICK_SRC, &click_src);
+
+       if (click_src & CLICK_SINGLE_X) {
+               input_report_key(dev, lis3->mapped_btns[0], 1);
+               input_report_key(dev, lis3->mapped_btns[0], 0);
+       }
+
+       if (click_src & CLICK_SINGLE_Y) {
+               input_report_key(dev, lis3->mapped_btns[1], 1);
+               input_report_key(dev, lis3->mapped_btns[1], 0);
+       }
+
+       if (click_src & CLICK_SINGLE_Z) {
+               input_report_key(dev, lis3->mapped_btns[2], 1);
+               input_report_key(dev, lis3->mapped_btns[2], 0);
+       }
+       input_sync(dev);
+       mutex_unlock(&lis3->mutex);
+}
+
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
+{
+       int dummy;
+
+       /* Dummy read to ack interrupt */
+       lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+       lis3->data_ready_count[index]++;
+}
+
+static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
+{
+       struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
+
+       if (irq_cfg == LIS3_IRQ1_CLICK)
+               lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE0);
+       else
+               lis3lv02d_joystick_poll(lis3->idev);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
+{
+       struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
+
+       if (irq_cfg == LIS3_IRQ2_CLICK)
+               lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE1);
+       else
+               lis3lv02d_joystick_poll(lis3->idev);
+
+       return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &lis3_dev.misc_opened))
+               return -EBUSY; /* already open */
+
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
+       atomic_set(&lis3_dev.count, 0);
+       return 0;
+}
+
+static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
+{
+       fasync_helper(-1, file, 0, &lis3_dev.async_queue);
+       clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
+       return 0;
+}
+
+static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
+                               size_t count, loff_t *pos)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       u32 data;
+       unsigned char byte_data;
+       ssize_t retval = 1;
+
+       if (count < 1)
+               return -EINVAL;
+
+       add_wait_queue(&lis3_dev.misc_wait, &wait);
+       while (true) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               data = atomic_xchg(&lis3_dev.count, 0);
+               if (data)
+                       break;
+
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               schedule();
+       }
+
+       if (data < 255)
+               byte_data = data;
+       else
+               byte_data = 255;
+
+       /* make sure we are not going into copy_to_user() with
+        * TASK_INTERRUPTIBLE state */
+       set_current_state(TASK_RUNNING);
+       if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
+               retval = -EFAULT;
+
+out:
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&lis3_dev.misc_wait, &wait);
+
+       return retval;
+}
+
+static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+{
+       poll_wait(file, &lis3_dev.misc_wait, wait);
+       if (atomic_read(&lis3_dev.count))
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
+{
+       return fasync_helper(fd, file, on, &lis3_dev.async_queue);
+}
+
+static const struct file_operations lis3lv02d_misc_fops = {
+       .owner   = THIS_MODULE,
+       .llseek  = no_llseek,
+       .read    = lis3lv02d_misc_read,
+       .open    = lis3lv02d_misc_open,
+       .release = lis3lv02d_misc_release,
+       .poll    = lis3lv02d_misc_poll,
+       .fasync  = lis3lv02d_misc_fasync,
+};
+
+static struct miscdevice lis3lv02d_misc_device = {
+       .minor   = MISC_DYNAMIC_MINOR,
+       .name    = "freefall",
+       .fops    = &lis3lv02d_misc_fops,
+};
+
+int lis3lv02d_joystick_enable(void)
+{
+       struct input_dev *input_dev;
+       int err;
+       int max_val, fuzz, flat;
+       int btns[] = {BTN_X, BTN_Y, BTN_Z};
+
+       if (lis3_dev.idev)
+               return -EINVAL;
+
+       lis3_dev.idev = input_allocate_polled_device();
+       if (!lis3_dev.idev)
+               return -ENOMEM;
+
+       lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+       lis3_dev.idev->open = lis3lv02d_joystick_open;
+       lis3_dev.idev->close = lis3lv02d_joystick_close;
+       lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
+       lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
+       lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
+       input_dev = lis3_dev.idev->input;
+
+       input_dev->name       = "ST LIS3LV02DL Accelerometer";
+       input_dev->phys       = DRIVER_NAME "/input0";
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor  = 0;
+       input_dev->dev.parent = &lis3_dev.pdev->dev;
+
+       set_bit(EV_ABS, input_dev->evbit);
+       max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
+       if (lis3_dev.whoami == WAI_12B) {
+               fuzz = LIS3_DEFAULT_FUZZ_12B;
+               flat = LIS3_DEFAULT_FLAT_12B;
+       } else {
+               fuzz = LIS3_DEFAULT_FUZZ_8B;
+               flat = LIS3_DEFAULT_FLAT_8B;
+       }
+       fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+       flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
+       input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
+       input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
+       input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
+
+       lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
+       lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
+       lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+
+       err = input_register_polled_device(lis3_dev.idev);
+       if (err) {
+               input_free_polled_device(lis3_dev.idev);
+               lis3_dev.idev = NULL;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
+
+void lis3lv02d_joystick_disable(void)
+{
+       if (lis3_dev.irq)
+               free_irq(lis3_dev.irq, &lis3_dev);
+       if (lis3_dev.pdata && lis3_dev.pdata->irq2)
+               free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+
+       if (!lis3_dev.idev)
+               return;
+
+       if (lis3_dev.irq)
+               misc_deregister(&lis3lv02d_misc_device);
+       input_unregister_polled_device(lis3_dev.idev);
+       input_free_polled_device(lis3_dev.idev);
+       lis3_dev.idev = NULL;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
+
+/* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+       /*
+        * SYSFS functions are fast visitors so put-call
+        * immediately after the get-call. However, keep
+        * chip running for a while and schedule delayed
+        * suspend. This way periodic sysfs calls doesn't
+        * suffer from relatively long power up time.
+        */
+
+       if (lis3->pm_dev) {
+               pm_runtime_get_sync(lis3->pm_dev);
+               pm_runtime_put_noidle(lis3->pm_dev);
+               pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+       }
+}
+
+static ssize_t lis3lv02d_selftest_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       s16 values[3];
+
+       static const char ok[] = "OK";
+       static const char fail[] = "FAIL";
+       static const char irq[] = "FAIL_IRQ";
+       const char *res;
+
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       switch (lis3lv02d_selftest(&lis3_dev, values)) {
+       case SELFTEST_FAIL:
+               res = fail;
+               break;
+       case SELFTEST_IRQ:
+               res = irq;
+               break;
+       case SELFTEST_OK:
+       default:
+               res = ok;
+               break;
+       }
+       return sprintf(buf, "%s %d %d %d\n", res,
+               values[0], values[1], values[2]);
+}
+
+static ssize_t lis3lv02d_position_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int x, y, z;
+
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       mutex_lock(&lis3_dev.mutex);
+       lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+       mutex_unlock(&lis3_dev.mutex);
+       return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
+}
+
+static ssize_t lis3lv02d_rate_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       return sprintf(buf, "%d\n", lis3lv02d_get_odr());
+}
+
+static ssize_t lis3lv02d_rate_set(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       unsigned long rate;
+
+       if (strict_strtoul(buf, 0, &rate))
+               return -EINVAL;
+
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       if (lis3lv02d_set_odr(rate))
+               return -EINVAL;
+
+       return count;
+}
+
+static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
+static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
+static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
+                                           lis3lv02d_rate_set);
+
+static struct attribute *lis3lv02d_attributes[] = {
+       &dev_attr_selftest.attr,
+       &dev_attr_position.attr,
+       &dev_attr_rate.attr,
+       NULL
+};
+
+static struct attribute_group lis3lv02d_attribute_group = {
+       .attrs = lis3lv02d_attributes
+};
+
+
+static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
+{
+       lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+       if (IS_ERR(lis3->pdev))
+               return PTR_ERR(lis3->pdev);
+
+       return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+}
+
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
+{
+       sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+       platform_device_unregister(lis3->pdev);
+       if (lis3->pm_dev) {
+               /* Barrier after the sysfs remove */
+               pm_runtime_barrier(lis3->pm_dev);
+
+               /* SYSFS may have left chip running. Turn off if necessary */
+               if (!pm_runtime_suspended(lis3->pm_dev))
+                       lis3lv02d_poweroff(&lis3_dev);
+
+               pm_runtime_disable(lis3->pm_dev);
+               pm_runtime_set_suspended(lis3->pm_dev);
+       }
+       kfree(lis3->reg_cache);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
+
+static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+                               struct lis3lv02d_platform_data *p)
+{
+       int err;
+       int ctrl2 = p->hipass_ctrl;
+
+       if (p->click_flags) {
+               dev->write(dev, CLICK_CFG, p->click_flags);
+               dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
+               dev->write(dev, CLICK_LATENCY, p->click_latency);
+               dev->write(dev, CLICK_WINDOW, p->click_window);
+               dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
+               dev->write(dev, CLICK_THSY_X,
+                       (p->click_thresh_x & 0xf) |
+                       (p->click_thresh_y << 4));
+
+               if (dev->idev) {
+                       struct input_dev *input_dev = lis3_dev.idev->input;
+                       input_set_capability(input_dev, EV_KEY, BTN_X);
+                       input_set_capability(input_dev, EV_KEY, BTN_Y);
+                       input_set_capability(input_dev, EV_KEY, BTN_Z);
+               }
+       }
+
+       if (p->wakeup_flags) {
+               dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
+               dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
+               ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
+       }
+
+       if (p->wakeup_flags2) {
+               dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
+               dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
+               ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
+       }
+       /* Configure hipass filters */
+       dev->write(dev, CTRL_REG2, ctrl2);
+
+       if (p->irq2) {
+               err = request_threaded_irq(p->irq2,
+                                       NULL,
+                                       lis302dl_interrupt_thread2_8b,
+                                       IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                                       (p->irq_flags2 & IRQF_TRIGGER_MASK),
+                                       DRIVER_NAME, &lis3_dev);
+               if (err < 0)
+                       pr_err("No second IRQ. Limited functionality\n");
+       }
+}
+
+/*
+ * Initialise the accelerometer and the various subsystems.
+ * Should be rather independent of the bus system.
+ */
+int lis3lv02d_init_device(struct lis3lv02d *dev)
+{
+       int err;
+       irq_handler_t thread_fn;
+       int irq_flags = 0;
+
+       dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+
+       switch (dev->whoami) {
+       case WAI_12B:
+               pr_info("12 bits sensor found\n");
+               dev->read_data = lis3lv02d_read_12;
+               dev->mdps_max_val = 2048;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+               dev->odrs = lis3_12_rates;
+               dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+               dev->scale = LIS3_SENSITIVITY_12B;
+               dev->regs = lis3_wai12_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
+               break;
+       case WAI_8B:
+               pr_info("8 bits sensor found\n");
+               dev->read_data = lis3lv02d_read_8;
+               dev->mdps_max_val = 128;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+               dev->odrs = lis3_8_rates;
+               dev->odr_mask = CTRL1_DR;
+               dev->scale = LIS3_SENSITIVITY_8B;
+               dev->regs = lis3_wai8_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+               break;
+       case WAI_3DC:
+               pr_info("8 bits 3DC sensor found\n");
+               dev->read_data = lis3lv02d_read_8;
+               dev->mdps_max_val = 128;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+               dev->odrs = lis3_3dc_rates;
+               dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+               dev->scale = LIS3_SENSITIVITY_8B;
+               break;
+       default:
+               pr_err("unknown sensor type 0x%X\n", dev->whoami);
+               return -EINVAL;
+       }
+
+       dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+                                    sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+       if (dev->reg_cache == NULL) {
+               printk(KERN_ERR DRIVER_NAME "out of memory\n");
+               return -ENOMEM;
+       }
+
+       mutex_init(&dev->mutex);
+       atomic_set(&dev->wake_thread, 0);
+
+       lis3lv02d_add_fs(dev);
+       lis3lv02d_poweron(dev);
+
+       if (dev->pm_dev) {
+               pm_runtime_set_active(dev->pm_dev);
+               pm_runtime_enable(dev->pm_dev);
+       }
+
+       if (lis3lv02d_joystick_enable())
+               pr_err("joystick initialization failed\n");
+
+       /* passing in platform specific data is purely optional and only
+        * used by the SPI transport layer at the moment */
+       if (dev->pdata) {
+               struct lis3lv02d_platform_data *p = dev->pdata;
+
+               if (dev->whoami == WAI_8B)
+                       lis3lv02d_8b_configure(dev, p);
+
+               irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+               dev->irq_cfg = p->irq_cfg;
+               if (p->irq_cfg)
+                       dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+               if (p->default_rate)
+                       lis3lv02d_set_odr(p->default_rate);
+       }
+
+       /* bail if we did not get an IRQ from the bus layer */
+       if (!dev->irq) {
+               pr_debug("No IRQ. Disabling /dev/freefall\n");
+               goto out;
+       }
+
+       /*
+        * The sensor can generate interrupts for free-fall and direction
+        * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+        * the things simple and _fast_ we activate it only for free-fall, so
+        * no need to read register (very slow with ACPI). For the same reason,
+        * we forbid shared interrupts.
+        *
+        * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+        * io-apic is not configurable (and generates a warning) but I keep it
+        * in case of support for other hardware.
+        */
+       if (dev->pdata && dev->whoami == WAI_8B)
+               thread_fn = lis302dl_interrupt_thread1_8b;
+       else
+               thread_fn = NULL;
+
+       err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+                               thread_fn,
+                               IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                               irq_flags,
+                               DRIVER_NAME, &lis3_dev);
+
+       if (err < 0) {
+               pr_err("Cannot get IRQ\n");
+               goto out;
+       }
+
+       if (misc_register(&lis3lv02d_misc_device))
+               pr_err("misc_register failed\n");
+out:
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
+
+MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
new file mode 100644 (file)
index 0000000..a193958
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008-2009 Eric Piel
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * This driver tries to support the "digital" accelerometer chips from
+ * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
+ * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
+ * almost the same registers. In addition to differing on physical properties,
+ * they differ on the number of axes (2/3), precision (8/12 bits), and special
+ * features (freefall detection, click...). Unfortunately, not all the
+ * differences can be probed via a register.
+ * They can be connected either via IĀ²C or SPI.
+ */
+
+#include <linux/lis3lv02d.h>
+
+enum lis3_reg {
+       WHO_AM_I        = 0x0F,
+       OFFSET_X        = 0x16,
+       OFFSET_Y        = 0x17,
+       OFFSET_Z        = 0x18,
+       GAIN_X          = 0x19,
+       GAIN_Y          = 0x1A,
+       GAIN_Z          = 0x1B,
+       CTRL_REG1       = 0x20,
+       CTRL_REG2       = 0x21,
+       CTRL_REG3       = 0x22,
+       CTRL_REG4       = 0x23,
+       HP_FILTER_RESET = 0x23,
+       STATUS_REG      = 0x27,
+       OUTX_L          = 0x28,
+       OUTX_H          = 0x29,
+       OUTX            = 0x29,
+       OUTY_L          = 0x2A,
+       OUTY_H          = 0x2B,
+       OUTY            = 0x2B,
+       OUTZ_L          = 0x2C,
+       OUTZ_H          = 0x2D,
+       OUTZ            = 0x2D,
+};
+
+enum lis302d_reg {
+       FF_WU_CFG_1     = 0x30,
+       FF_WU_SRC_1     = 0x31,
+       FF_WU_THS_1     = 0x32,
+       FF_WU_DURATION_1 = 0x33,
+       FF_WU_CFG_2     = 0x34,
+       FF_WU_SRC_2     = 0x35,
+       FF_WU_THS_2     = 0x36,
+       FF_WU_DURATION_2 = 0x37,
+       CLICK_CFG       = 0x38,
+       CLICK_SRC       = 0x39,
+       CLICK_THSY_X    = 0x3B,
+       CLICK_THSZ      = 0x3C,
+       CLICK_TIMELIMIT = 0x3D,
+       CLICK_LATENCY   = 0x3E,
+       CLICK_WINDOW    = 0x3F,
+};
+
+enum lis3lv02d_reg {
+       FF_WU_CFG       = 0x30,
+       FF_WU_SRC       = 0x31,
+       FF_WU_ACK       = 0x32,
+       FF_WU_THS_L     = 0x34,
+       FF_WU_THS_H     = 0x35,
+       FF_WU_DURATION  = 0x36,
+       DD_CFG          = 0x38,
+       DD_SRC          = 0x39,
+       DD_ACK          = 0x3A,
+       DD_THSI_L       = 0x3C,
+       DD_THSI_H       = 0x3D,
+       DD_THSE_L       = 0x3E,
+       DD_THSE_H       = 0x3F,
+};
+
+enum lis3_who_am_i {
+       WAI_3DC         = 0x33, /* 8 bits: LIS3DC, HP3DC */
+       WAI_12B         = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
+       WAI_8B          = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
+       WAI_6B          = 0x52, /* 6 bits: LIS331DLF - not supported */
+};
+
+enum lis3lv02d_ctrl1_12b {
+       CTRL1_Xen       = 0x01,
+       CTRL1_Yen       = 0x02,
+       CTRL1_Zen       = 0x04,
+       CTRL1_ST        = 0x08,
+       CTRL1_DF0       = 0x10,
+       CTRL1_DF1       = 0x20,
+       CTRL1_PD0       = 0x40,
+       CTRL1_PD1       = 0x80,
+};
+
+/* Delta to ctrl1_12b version */
+enum lis3lv02d_ctrl1_8b {
+       CTRL1_STM       = 0x08,
+       CTRL1_STP       = 0x10,
+       CTRL1_FS        = 0x20,
+       CTRL1_PD        = 0x40,
+       CTRL1_DR        = 0x80,
+};
+
+enum lis3lv02d_ctrl1_3dc {
+       CTRL1_ODR0      = 0x10,
+       CTRL1_ODR1      = 0x20,
+       CTRL1_ODR2      = 0x40,
+       CTRL1_ODR3      = 0x80,
+};
+
+enum lis3lv02d_ctrl2 {
+       CTRL2_DAS       = 0x01,
+       CTRL2_SIM       = 0x02,
+       CTRL2_DRDY      = 0x04,
+       CTRL2_IEN       = 0x08,
+       CTRL2_BOOT      = 0x10,
+       CTRL2_BLE       = 0x20,
+       CTRL2_BDU       = 0x40, /* Block Data Update */
+       CTRL2_FS        = 0x80, /* Full Scale selection */
+};
+
+enum lis3lv02d_ctrl4_3dc {
+       CTRL4_SIM       = 0x01,
+       CTRL4_ST0       = 0x02,
+       CTRL4_ST1       = 0x04,
+       CTRL4_FS0       = 0x10,
+       CTRL4_FS1       = 0x20,
+};
+
+enum lis302d_ctrl2 {
+       HP_FF_WU2       = 0x08,
+       HP_FF_WU1       = 0x04,
+       CTRL2_BOOT_8B   = 0x40,
+};
+
+enum lis3lv02d_ctrl3 {
+       CTRL3_CFS0      = 0x01,
+       CTRL3_CFS1      = 0x02,
+       CTRL3_FDS       = 0x10,
+       CTRL3_HPFF      = 0x20,
+       CTRL3_HPDD      = 0x40,
+       CTRL3_ECK       = 0x80,
+};
+
+enum lis3lv02d_status_reg {
+       STATUS_XDA      = 0x01,
+       STATUS_YDA      = 0x02,
+       STATUS_ZDA      = 0x04,
+       STATUS_XYZDA    = 0x08,
+       STATUS_XOR      = 0x10,
+       STATUS_YOR      = 0x20,
+       STATUS_ZOR      = 0x40,
+       STATUS_XYZOR    = 0x80,
+};
+
+enum lis3lv02d_ff_wu_cfg {
+       FF_WU_CFG_XLIE  = 0x01,
+       FF_WU_CFG_XHIE  = 0x02,
+       FF_WU_CFG_YLIE  = 0x04,
+       FF_WU_CFG_YHIE  = 0x08,
+       FF_WU_CFG_ZLIE  = 0x10,
+       FF_WU_CFG_ZHIE  = 0x20,
+       FF_WU_CFG_LIR   = 0x40,
+       FF_WU_CFG_AOI   = 0x80,
+};
+
+enum lis3lv02d_ff_wu_src {
+       FF_WU_SRC_XL    = 0x01,
+       FF_WU_SRC_XH    = 0x02,
+       FF_WU_SRC_YL    = 0x04,
+       FF_WU_SRC_YH    = 0x08,
+       FF_WU_SRC_ZL    = 0x10,
+       FF_WU_SRC_ZH    = 0x20,
+       FF_WU_SRC_IA    = 0x40,
+};
+
+enum lis3lv02d_dd_cfg {
+       DD_CFG_XLIE     = 0x01,
+       DD_CFG_XHIE     = 0x02,
+       DD_CFG_YLIE     = 0x04,
+       DD_CFG_YHIE     = 0x08,
+       DD_CFG_ZLIE     = 0x10,
+       DD_CFG_ZHIE     = 0x20,
+       DD_CFG_LIR      = 0x40,
+       DD_CFG_IEND     = 0x80,
+};
+
+enum lis3lv02d_dd_src {
+       DD_SRC_XL       = 0x01,
+       DD_SRC_XH       = 0x02,
+       DD_SRC_YL       = 0x04,
+       DD_SRC_YH       = 0x08,
+       DD_SRC_ZL       = 0x10,
+       DD_SRC_ZH       = 0x20,
+       DD_SRC_IA       = 0x40,
+};
+
+enum lis3lv02d_click_src_8b {
+       CLICK_SINGLE_X  = 0x01,
+       CLICK_DOUBLE_X  = 0x02,
+       CLICK_SINGLE_Y  = 0x04,
+       CLICK_DOUBLE_Y  = 0x08,
+       CLICK_SINGLE_Z  = 0x10,
+       CLICK_DOUBLE_Z  = 0x20,
+       CLICK_IA        = 0x40,
+};
+
+enum lis3lv02d_reg_state {
+       LIS3_REG_OFF    = 0x00,
+       LIS3_REG_ON     = 0x01,
+};
+
+union axis_conversion {
+       struct {
+               int x, y, z;
+       };
+       int as_array[3];
+
+};
+
+struct lis3lv02d {
+       void                    *bus_priv; /* used by the bus layer only */
+       struct device           *pm_dev; /* for pm_runtime purposes */
+       int (*init) (struct lis3lv02d *lis3);
+       int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
+       int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+       int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+       int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
+
+       int                     *odrs;     /* Supported output data rates */
+       u8                      *regs;     /* Regs to store / restore */
+       int                     regs_size;
+       u8                      *reg_cache;
+       bool                    regs_stored;
+       u8                      odr_mask;  /* ODR bit mask */
+       u8                      whoami;    /* indicates measurement precision */
+       s16 (*read_data) (struct lis3lv02d *lis3, int reg);
+       int                     mdps_max_val;
+       int                     pwron_delay;
+       int                     scale; /*
+                                       * relationship between 1 LBS and mG
+                                       * (1/1000th of earth gravity)
+                                       */
+
+       struct input_polled_dev *idev;     /* input device */
+       struct platform_device  *pdev;     /* platform device */
+       struct regulator_bulk_data regulators[2];
+       atomic_t                count;     /* interrupt count after last read */
+       union axis_conversion   ac;        /* hw -> logical axis */
+       int                     mapped_btns[3];
+
+       u32                     irq;       /* IRQ number */
+       struct fasync_struct    *async_queue; /* queue for the misc device */
+       wait_queue_head_t       misc_wait; /* Wait queue for the misc device */
+       unsigned long           misc_opened; /* bit0: whether the device is open */
+       int                     data_ready_count[2];
+       atomic_t                wake_thread;
+       unsigned char           irq_cfg;
+
+       struct lis3lv02d_platform_data *pdata;  /* for passing board config */
+       struct mutex            mutex;     /* Serialize poll and selftest */
+};
+
+int lis3lv02d_init_device(struct lis3lv02d *lis3);
+int lis3lv02d_joystick_enable(void);
+void lis3lv02d_joystick_disable(void);
+void lis3lv02d_poweroff(struct lis3lv02d *lis3);
+void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
+
+extern struct lis3lv02d lis3_dev;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
new file mode 100644 (file)
index 0000000..b20dfb4
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * drivers/hwmon/lis3lv02d_i2c.c
+ *
+ * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
+ * Driver is based on corresponding SPI driver written by Daniel Mack
+ * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "lis3lv02d.h"
+
+#define DRV_NAME       "lis3lv02d_i2c"
+
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+       int ret;
+       if (state == LIS3_REG_OFF) {
+               ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+       } else {
+               ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+               /* Chip needs time to wakeup. Not mentioned in datasheet */
+               usleep_range(10000, 20000);
+       }
+       return ret;
+}
+
+static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       *v = i2c_smbus_read_byte_data(c, reg);
+       return 0;
+}
+
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+                               u8 *v)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+       return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
+static int lis3_i2c_init(struct lis3lv02d *lis3)
+{
+       u8 reg;
+       int ret;
+
+       if (lis3->reg_ctrl)
+               lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+       lis3->read(lis3, WHO_AM_I, &reg);
+       if (reg != lis3->whoami)
+               printk(KERN_ERR "lis3: power on failure\n");
+
+       /* power up the device */
+       ret = lis3->read(lis3, CTRL_REG1, &reg);
+       if (ret < 0)
+               return ret;
+
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+       return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+/* Default axis mapping but it can be overwritten by platform data */
+static union axis_conversion lis3lv02d_axis_map =
+       { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
+
+static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+       if (pdata) {
+               /* Regulator control is optional */
+               if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+                       lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+               if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+                       (i2c_check_functionality(client->adapter,
+                                               I2C_FUNC_SMBUS_I2C_BLOCK)))
+                       lis3_dev.blkread  = lis3_i2c_blockread;
+
+               if (pdata->axis_x)
+                       lis3lv02d_axis_map.x = pdata->axis_x;
+
+               if (pdata->axis_y)
+                       lis3lv02d_axis_map.y = pdata->axis_y;
+
+               if (pdata->axis_z)
+                       lis3lv02d_axis_map.z = pdata->axis_z;
+
+               if (pdata->setup_resources)
+                       ret = pdata->setup_resources();
+
+               if (ret)
+                       goto fail;
+       }
+
+       if (lis3_dev.reg_ctrl) {
+               lis3_dev.regulators[0].supply = reg_vdd;
+               lis3_dev.regulators[1].supply = reg_vdd_io;
+               ret = regulator_bulk_get(&client->dev,
+                                       ARRAY_SIZE(lis3_dev.regulators),
+                                       lis3_dev.regulators);
+               if (ret < 0)
+                       goto fail;
+       }
+
+       lis3_dev.pdata    = pdata;
+       lis3_dev.bus_priv = client;
+       lis3_dev.init     = lis3_i2c_init;
+       lis3_dev.read     = lis3_i2c_read;
+       lis3_dev.write    = lis3_i2c_write;
+       lis3_dev.irq      = client->irq;
+       lis3_dev.ac       = lis3lv02d_axis_map;
+       lis3_dev.pm_dev   = &client->dev;
+
+       i2c_set_clientdata(client, &lis3_dev);
+
+       /* Provide power over the init call */
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
+       ret = lis3lv02d_init_device(&lis3_dev);
+
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+       if (ret == 0)
+               return 0;
+fail:
+       if (pdata && pdata->release_resources)
+               pdata->release_resources();
+       return ret;
+}
+
+static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+{
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+       if (pdata && pdata->release_resources)
+               pdata->release_resources();
+
+       lis3lv02d_joystick_disable();
+       lis3lv02d_remove_fs(&lis3_dev);
+
+       if (lis3_dev.reg_ctrl)
+               regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+                               lis3_dev.regulators);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_i2c_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+               lis3lv02d_poweroff(lis3);
+       return 0;
+}
+
+static int lis3lv02d_i2c_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       /*
+        * pm_runtime documentation says that devices should always
+        * be powered on at resume. Pm_runtime turns them off after system
+        * wide resume is complete.
+        */
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+               pm_runtime_suspended(dev))
+               lis3lv02d_poweron(lis3);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweroff(lis3);
+       return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweron(lis3);
+       return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct i2c_device_id lis3lv02d_id[] = {
+       {"lis3lv02d", 0 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
+
+static const struct dev_pm_ops lis3_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+                               lis3lv02d_i2c_resume)
+       SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+                          lis3_i2c_runtime_resume,
+                          NULL)
+};
+
+static struct i2c_driver lis3lv02d_i2c_driver = {
+       .driver  = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &lis3_pm_ops,
+       },
+       .probe  = lis3lv02d_i2c_probe,
+       .remove = __devexit_p(lis3lv02d_i2c_remove),
+       .id_table = lis3lv02d_id,
+};
+
+static int __init lis3lv02d_init(void)
+{
+       return i2c_add_driver(&lis3lv02d_i2c_driver);
+}
+
+static void __exit lis3lv02d_exit(void)
+{
+       i2c_del_driver(&lis3lv02d_i2c_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("lis3lv02d I2C interface");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init);
+module_exit(lis3lv02d_exit);
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
new file mode 100644 (file)
index 0000000..c1f8a8f
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * lis3lv02d_spi - SPI glue layer for lis3lv02d
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/pm.h>
+
+#include "lis3lv02d.h"
+
+#define DRV_NAME       "lis3lv02d_spi"
+#define LIS3_SPI_READ  0x80
+
+static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+       struct spi_device *spi = lis3->bus_priv;
+       int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
+       if (ret < 0)
+               return -EINVAL;
+
+       *v = (u8) ret;
+       return 0;
+}
+
+static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+       u8 tmp[2] = { reg, val };
+       struct spi_device *spi = lis3->bus_priv;
+       return spi_write(spi, tmp, sizeof(tmp));
+}
+
+static int lis3_spi_init(struct lis3lv02d *lis3)
+{
+       u8 reg;
+       int ret;
+
+       /* power up the device */
+       ret = lis3->read(lis3, CTRL_REG1, &reg);
+       if (ret < 0)
+               return ret;
+
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+       return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+static union axis_conversion lis3lv02d_axis_normal =
+       { .as_array = { 1, 2, 3 } };
+
+static int __devinit lis302dl_spi_probe(struct spi_device *spi)
+{
+       int ret;
+
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_0;
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
+       lis3_dev.bus_priv       = spi;
+       lis3_dev.init           = lis3_spi_init;
+       lis3_dev.read           = lis3_spi_read;
+       lis3_dev.write          = lis3_spi_write;
+       lis3_dev.irq            = spi->irq;
+       lis3_dev.ac             = lis3lv02d_axis_normal;
+       lis3_dev.pdata          = spi->dev.platform_data;
+       spi_set_drvdata(spi, &lis3_dev);
+
+       return lis3lv02d_init_device(&lis3_dev);
+}
+
+static int __devexit lis302dl_spi_remove(struct spi_device *spi)
+{
+       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+       lis3lv02d_joystick_disable();
+       lis3lv02d_poweroff(lis3);
+
+       return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_spi_suspend(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+               lis3lv02d_poweroff(&lis3_dev);
+
+       return 0;
+}
+
+static int lis3lv02d_spi_resume(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+               lis3lv02d_poweron(lis3);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
+                        lis3lv02d_spi_resume);
+
+static struct spi_driver lis302dl_spi_driver = {
+       .driver  = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &lis3lv02d_spi_pm,
+       },
+       .probe  = lis302dl_spi_probe,
+       .remove = __devexit_p(lis302dl_spi_remove),
+};
+
+static int __init lis302dl_init(void)
+{
+       return spi_register_driver(&lis302dl_spi_driver);
+}
+
+static void __exit lis302dl_exit(void)
+{
+       spi_unregister_driver(&lis302dl_spi_driver);
+}
+
+module_init(lis302dl_init);
+module_exit(lis302dl_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:" DRV_NAME);
index 7c4c306dfa8a464073b74b8c1358c72ed1f0d12d..0003a1d56f7f63123411de0388e2221abc997193 100644 (file)
@@ -1,6 +1,4 @@
-ifdef CONFIG_SGI_GRU_DEBUG
-  EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_SGI_GRU_DEBUG)        := -DDEBUG
 
 obj-$(CONFIG_SGI_GRU) := gru.o
 gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o grukdump.o
index 2a876c4099cd3d1054e39217424ba85f34772780..3b1f783bf924fccc2168aea37b9a1056d5095dd6 100644 (file)
@@ -58,12 +58,11 @@ config SDIO_UART
 
 config MMC_TEST
        tristate "MMC host test driver"
-       default n
        help
          Development driver that performs a series of reads and writes
          to a memory card in order to expose certain well known bugs
          in host controllers. The tests are executed by writing to the
-         "test" file in sysfs under each card. Note that whatever is
+         "test" file in debugfs under each card. Note that whatever is
          on your card will be overwritten by these tests.
 
          This driver is only of interest to those developing or
index bfc8a8ae55df209458b52e0cb6bfcb1b6f79d989..61d233a7c1180e4b9fea129104ad60f631e60de2 100644 (file)
@@ -621,6 +621,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
        md->disk->private_data = md;
        md->disk->queue = md->queue.queue;
        md->disk->driverfs_dev = &card->dev;
+       set_disk_ro(md->disk, md->read_only);
 
        /*
         * As discussed on lkml, GENHD_FL_REMOVABLE should:
index 21adc27f413281ec5e6d6f0e699a1a12f3b4ce9f..5ec8eddfcf6e6e4db69633c71875005c44812688 100644 (file)
@@ -88,6 +88,7 @@ struct mmc_test_area {
  * @sectors: amount of sectors to check in one group
  * @ts: time values of transfer
  * @rate: calculated transfer rate
+ * @iops: I/O operations per second (times 100)
  */
 struct mmc_test_transfer_result {
        struct list_head link;
@@ -95,6 +96,7 @@ struct mmc_test_transfer_result {
        unsigned int sectors;
        struct timespec ts;
        unsigned int rate;
+       unsigned int iops;
 };
 
 /**
@@ -226,9 +228,10 @@ static int mmc_test_wait_busy(struct mmc_test_card *test)
 
                if (!busy && mmc_test_busy(&cmd)) {
                        busy = 1;
-                       printk(KERN_INFO "%s: Warning: Host did not "
-                               "wait for busy state to end.\n",
-                               mmc_hostname(test->card->host));
+                       if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+                               printk(KERN_INFO "%s: Warning: Host did not "
+                                       "wait for busy state to end.\n",
+                                       mmc_hostname(test->card->host));
                }
        } while (mmc_test_busy(&cmd));
 
@@ -494,7 +497,7 @@ static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts)
  */
 static void mmc_test_save_transfer_result(struct mmc_test_card *test,
        unsigned int count, unsigned int sectors, struct timespec ts,
-       unsigned int rate)
+       unsigned int rate, unsigned int iops)
 {
        struct mmc_test_transfer_result *tr;
 
@@ -509,6 +512,7 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
        tr->sectors = sectors;
        tr->ts = ts;
        tr->rate = rate;
+       tr->iops = iops;
 
        list_add_tail(&tr->link, &test->gr->tr_lst);
 }
@@ -519,20 +523,22 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
 static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
                                struct timespec *ts1, struct timespec *ts2)
 {
-       unsigned int rate, sectors = bytes >> 9;
+       unsigned int rate, iops, sectors = bytes >> 9;
        struct timespec ts;
 
        ts = timespec_sub(*ts2, *ts1);
 
        rate = mmc_test_rate(bytes, &ts);
+       iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
 
        printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
-                        "seconds (%u kB/s, %u KiB/s)\n",
+                        "seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n",
                         mmc_hostname(test->card->host), sectors, sectors >> 1,
                         (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec,
-                        (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024);
+                        (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
+                        iops / 100, iops % 100);
 
-       mmc_test_save_transfer_result(test, 1, sectors, ts, rate);
+       mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
 }
 
 /*
@@ -542,22 +548,24 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
                                    unsigned int count, struct timespec *ts1,
                                    struct timespec *ts2)
 {
-       unsigned int rate, sectors = bytes >> 9;
+       unsigned int rate, iops, sectors = bytes >> 9;
        uint64_t tot = bytes * count;
        struct timespec ts;
 
        ts = timespec_sub(*ts2, *ts1);
 
        rate = mmc_test_rate(tot, &ts);
+       iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
 
        printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
-                        "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n",
+                        "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
+                        "%u.%02u IOPS)\n",
                         mmc_hostname(test->card->host), count, sectors, count,
                         sectors >> 1, (sectors & 1 ? ".5" : ""),
                         (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
-                        rate / 1000, rate / 1024);
+                        rate / 1000, rate / 1024, iops / 100, iops % 100);
 
-       mmc_test_save_transfer_result(test, count, sectors, ts, rate);
+       mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
 }
 
 /*
@@ -1425,28 +1433,29 @@ static int mmc_test_area_cleanup(struct mmc_test_card *test)
 }
 
 /*
- * Initialize an area for testing large transfers.  The size of the area is the
- * preferred erase size which is a good size for optimal transfer speed.  Note
- * that is typically 4MiB for modern cards.  The test area is set to the middle
- * of the card because cards may have different charateristics at the front
- * (for FAT file system optimization).  Optionally, the area is erased (if the
- * card supports it) which may improve write performance.  Optionally, the area
- * is filled with data for subsequent read tests.
+ * Initialize an area for testing large transfers.  The test area is set to the
+ * middle of the card because cards may have different charateristics at the
+ * front (for FAT file system optimization).  Optionally, the area is erased
+ * (if the card supports it) which may improve write performance.  Optionally,
+ * the area is filled with data for subsequent read tests.
  */
 static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
 {
        struct mmc_test_area *t = &test->area;
-       unsigned long min_sz = 64 * 1024;
+       unsigned long min_sz = 64 * 1024, sz;
        int ret;
 
        ret = mmc_test_set_blksize(test, 512);
        if (ret)
                return ret;
 
-       if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9)
-               t->max_sz = TEST_AREA_MAX_SIZE;
-       else
-               t->max_sz = (unsigned long)test->card->pref_erase << 9;
+       /* Make the test area size about 4MiB */
+       sz = (unsigned long)test->card->pref_erase << 9;
+       t->max_sz = sz;
+       while (t->max_sz < 4 * 1024 * 1024)
+               t->max_sz += sz;
+       while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz)
+               t->max_sz -= sz;
 
        t->max_segs = test->card->host->max_segs;
        t->max_seg_sz = test->card->host->max_seg_size;
@@ -1766,6 +1775,188 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
        return 0;
 }
 
+static unsigned int rnd_next = 1;
+
+static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
+{
+       uint64_t r;
+
+       rnd_next = rnd_next * 1103515245 + 12345;
+       r = (rnd_next >> 16) & 0x7fff;
+       return (r * rnd_cnt) >> 15;
+}
+
+static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
+                            unsigned long sz)
+{
+       unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
+       unsigned int ssz;
+       struct timespec ts1, ts2, ts;
+       int ret;
+
+       ssz = sz >> 9;
+
+       rnd_addr = mmc_test_capacity(test->card) / 4;
+       range1 = rnd_addr / test->card->pref_erase;
+       range2 = range1 / ssz;
+
+       getnstimeofday(&ts1);
+       for (cnt = 0; cnt < UINT_MAX; cnt++) {
+               getnstimeofday(&ts2);
+               ts = timespec_sub(ts2, ts1);
+               if (ts.tv_sec >= 10)
+                       break;
+               ea = mmc_test_rnd_num(range1);
+               if (ea == last_ea)
+                       ea -= 1;
+               last_ea = ea;
+               dev_addr = rnd_addr + test->card->pref_erase * ea +
+                          ssz * mmc_test_rnd_num(range2);
+               ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
+               if (ret)
+                       return ret;
+       }
+       if (print)
+               mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+       return 0;
+}
+
+static int mmc_test_random_perf(struct mmc_test_card *test, int write)
+{
+       unsigned int next;
+       unsigned long sz;
+       int ret;
+
+       for (sz = 512; sz < test->area.max_tfr; sz <<= 1) {
+               /*
+                * When writing, try to get more consistent results by running
+                * the test twice with exactly the same I/O but outputting the
+                * results only for the 2nd run.
+                */
+               if (write) {
+                       next = rnd_next;
+                       ret = mmc_test_rnd_perf(test, write, 0, sz);
+                       if (ret)
+                               return ret;
+                       rnd_next = next;
+               }
+               ret = mmc_test_rnd_perf(test, write, 1, sz);
+               if (ret)
+                       return ret;
+       }
+       sz = test->area.max_tfr;
+       if (write) {
+               next = rnd_next;
+               ret = mmc_test_rnd_perf(test, write, 0, sz);
+               if (ret)
+                       return ret;
+               rnd_next = next;
+       }
+       return mmc_test_rnd_perf(test, write, 1, sz);
+}
+
+/*
+ * Random read performance by transfer size.
+ */
+static int mmc_test_random_read_perf(struct mmc_test_card *test)
+{
+       return mmc_test_random_perf(test, 0);
+}
+
+/*
+ * Random write performance by transfer size.
+ */
+static int mmc_test_random_write_perf(struct mmc_test_card *test)
+{
+       return mmc_test_random_perf(test, 1);
+}
+
+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;
+       int ret;
+
+       sz = test->area.max_tfr;
+       /*
+        * In the case of a maximally scattered transfer, the maximum transfer
+        * size is further limited by using PAGE_SIZE segments.
+        */
+       if (max_scatter) {
+               struct mmc_test_area *t = &test->area;
+               unsigned long max_tfr;
+
+               if (t->max_seg_sz >= PAGE_SIZE)
+                       max_tfr = t->max_segs * PAGE_SIZE;
+               else
+                       max_tfr = t->max_segs * t->max_seg_sz;
+               if (sz > max_tfr)
+                       sz = max_tfr;
+       }
+
+       ssz = sz >> 9;
+       dev_addr = mmc_test_capacity(test->card) / 4;
+       if (tot_sz > dev_addr << 9)
+               tot_sz = dev_addr << 9;
+       cnt = tot_sz / sz;
+       dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+
+       getnstimeofday(&ts1);
+       for (i = 0; i < cnt; i++) {
+               ret = mmc_test_area_io(test, sz, dev_addr, write,
+                                      max_scatter, 0);
+               if (ret)
+                       return ret;
+               dev_addr += ssz;
+       }
+       getnstimeofday(&ts2);
+
+       ts = timespec_sub(ts2, ts1);
+       mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+
+       return 0;
+}
+
+static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write)
+{
+       int ret, i;
+
+       for (i = 0; i < 10; i++) {
+               ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1);
+               if (ret)
+                       return ret;
+       }
+       for (i = 0; i < 5; i++) {
+               ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1);
+               if (ret)
+                       return ret;
+       }
+       for (i = 0; i < 3; i++) {
+               ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
+/*
+ * Large sequential read performance.
+ */
+static int mmc_test_large_seq_read_perf(struct mmc_test_card *test)
+{
+       return mmc_test_large_seq_perf(test, 0);
+}
+
+/*
+ * Large sequential write performance.
+ */
+static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
+{
+       return mmc_test_large_seq_perf(test, 1);
+}
+
 static const struct mmc_test_case mmc_test_cases[] = {
        {
                .name = "Basic write (no data verification)",
@@ -2005,6 +2196,34 @@ static const struct mmc_test_case mmc_test_cases[] = {
                .cleanup = mmc_test_area_cleanup,
        },
 
+       {
+               .name = "Random read performance by transfer size",
+               .prepare = mmc_test_area_prepare,
+               .run = mmc_test_random_read_perf,
+               .cleanup = mmc_test_area_cleanup,
+       },
+
+       {
+               .name = "Random write performance by transfer size",
+               .prepare = mmc_test_area_prepare,
+               .run = mmc_test_random_write_perf,
+               .cleanup = mmc_test_area_cleanup,
+       },
+
+       {
+               .name = "Large sequential read into scattered pages",
+               .prepare = mmc_test_area_prepare,
+               .run = mmc_test_large_seq_read_perf,
+               .cleanup = mmc_test_area_cleanup,
+       },
+
+       {
+               .name = "Large sequential write from scattered pages",
+               .prepare = mmc_test_area_prepare,
+               .run = mmc_test_large_seq_write_perf,
+               .cleanup = mmc_test_area_cleanup,
+       },
+
 };
 
 static DEFINE_MUTEX(mmc_test_lock);
@@ -2148,11 +2367,11 @@ static int mtf_test_show(struct seq_file *sf, void *data)
                seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
 
                list_for_each_entry(tr, &gr->tr_lst, link) {
-                       seq_printf(sf, "%u %d %lu.%09lu %u\n",
+                       seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
                                tr->count, tr->sectors,
                                (unsigned long)tr->ts.tv_sec,
                                (unsigned long)tr->ts.tv_nsec,
-                               tr->rate);
+                               tr->rate, tr->iops / 100, tr->iops % 100);
                }
        }
 
index 86b479119332686192ad73bee576c0fce8f1d0ed..639501970b412c7315c4d516da44aa9bf930a203 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_MMC)               += mmc_core.o
 mmc_core-y                     := core.o bus.o host.o \
                                   mmc.o mmc_ops.o sd.o sd_ops.o \
                                   sdio.o sdio_ops.o sdio_bus.o \
-                                  sdio_cis.o sdio_io.o sdio_irq.o
+                                  sdio_cis.o sdio_io.o sdio_irq.o \
+                                  quirks.o
 
 mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
index 150b5f3cd401a7c8549e9e15910a1107b713986e..1f453acc8682b8f828b4f6c9574f2b0f6e1ff7f9 100644 (file)
@@ -167,8 +167,6 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
        WARN_ON(!host->claimed);
 
-       led_trigger_event(host->led, LED_FULL);
-
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
        if (mrq->data) {
@@ -194,6 +192,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
                }
        }
        mmc_host_clk_ungate(host);
+       led_trigger_event(host->led, LED_FULL);
        host->ops->request(host, mrq);
 }
 
@@ -528,7 +527,14 @@ int mmc_try_claim_host(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_try_claim_host);
 
-static void mmc_do_release_host(struct mmc_host *host)
+/**
+ *     mmc_do_release_host - release a claimed host
+ *     @host: mmc host to release
+ *
+ *     If you successfully claimed a host, this function will
+ *     release it again.
+ */
+void mmc_do_release_host(struct mmc_host *host)
 {
        unsigned long flags;
 
@@ -543,6 +549,7 @@ static void mmc_do_release_host(struct mmc_host *host)
                wake_up(&host->wq);
        }
 }
+EXPORT_SYMBOL(mmc_do_release_host);
 
 void mmc_host_deeper_disable(struct work_struct *work)
 {
@@ -1002,6 +1009,13 @@ static void mmc_power_off(struct mmc_host *host)
 {
        host->ios.clock = 0;
        host->ios.vdd = 0;
+
+       /*
+        * Reset ocr mask to be the highest possible voltage supported for
+        * this mmc host. This value will be used at next power up.
+        */
+       host->ocr = 1 << (fls(host->ocr_avail) - 1);
+
        if (!mmc_host_is_spi(host)) {
                host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
                host->ios.chip_select = MMC_CS_DONTCARE;
@@ -1495,6 +1509,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
                mmc_hostname(host), __func__, host->f_init);
 #endif
        mmc_power_up(host);
+
+       /*
+        * sdio_reset sends CMD52 to reset card.  Since we do not know
+        * if the card is being re-initialized, just send it.  CMD52
+        * should be ignored by SD/eMMC cards.
+        */
        sdio_reset(host);
        mmc_go_idle(host);
 
index ca1fdde29df6c9a90f7c1a931588048f5e3425e6..20b1c0831eac8f01e0bd8234d547f37618bd1494 100644 (file)
@@ -61,6 +61,8 @@ int mmc_attach_mmc(struct mmc_host *host);
 int mmc_attach_sd(struct mmc_host *host);
 int mmc_attach_sdio(struct mmc_host *host);
 
+void mmc_fixup_device(struct mmc_card *card);
+
 /* Module parameters */
 extern int use_spi_crc;
 
index b3ac6c5bc5c6289b39299e715d0feb01170b22bb..461e6a17fb90e8526d96054f2ec90f44a85e70c3 100644 (file)
@@ -160,10 +160,7 @@ static bool mmc_host_may_gate_card(struct mmc_card *card)
         * gate the clock, because there is somebody out there that may still
         * be using it.
         */
-       if (mmc_card_sdio(card))
-               return false;
-
-       return true;
+       return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING);
 }
 
 /**
index 16006ef153fe081c2f0f0a09cd4443ce7f3c49a1..14e95f39a7bf3fec3dff6c45048a40c7a67fcd80 100644 (file)
@@ -302,6 +302,44 @@ static int mmc_read_ext_csd(struct mmc_card *card)
        }
 
        if (card->ext_csd.rev >= 4) {
+               /*
+                * Enhanced area feature support -- check whether the eMMC
+                * card has the Enhanced area enabled.  If so, export enhanced
+                * area offset and size to user by adding sysfs interface.
+                */
+               if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+                               (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+                       u8 hc_erase_grp_sz =
+                               ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+                       u8 hc_wp_grp_sz =
+                               ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+                       card->ext_csd.enhanced_area_en = 1;
+                       /*
+                        * calculate the enhanced data area offset, in bytes
+                        */
+                       card->ext_csd.enhanced_area_offset =
+                               (ext_csd[139] << 24) + (ext_csd[138] << 16) +
+                               (ext_csd[137] << 8) + ext_csd[136];
+                       if (mmc_card_blockaddr(card))
+                               card->ext_csd.enhanced_area_offset <<= 9;
+                       /*
+                        * calculate the enhanced data area size, in kilobytes
+                        */
+                       card->ext_csd.enhanced_area_size =
+                               (ext_csd[142] << 16) + (ext_csd[141] << 8) +
+                               ext_csd[140];
+                       card->ext_csd.enhanced_area_size *=
+                               (size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+                       card->ext_csd.enhanced_area_size <<= 9;
+               } else {
+                       /*
+                        * If the enhanced area is not enabled, disable these
+                        * device attributes.
+                        */
+                       card->ext_csd.enhanced_area_offset = -EINVAL;
+                       card->ext_csd.enhanced_area_size = -EINVAL;
+               }
                card->ext_csd.sec_trim_mult =
                        ext_csd[EXT_CSD_SEC_TRIM_MULT];
                card->ext_csd.sec_erase_mult =
@@ -336,6 +374,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
+               card->ext_csd.enhanced_area_offset);
+MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
 
 static struct attribute *mmc_std_attrs[] = {
        &dev_attr_cid.attr,
@@ -349,6 +390,8 @@ static struct attribute *mmc_std_attrs[] = {
        &dev_attr_name.attr,
        &dev_attr_oemid.attr,
        &dev_attr_serial.attr,
+       &dev_attr_enhanced_area_offset.attr,
+       &dev_attr_enhanced_area_size.attr,
        NULL,
 };
 
@@ -378,6 +421,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        int err, ddr = 0;
        u32 cid[4];
        unsigned int max_dtr;
+       u32 rocr;
 
        BUG_ON(!host);
        WARN_ON(!host->claimed);
@@ -391,7 +435,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        mmc_go_idle(host);
 
        /* The extra bit indicates that we support high capacity */
-       err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+       err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
        if (err)
                goto err;
 
@@ -479,10 +523,50 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_read_ext_csd(card);
                if (err)
                        goto free_card;
+
+               /* If doing byte addressing, check if required to do sector
+                * addressing.  Handle the case of <2GB cards needing sector
+                * addressing.  See section 8.1 JEDEC Standard JED84-A441;
+                * ocr register has bit 30 set for sector addressing.
+                */
+               if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
+                       mmc_card_set_blockaddr(card);
+
                /* Erase size depends on CSD and Extended CSD */
                mmc_set_erase_size(card);
        }
 
+       /*
+        * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
+        * bit.  This bit will be lost everytime after a reset or power off.
+        */
+       if (card->ext_csd.enhanced_area_en) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_ERASE_GROUP_DEF, 1);
+
+               if (err && err != -EBADMSG)
+                       goto free_card;
+
+               if (err) {
+                       err = 0;
+                       /*
+                        * Just disable enhanced area off & sz
+                        * will try to enable ERASE_GROUP_DEF
+                        * during next time reinit
+                        */
+                       card->ext_csd.enhanced_area_offset = -EINVAL;
+                       card->ext_csd.enhanced_area_size = -EINVAL;
+               } else {
+                       card->ext_csd.erase_group_def = 1;
+                       /*
+                        * enable ERASE_GRP_DEF successfully.
+                        * This will affect the erase size, so
+                        * here need to reset erase size
+                        */
+                       mmc_set_erase_size(card);
+               }
+       }
+
        /*
         * Activate high speed (if supported)
         */
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
new file mode 100644 (file)
index 0000000..11118b7
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *  This file contains work-arounds for many known sdio hardware
+ *  bugs.
+ *
+ *  Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
+ *  Inspired from pci fixup code:
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mmc/card.h>
+#include <linux/mod_devicetable.h>
+
+/*
+ *  The world is not perfect and supplies us with broken mmc/sdio devices.
+ *  For at least a part of these bugs we need a work-around
+ */
+
+struct mmc_fixup {
+       u16 vendor, device;     /* You can use SDIO_ANY_ID here of course */
+       void (*vendor_fixup)(struct mmc_card *card, int data);
+       int data;
+};
+
+/*
+ * This hook just adds a quirk unconditionnally
+ */
+static void __maybe_unused add_quirk(struct mmc_card *card, int data)
+{
+       card->quirks |= data;
+}
+
+/*
+ * This hook just removes a quirk unconditionnally
+ */
+static void __maybe_unused remove_quirk(struct mmc_card *card, int data)
+{
+       card->quirks &= ~data;
+}
+
+/*
+ * This hook just adds a quirk for all sdio devices
+ */
+static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
+{
+       if (mmc_card_sdio(card))
+               card->quirks |= data;
+}
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI              0x0097
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1271
+#define SDIO_DEVICE_ID_TI_WL1271       0x4076
+#endif
+
+static const struct mmc_fixup mmc_fixup_methods[] = {
+       /* by default sdio devices are considered CLK_GATING broken */
+       /* good cards will be whitelisted as they are tested */
+       { SDIO_ANY_ID, SDIO_ANY_ID,
+               add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING },
+       { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
+               remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING },
+       { 0 }
+};
+
+void mmc_fixup_device(struct mmc_card *card)
+{
+       const struct mmc_fixup *f;
+
+       for (f = mmc_fixup_methods; f->vendor_fixup; f++) {
+               if ((f->vendor == card->cis.vendor
+                    || f->vendor == (u16) SDIO_ANY_ID) &&
+                   (f->device == card->cis.device
+                    || f->device == (u16) SDIO_ANY_ID)) {
+                       dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
+                       f->vendor_fixup(card, f->data);
+               }
+       }
+}
+EXPORT_SYMBOL(mmc_fixup_device);
index d18c32bca99bae78fe3b0f04d22c2f124ce86cb5..6dac89fe0535ad02b272e5fbe658627d0263fd29 100644 (file)
@@ -21,6 +21,7 @@
 #include "core.h"
 #include "bus.h"
 #include "mmc_ops.h"
+#include "sd.h"
 #include "sd_ops.h"
 
 static const unsigned int tran_exp[] = {
index ebc62ad4cc567b7aee3313835050770dd1ff14f0..db0f0b44d684617b006b7eaa787e07fd0cd1017b 100644 (file)
@@ -395,6 +395,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
                if (err)
                        goto remove;
 
+               /*
+                * Update oldcard with the new RCA received from the SDIO
+                * device -- we're doing this so that it's updated in the
+                * "card" struct when oldcard overwrites that later.
+                */
+               if (oldcard)
+                       oldcard->rca = card->rca;
+
                mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
        }
 
@@ -458,6 +466,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 
                card = oldcard;
        }
+       mmc_fixup_device(card);
 
        if (card->type == MMC_TYPE_SD_COMBO) {
                err = mmc_sd_setup_card(host, card, oldcard != NULL);
index 54f91321749a526b07d78ca96739968731386d27..1a21c6427a19769c84cb31018c7d745ea5517164 100644 (file)
@@ -311,7 +311,7 @@ config MMC_MSM
 
 config MMC_MXC
        tristate "Freescale i.MX2/3 Multimedia Card Interface support"
-       depends on ARCH_MXC
+       depends on MACH_MX21 || MACH_MX27 || ARCH_MX31
        help
          This selects the Freescale i.MX2/3 Multimedia card Interface.
          If you have a i.MX platform with a Multimedia Card slot,
@@ -319,6 +319,15 @@ config MMC_MXC
 
          If unsure, say N.
 
+config MMC_MXS
+       tristate "Freescale MXS Multimedia Card Interface support"
+       depends on ARCH_MXS && MXS_DMA
+       help
+         This selects the Freescale SSP MMC controller found on MXS based
+         platforms like mx23/28.
+
+         If unsure, say N.
+
 config MMC_TIFM_SD
        tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
        depends on EXPERIMENTAL && PCI
index e834fb223e9a80f7a84615b2a2a95d26348e808d..30aa6867745f442ddbba5bfe219a5881bd8ef053 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_MMC_ARMMMCI)       += mmci.o
 obj-$(CONFIG_MMC_PXA)          += pxamci.o
 obj-$(CONFIG_MMC_IMX)          += imxmmc.o
 obj-$(CONFIG_MMC_MXC)          += mxcmmc.o
+obj-$(CONFIG_MMC_MXS)          += mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
 obj-$(CONFIG_MMC_SDHCI_PXA)    += sdhci-pxa.o
index ad2a7a032cdf02478a80cd87055abce9648e31ca..80bc9a5c25cc3ef3f6bd7656c03e5d2da00ee0c7 100644 (file)
@@ -578,7 +578,8 @@ static void atmci_dma_cleanup(struct atmel_mci *host)
        struct mmc_data                 *data = host->data;
 
        if (data)
-               dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+               dma_unmap_sg(host->dma.chan->device->dev,
+                            data->sg, data->sg_len,
                             ((data->flags & MMC_DATA_WRITE)
                              ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
 }
@@ -588,7 +589,7 @@ static void atmci_stop_dma(struct atmel_mci *host)
        struct dma_chan *chan = host->data_chan;
 
        if (chan) {
-         chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+               dmaengine_terminate_all(chan);
                atmci_dma_cleanup(host);
        } else {
                /* Data transfer was stopped by the interrupt handler */
@@ -684,11 +685,11 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
        else
                direction = DMA_TO_DEVICE;
 
-       sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction);
-       if (sglen != data->sg_len)
-               goto unmap_exit;
+       sglen = dma_map_sg(chan->device->dev, data->sg,
+                          data->sg_len, direction);
+
        desc = chan->device->device_prep_slave_sg(chan,
-                       data->sg, data->sg_len, direction,
+                       data->sg, sglen, direction,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc)
                goto unmap_exit;
@@ -699,7 +700,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
 
        return 0;
 unmap_exit:
-       dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction);
+       dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction);
        return -ENOMEM;
 }
 
@@ -709,8 +710,8 @@ static void atmci_submit_data(struct atmel_mci *host)
        struct dma_async_tx_descriptor  *desc = host->dma.data_desc;
 
        if (chan) {
-               desc->tx_submit(desc);
-               chan->device->device_issue_pending(chan);
+               dmaengine_submit(desc);
+               dma_async_issue_pending(chan);
        }
 }
 
index 66b4ce587f4bdb13bf3ff5de67f289f5f3a9d580..ce2a47b71dd6a0fe8b73d5eefb616607d04fe731 100644 (file)
@@ -205,7 +205,7 @@ static int cb710_wait_while_busy(struct cb710_slot *slot, uint8_t mask)
                        "WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n",
                        limit, mask, e, x);
 #endif
-       return 0;
+       return err;
 }
 
 static void cb710_mmc_set_transfer_size(struct cb710_slot *slot,
index 2fcc82577c1b156c08102270903b5b28ef2c430f..5a614069cb00b67122d053635897e769972adb0d 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/dw_mmc.h>
 #include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
 
 #include "dw_mmc.h"
 
@@ -562,7 +563,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
                             SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
                /* enable clock */
-               mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE);
+               mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE |
+                          SDMMC_CLKEN_LOW_PWR);
 
                /* inform CIU */
                mci_send_cmd(slot,
@@ -661,6 +663,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       u32 regs;
 
        /* set default 1 bit mode */
        slot->ctype = SDMMC_CTYPE_1BIT;
@@ -672,6 +675,16 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_BUS_WIDTH_4:
                slot->ctype = SDMMC_CTYPE_4BIT;
                break;
+       case MMC_BUS_WIDTH_8:
+               slot->ctype = SDMMC_CTYPE_8BIT;
+               break;
+       }
+
+       /* DDR mode set */
+       if (ios->ddr) {
+               regs = mci_readl(slot->host, UHS_REG);
+               regs |= (0x1 << slot->id) << 16;
+               mci_writel(slot->host, UHS_REG, regs);
        }
 
        if (ios->clock) {
@@ -717,7 +730,9 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        struct dw_mci_board *brd = slot->host->pdata;
 
        /* Use platform get_cd function, else try onboard card detect */
-       if (brd->get_cd)
+       if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+               present = 1;
+       else if (brd->get_cd)
                present = !brd->get_cd(slot->id);
        else
                present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
@@ -1019,13 +1034,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
        struct mmc_data *data = host->data;
        int shift = host->data_shift;
        u32 status;
-       unsigned int nbytes = 0, len, old_len, count = 0;
+       unsigned int nbytes = 0, len;
 
        do {
                len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
-               if (count == 0)
-                       old_len = len;
-
                if (offset + len <= sg->length) {
                        host->pull_data(host, (void *)(buf + offset), len);
 
@@ -1070,7 +1082,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
                        tasklet_schedule(&host->tasklet);
                        return;
                }
-               count++;
        } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
        len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
        host->pio_offset = offset;
@@ -1395,7 +1406,11 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (host->pdata->setpower)
                host->pdata->setpower(id, 0);
 
-       mmc->caps = 0;
+       if (host->pdata->caps)
+               mmc->caps = host->pdata->caps;
+       else
+               mmc->caps = 0;
+
        if (host->pdata->get_bus_wd)
                if (host->pdata->get_bus_wd(slot->id) >= 4)
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1426,6 +1441,13 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        }
 #endif /* CONFIG_MMC_DW_IDMAC */
 
+       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+       if (IS_ERR(host->vmmc)) {
+               printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
+               host->vmmc = NULL;
+       } else
+               regulator_enable(host->vmmc);
+
        if (dw_mci_get_cd(mmc))
                set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
        else
@@ -1441,6 +1463,12 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        /* Card initially undetected */
        slot->last_detect_state = 0;
 
+       /*
+        * Card may have been plugged in prior to boot so we
+        * need to run the detect tasklet
+        */
+       tasklet_schedule(&host->card_tasklet);
+
        return 0;
 }
 
@@ -1619,8 +1647,9 @@ static int dw_mci_probe(struct platform_device *pdev)
         */
        fifo_size = mci_readl(host, FIFOTH);
        fifo_size = (fifo_size >> 16) & 0x7ff;
-       mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
-                                 ((fifo_size/2) << 0)));
+       host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
+                       ((fifo_size/2) << 0));
+       mci_writel(host, FIFOTH, host->fifoth_val);
 
        /* disable clock to CIU */
        mci_writel(host, CLKENA, 0);
@@ -1683,6 +1712,12 @@ err_dmaunmap:
                          host->sg_cpu, host->sg_dma);
        iounmap(host->regs);
 
+       if (host->vmmc) {
+               regulator_disable(host->vmmc);
+               regulator_put(host->vmmc);
+       }
+
+
 err_freehost:
        kfree(host);
        return ret;
@@ -1714,6 +1749,11 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
 
+       if (host->vmmc) {
+               regulator_disable(host->vmmc);
+               regulator_put(host->vmmc);
+       }
+
        iounmap(host->regs);
 
        kfree(host);
@@ -1729,6 +1769,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
        int i, ret;
        struct dw_mci *host = platform_get_drvdata(pdev);
 
+       if (host->vmmc)
+               regulator_enable(host->vmmc);
+
        for (i = 0; i < host->num_slots; i++) {
                struct dw_mci_slot *slot = host->slot[i];
                if (!slot)
@@ -1744,6 +1787,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
                }
        }
 
+       if (host->vmmc)
+               regulator_disable(host->vmmc);
+
        return 0;
 }
 
@@ -1752,6 +1798,23 @@ static int dw_mci_resume(struct platform_device *pdev)
        int i, ret;
        struct dw_mci *host = platform_get_drvdata(pdev);
 
+       if (host->dma_ops->init)
+               host->dma_ops->init(host);
+
+       if (!mci_wait_reset(&pdev->dev, host)) {
+               ret = -ENODEV;
+               return ret;
+       }
+
+       /* Restore the old value at FIFOTH register */
+       mci_writel(host, FIFOTH, host->fifoth_val);
+
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
+
        for (i = 0; i < host->num_slots; i++) {
                struct dw_mci_slot *slot = host->slot[i];
                if (!slot)
index 5dd55a75233d912f9a9be9d6f82de04a76eff93d..23c662af5616f3a741e14e685b43ec5c5dcc66e7 100644 (file)
@@ -43,6 +43,7 @@
 #define SDMMC_USRID            0x068
 #define SDMMC_VERID            0x06c
 #define SDMMC_HCON             0x070
+#define SDMMC_UHS_REG          0x074
 #define SDMMC_BMOD             0x080
 #define SDMMC_PLDMND           0x084
 #define SDMMC_DBADDR           0x088
@@ -51,7 +52,6 @@
 #define SDMMC_DSCADDR          0x094
 #define SDMMC_BUFADDR          0x098
 #define SDMMC_DATA             0x100
-#define SDMMC_DATA_ADR         0x100
 
 /* shift bit field */
 #define _SBF(f, v)             ((v) << (f))
index 97c9b3638d57ea81aef3917c042b0067234fa31b..a4c865a5286b2cde603898fd7e4a669e429855f1 100644 (file)
@@ -267,14 +267,6 @@ msmsdcc_dma_complete_tlet(unsigned long data)
        dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
                     host->dma.dir);
 
-       if (host->curr.user_pages) {
-               struct scatterlist *sg = host->dma.sg;
-               int i;
-
-               for (i = 0; i < host->dma.num_ents; i++)
-                       flush_dcache_page(sg_page(sg++));
-       }
-
        host->dma.sg = NULL;
        host->dma.busy = 0;
 
index 4428594261c52cbc42b5e265e1e26ab52c947820..cc20e025932593db93deb84d3e27f05bf9ed89c0 100644 (file)
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
 #include <mach/mmc.h>
 
-#ifdef CONFIG_ARCH_MX2
-#include <mach/dma-mx1-mx2.h>
-#define HAS_DMA
-#endif
+#include <mach/dma.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
@@ -118,7 +116,8 @@ struct mxcmci_host {
        void __iomem            *base;
        int                     irq;
        int                     detect_irq;
-       int                     dma;
+       struct dma_chan         *dma;
+       struct dma_async_tx_descriptor *desc;
        int                     do_dma;
        int                     default_irq_mask;
        int                     use_sdio;
@@ -129,7 +128,6 @@ struct mxcmci_host {
        struct mmc_command      *cmd;
        struct mmc_data         *data;
 
-       unsigned int            dma_nents;
        unsigned int            datasize;
        unsigned int            dma_dir;
 
@@ -144,6 +142,11 @@ struct mxcmci_host {
        spinlock_t              lock;
 
        struct regulator        *vcc;
+
+       int                     burstlen;
+       int                     dmareq;
+       struct dma_slave_config dma_slave_config;
+       struct imx_dma_data     dma_data;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -206,17 +209,16 @@ static void mxcmci_softreset(struct mxcmci_host *host)
 
        writew(0xff, host->base + MMC_REG_RES_TO);
 }
+static int mxcmci_setup_dma(struct mmc_host *mmc);
 
 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 {
        unsigned int nob = data->blocks;
        unsigned int blksz = data->blksz;
        unsigned int datasize = nob * blksz;
-#ifdef HAS_DMA
        struct scatterlist *sg;
-       int i;
-       int ret;
-#endif
+       int i, nents;
+
        if (data->flags & MMC_DATA_STREAM)
                nob = 0xffff;
 
@@ -227,7 +229,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
        writew(blksz, host->base + MMC_REG_BLK_LEN);
        host->datasize = datasize;
 
-#ifdef HAS_DMA
+       if (!mxcmci_use_dma(host))
+               return 0;
+
        for_each_sg(data->sg, sg, data->sg_len, i) {
                if (sg->offset & 3 || sg->length & 3) {
                        host->do_dma = 0;
@@ -235,34 +239,30 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
                }
        }
 
-       if (data->flags & MMC_DATA_READ) {
+       if (data->flags & MMC_DATA_READ)
                host->dma_dir = DMA_FROM_DEVICE;
-               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                            data->sg_len,  host->dma_dir);
-
-               ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-                               datasize,
-                               host->res->start + MMC_REG_BUFFER_ACCESS,
-                               DMA_MODE_READ);
-       } else {
+       else
                host->dma_dir = DMA_TO_DEVICE;
-               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                            data->sg_len,  host->dma_dir);
 
-               ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-                               datasize,
-                               host->res->start + MMC_REG_BUFFER_ACCESS,
-                               DMA_MODE_WRITE);
-       }
+       nents = dma_map_sg(host->dma->device->dev, data->sg,
+                                    data->sg_len,  host->dma_dir);
+       if (nents != data->sg_len)
+               return -EINVAL;
+
+       host->desc = host->dma->device->device_prep_slave_sg(host->dma,
+               data->sg, data->sg_len, host->dma_dir,
+               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
-       if (ret) {
-               dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret);
-               return ret;
+       if (!host->desc) {
+               dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
+                               host->dma_dir);
+               host->do_dma = 0;
+               return 0; /* Fall back to PIO */
        }
        wmb();
 
-       imx_dma_enable(host->dma);
-#endif /* HAS_DMA */
+       dmaengine_submit(host->desc);
+
        return 0;
 }
 
@@ -337,13 +337,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
        struct mmc_data *data = host->data;
        int data_error;
 
-#ifdef HAS_DMA
        if (mxcmci_use_dma(host)) {
-               imx_dma_disable(host->dma);
-               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+               dmaengine_terminate_all(host->dma);
+               dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
                                host->dma_dir);
        }
-#endif
 
        if (stat & STATUS_ERR_MASK) {
                dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -545,7 +543,6 @@ static void mxcmci_datawork(struct work_struct *work)
        }
 }
 
-#ifdef HAS_DMA
 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 {
        struct mmc_data *data = host->data;
@@ -568,7 +565,6 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
                mxcmci_finish_request(host, host->req);
        }
 }
-#endif /* HAS_DMA */
 
 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
 {
@@ -606,12 +602,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
        sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
        spin_unlock_irqrestore(&host->lock, flags);
 
-#ifdef HAS_DMA
        if (mxcmci_use_dma(host) &&
            (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
                writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
                        host->base + MMC_REG_STATUS);
-#endif
 
        if (sdio_irq) {
                writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS);
@@ -621,14 +615,14 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
        if (stat & STATUS_END_CMD_RESP)
                mxcmci_cmd_done(host, stat);
 
-#ifdef HAS_DMA
        if (mxcmci_use_dma(host) &&
                  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
                mxcmci_data_done(host, stat);
-#endif
+
        if (host->default_irq_mask &&
                  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
                mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+
        return IRQ_HANDLED;
 }
 
@@ -642,9 +636,10 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
 
        host->req = req;
        host->cmdat &= ~CMD_DAT_CONT_INIT;
-#ifdef HAS_DMA
-       host->do_dma = 1;
-#endif
+
+       if (host->dma)
+               host->do_dma = 1;
+
        if (req->data) {
                error = mxcmci_setup_data(host, req->data);
                if (error) {
@@ -660,6 +655,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
        }
 
        error = mxcmci_start_cmd(host, req->cmd, cmdat);
+
 out:
        if (error)
                mxcmci_finish_request(host, req);
@@ -698,22 +694,46 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
                        prescaler, divider, clk_in, clk_ios);
 }
 
+static int mxcmci_setup_dma(struct mmc_host *mmc)
+{
+       struct mxcmci_host *host = mmc_priv(mmc);
+       struct dma_slave_config *config = &host->dma_slave_config;
+
+       config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+       config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+       config->dst_addr_width = 4;
+       config->src_addr_width = 4;
+       config->dst_maxburst = host->burstlen;
+       config->src_maxburst = host->burstlen;
+
+       return dmaengine_slave_config(host->dma, config);
+}
+
 static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct mxcmci_host *host = mmc_priv(mmc);
-#ifdef HAS_DMA
-       unsigned int blen;
+       int burstlen, ret;
+
        /*
         * use burstlen of 64 in 4 bit mode (--> reg value  0)
         * use burstlen of 16 in 1 bit mode (--> reg value 16)
         */
        if (ios->bus_width == MMC_BUS_WIDTH_4)
-               blen = 0;
+               burstlen = 64;
        else
-               blen = 16;
+               burstlen = 16;
+
+       if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
+               host->burstlen = burstlen;
+               ret = mxcmci_setup_dma(mmc);
+               if (ret) {
+                       dev_err(mmc_dev(host->mmc),
+                               "failed to config DMA channel. Falling back to PIO\n");
+                       dma_release_channel(host->dma);
+                       host->do_dma = 0;
+               }
+       }
 
-       imx_dma_config_burstlen(host->dma, blen);
-#endif
        if (ios->bus_width == MMC_BUS_WIDTH_4)
                host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
        else
@@ -794,6 +814,18 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
                host->caps |= MMC_CAP_4_BIT_DATA;
 }
 
+static bool filter(struct dma_chan *chan, void *param)
+{
+       struct mxcmci_host *host = param;
+
+       if (!imx_dma_is_general_purpose(chan))
+               return false;
+
+       chan->private = &host->dma_data;
+
+       return true;
+}
+
 static const struct mmc_host_ops mxcmci_ops = {
        .request                = mxcmci_request,
        .set_ios                = mxcmci_set_ios,
@@ -808,6 +840,7 @@ static int mxcmci_probe(struct platform_device *pdev)
        struct mxcmci_host *host = NULL;
        struct resource *iores, *r;
        int ret = 0, irq;
+       dma_cap_mask_t mask;
 
        printk(KERN_INFO "i.MX SDHC driver\n");
 
@@ -883,29 +916,23 @@ static int mxcmci_probe(struct platform_device *pdev)
 
        writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
 
-#ifdef HAS_DMA
-       host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
-       if (host->dma < 0) {
-               dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
-               ret = -EBUSY;
-               goto out_clk_put;
-       }
-
        r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r) {
-               ret = -EINVAL;
-               goto out_free_dma;
+       if (r) {
+               host->dmareq = r->start;
+               host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
+               host->dma_data.priority = DMA_PRIO_LOW;
+               host->dma_data.dma_request = host->dmareq;
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+               host->dma = dma_request_channel(mask, filter, host);
+               if (host->dma)
+                       mmc->max_seg_size = dma_get_max_seg_size(
+                                       host->dma->device->dev);
        }
 
-       ret = imx_dma_config_channel(host->dma,
-                                    IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
-                                    IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-                                    r->start, 0);
-       if (ret) {
-               dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
-               goto out_free_dma;
-       }
-#endif
+       if (!host->dma)
+               dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
+
        INIT_WORK(&host->datawork, mxcmci_datawork);
 
        ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
@@ -928,9 +955,8 @@ static int mxcmci_probe(struct platform_device *pdev)
 out_free_irq:
        free_irq(host->irq, host);
 out_free_dma:
-#ifdef HAS_DMA
-       imx_dma_free(host->dma);
-#endif
+       if (host->dma)
+               dma_release_channel(host->dma);
 out_clk_put:
        clk_disable(host->clk);
        clk_put(host->clk);
@@ -960,9 +986,10 @@ static int mxcmci_remove(struct platform_device *pdev)
 
        free_irq(host->irq, host);
        iounmap(host->base);
-#ifdef HAS_DMA
-       imx_dma_free(host->dma);
-#endif
+
+       if (host->dma)
+               dma_release_channel(host->dma);
+
        clk_disable(host->clk);
        clk_put(host->clk);
 
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
new file mode 100644 (file)
index 0000000..99d39a6
--- /dev/null
@@ -0,0 +1,874 @@
+/*
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/mmc.h>
+
+#define DRIVER_NAME    "mxs-mmc"
+
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT                 (HZ/2)
+
+#define SSP_VERSION_LATEST     4
+#define ssp_is_old()           (host->version < SSP_VERSION_LATEST)
+
+/* SSP registers */
+#define HW_SSP_CTRL0                           0x000
+#define  BM_SSP_CTRL0_RUN                      (1 << 29)
+#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK           (1 << 28)
+#define  BM_SSP_CTRL0_IGNORE_CRC               (1 << 26)
+#define  BM_SSP_CTRL0_READ                     (1 << 25)
+#define  BM_SSP_CTRL0_DATA_XFER                        (1 << 24)
+#define  BP_SSP_CTRL0_BUS_WIDTH                        (22)
+#define  BM_SSP_CTRL0_BUS_WIDTH                        (0x3 << 22)
+#define  BM_SSP_CTRL0_WAIT_FOR_IRQ             (1 << 21)
+#define  BM_SSP_CTRL0_LONG_RESP                        (1 << 19)
+#define  BM_SSP_CTRL0_GET_RESP                 (1 << 17)
+#define  BM_SSP_CTRL0_ENABLE                   (1 << 16)
+#define  BP_SSP_CTRL0_XFER_COUNT               (0)
+#define  BM_SSP_CTRL0_XFER_COUNT               (0xffff)
+#define HW_SSP_CMD0                            0x010
+#define  BM_SSP_CMD0_DBL_DATA_RATE_EN          (1 << 25)
+#define  BM_SSP_CMD0_SLOW_CLKING_EN            (1 << 22)
+#define  BM_SSP_CMD0_CONT_CLKING_EN            (1 << 21)
+#define  BM_SSP_CMD0_APPEND_8CYC               (1 << 20)
+#define  BP_SSP_CMD0_BLOCK_SIZE                        (16)
+#define  BM_SSP_CMD0_BLOCK_SIZE                        (0xf << 16)
+#define  BP_SSP_CMD0_BLOCK_COUNT               (8)
+#define  BM_SSP_CMD0_BLOCK_COUNT               (0xff << 8)
+#define  BP_SSP_CMD0_CMD                       (0)
+#define  BM_SSP_CMD0_CMD                       (0xff)
+#define HW_SSP_CMD1                            0x020
+#define HW_SSP_XFER_SIZE                       0x030
+#define HW_SSP_BLOCK_SIZE                      0x040
+#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT         (4)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT         (0xffffff << 4)
+#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE          (0)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE          (0xf)
+#define HW_SSP_TIMING                          (ssp_is_old() ? 0x050 : 0x070)
+#define  BP_SSP_TIMING_TIMEOUT                 (16)
+#define  BM_SSP_TIMING_TIMEOUT                 (0xffff << 16)
+#define  BP_SSP_TIMING_CLOCK_DIVIDE            (8)
+#define  BM_SSP_TIMING_CLOCK_DIVIDE            (0xff << 8)
+#define  BP_SSP_TIMING_CLOCK_RATE              (0)
+#define  BM_SSP_TIMING_CLOCK_RATE              (0xff)
+#define HW_SSP_CTRL1                           (ssp_is_old() ? 0x060 : 0x080)
+#define  BM_SSP_CTRL1_SDIO_IRQ                 (1 << 31)
+#define  BM_SSP_CTRL1_SDIO_IRQ_EN              (1 << 30)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ             (1 << 29)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN          (1 << 28)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ         (1 << 27)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN      (1 << 26)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ         (1 << 25)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN      (1 << 24)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ             (1 << 23)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN          (1 << 22)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ                (1 << 21)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN     (1 << 20)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ         (1 << 17)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN      (1 << 16)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ         (1 << 15)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN      (1 << 14)
+#define  BM_SSP_CTRL1_DMA_ENABLE               (1 << 13)
+#define  BM_SSP_CTRL1_POLARITY                 (1 << 9)
+#define  BP_SSP_CTRL1_WORD_LENGTH              (4)
+#define  BM_SSP_CTRL1_WORD_LENGTH              (0xf << 4)
+#define  BP_SSP_CTRL1_SSP_MODE                 (0)
+#define  BM_SSP_CTRL1_SSP_MODE                 (0xf)
+#define HW_SSP_SDRESP0                         (ssp_is_old() ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1                         (ssp_is_old() ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2                         (ssp_is_old() ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3                         (ssp_is_old() ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS                          (ssp_is_old() ? 0x0c0 : 0x100)
+#define  BM_SSP_STATUS_CARD_DETECT             (1 << 28)
+#define  BM_SSP_STATUS_SDIO_IRQ                        (1 << 17)
+#define HW_SSP_VERSION                         (cpu_is_mx23() ? 0x110 : 0x130)
+#define  BP_SSP_VERSION_MAJOR                  (24)
+
+#define BF_SSP(value, field)   (((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define MXS_MMC_IRQ_BITS       (BM_SSP_CTRL1_SDIO_IRQ          | \
+                                BM_SSP_CTRL1_RESP_ERR_IRQ      | \
+                                BM_SSP_CTRL1_RESP_TIMEOUT_IRQ  | \
+                                BM_SSP_CTRL1_DATA_TIMEOUT_IRQ  | \
+                                BM_SSP_CTRL1_DATA_CRC_IRQ      | \
+                                BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ | \
+                                BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
+                                BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+
+#define SSP_PIO_NUM    3
+
+struct mxs_mmc_host {
+       struct mmc_host                 *mmc;
+       struct mmc_request              *mrq;
+       struct mmc_command              *cmd;
+       struct mmc_data                 *data;
+
+       void __iomem                    *base;
+       int                             irq;
+       struct resource                 *res;
+       struct resource                 *dma_res;
+       struct clk                      *clk;
+       unsigned int                    clk_rate;
+
+       struct dma_chan                 *dmach;
+       struct mxs_dma_data             dma_data;
+       unsigned int                    dma_dir;
+       u32                             ssp_pio_words[SSP_PIO_NUM];
+
+       unsigned int                    version;
+       unsigned char                   bus_width;
+       spinlock_t                      lock;
+       int                             sdio_irq_en;
+};
+
+static int mxs_mmc_get_ro(struct mmc_host *mmc)
+{
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_mmc_platform_data *pdata =
+               mmc_dev(host->mmc)->platform_data;
+
+       if (!pdata)
+               return -EFAULT;
+
+       if (!gpio_is_valid(pdata->wp_gpio))
+               return -EINVAL;
+
+       return gpio_get_value(pdata->wp_gpio);
+}
+
+static int mxs_mmc_get_cd(struct mmc_host *mmc)
+{
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+
+       return !(readl(host->base + HW_SSP_STATUS) &
+                BM_SSP_STATUS_CARD_DETECT);
+}
+
+static void mxs_mmc_reset(struct mxs_mmc_host *host)
+{
+       u32 ctrl0, ctrl1;
+
+       mxs_reset_block(host->base);
+
+       ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
+       ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
+               BF_SSP(0x7, CTRL1_WORD_LENGTH) |
+               BM_SSP_CTRL1_DMA_ENABLE |
+               BM_SSP_CTRL1_POLARITY |
+               BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+               BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+               BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+               BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+               BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
+
+       writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
+              BF_SSP(2, TIMING_CLOCK_DIVIDE) |
+              BF_SSP(0, TIMING_CLOCK_RATE),
+              host->base + HW_SSP_TIMING);
+
+       if (host->sdio_irq_en) {
+               ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+               ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
+       }
+
+       writel(ctrl0, host->base + HW_SSP_CTRL0);
+       writel(ctrl1, host->base + HW_SSP_CTRL1);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+                             struct mmc_command *cmd);
+
+static void mxs_mmc_request_done(struct mxs_mmc_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       struct mmc_data *data = host->data;
+       struct mmc_request *mrq = host->mrq;
+
+       if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
+               if (mmc_resp_type(cmd) & MMC_RSP_136) {
+                       cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0);
+                       cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1);
+                       cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2);
+                       cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3);
+               } else {
+                       cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0);
+               }
+       }
+
+       if (data) {
+               dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+                            data->sg_len, host->dma_dir);
+               /*
+                * If there was an error on any block, we mark all
+                * data blocks as being in error.
+                */
+               if (!data->error)
+                       data->bytes_xfered = data->blocks * data->blksz;
+               else
+                       data->bytes_xfered = 0;
+
+               host->data = NULL;
+               if (mrq->stop) {
+                       mxs_mmc_start_cmd(host, mrq->stop);
+                       return;
+               }
+       }
+
+       host->mrq = NULL;
+       mmc_request_done(host->mmc, mrq);
+}
+
+static void mxs_mmc_dma_irq_callback(void *param)
+{
+       struct mxs_mmc_host *host = param;
+
+       mxs_mmc_request_done(host);
+}
+
+static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
+{
+       struct mxs_mmc_host *host = dev_id;
+       struct mmc_command *cmd = host->cmd;
+       struct mmc_data *data = host->data;
+       u32 stat;
+
+       spin_lock(&host->lock);
+
+       stat = readl(host->base + HW_SSP_CTRL1);
+       writel(stat & MXS_MMC_IRQ_BITS,
+              host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+
+       if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
+               mmc_signal_sdio_irq(host->mmc);
+
+       spin_unlock(&host->lock);
+
+       if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
+               cmd->error = -ETIMEDOUT;
+       else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
+               cmd->error = -EIO;
+
+       if (data) {
+               if (stat & (BM_SSP_CTRL1_DATA_TIMEOUT_IRQ |
+                           BM_SSP_CTRL1_RECV_TIMEOUT_IRQ))
+                       data->error = -ETIMEDOUT;
+               else if (stat & BM_SSP_CTRL1_DATA_CRC_IRQ)
+                       data->error = -EILSEQ;
+               else if (stat & (BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ |
+                                BM_SSP_CTRL1_FIFO_OVERRUN_IRQ))
+                       data->error = -EIO;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
+       struct mxs_mmc_host *host, unsigned int append)
+{
+       struct dma_async_tx_descriptor *desc;
+       struct mmc_data *data = host->data;
+       struct scatterlist * sgl;
+       unsigned int sg_len;
+
+       if (data) {
+               /* data */
+               dma_map_sg(mmc_dev(host->mmc), data->sg,
+                          data->sg_len, host->dma_dir);
+               sgl = data->sg;
+               sg_len = data->sg_len;
+       } else {
+               /* pio */
+               sgl = (struct scatterlist *) host->ssp_pio_words;
+               sg_len = SSP_PIO_NUM;
+       }
+
+       desc = host->dmach->device->device_prep_slave_sg(host->dmach,
+                               sgl, sg_len, host->dma_dir, append);
+       if (desc) {
+               desc->callback = mxs_mmc_dma_irq_callback;
+               desc->callback_param = host;
+       } else {
+               if (data)
+                       dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+                                    data->sg_len, host->dma_dir);
+       }
+
+       return desc;
+}
+
+static void mxs_mmc_bc(struct mxs_mmc_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       struct dma_async_tx_descriptor *desc;
+       u32 ctrl0, cmd0, cmd1;
+
+       ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC;
+       cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC;
+       cmd1 = cmd->arg;
+
+       if (host->sdio_irq_en) {
+               ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+               cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+       }
+
+       host->ssp_pio_words[0] = ctrl0;
+       host->ssp_pio_words[1] = cmd0;
+       host->ssp_pio_words[2] = cmd1;
+       host->dma_dir = DMA_NONE;
+       desc = mxs_mmc_prep_dma(host, 0);
+       if (!desc)
+               goto out;
+
+       dmaengine_submit(desc);
+       return;
+
+out:
+       dev_warn(mmc_dev(host->mmc),
+                "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_ac(struct mxs_mmc_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       struct dma_async_tx_descriptor *desc;
+       u32 ignore_crc, get_resp, long_resp;
+       u32 ctrl0, cmd0, cmd1;
+
+       ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+                       0 : BM_SSP_CTRL0_IGNORE_CRC;
+       get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+                       BM_SSP_CTRL0_GET_RESP : 0;
+       long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+                       BM_SSP_CTRL0_LONG_RESP : 0;
+
+       ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
+       cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+       cmd1 = cmd->arg;
+
+       if (host->sdio_irq_en) {
+               ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+               cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+       }
+
+       host->ssp_pio_words[0] = ctrl0;
+       host->ssp_pio_words[1] = cmd0;
+       host->ssp_pio_words[2] = cmd1;
+       host->dma_dir = DMA_NONE;
+       desc = mxs_mmc_prep_dma(host, 0);
+       if (!desc)
+               goto out;
+
+       dmaengine_submit(desc);
+       return;
+
+out:
+       dev_warn(mmc_dev(host->mmc),
+                "%s: failed to prep dma\n", __func__);
+}
+
+static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns)
+{
+       const unsigned int ssp_timeout_mul = 4096;
+       /*
+        * Calculate ticks in ms since ns are large numbers
+        * and might overflow
+        */
+       const unsigned int clock_per_ms = clock_rate / 1000;
+       const unsigned int ms = ns / 1000;
+       const unsigned int ticks = ms * clock_per_ms;
+       const unsigned int ssp_ticks = ticks / ssp_timeout_mul;
+
+       WARN_ON(ssp_ticks == 0);
+       return ssp_ticks;
+}
+
+static void mxs_mmc_adtc(struct mxs_mmc_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       struct mmc_data *data = cmd->data;
+       struct dma_async_tx_descriptor *desc;
+       struct scatterlist *sgl = data->sg, *sg;
+       unsigned int sg_len = data->sg_len;
+       int i;
+
+       unsigned short dma_data_dir, timeout;
+       unsigned int data_size = 0, log2_blksz;
+       unsigned int blocks = data->blocks;
+
+       u32 ignore_crc, get_resp, long_resp, read;
+       u32 ctrl0, cmd0, cmd1, val;
+
+       ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+                       0 : BM_SSP_CTRL0_IGNORE_CRC;
+       get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+                       BM_SSP_CTRL0_GET_RESP : 0;
+       long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+                       BM_SSP_CTRL0_LONG_RESP : 0;
+
+       if (data->flags & MMC_DATA_WRITE) {
+               dma_data_dir = DMA_TO_DEVICE;
+               read = 0;
+       } else {
+               dma_data_dir = DMA_FROM_DEVICE;
+               read = BM_SSP_CTRL0_READ;
+       }
+
+       ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
+               ignore_crc | get_resp | long_resp |
+               BM_SSP_CTRL0_DATA_XFER | read |
+               BM_SSP_CTRL0_WAIT_FOR_IRQ |
+               BM_SSP_CTRL0_ENABLE;
+
+       cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+
+       /* get logarithm to base 2 of block size for setting register */
+       log2_blksz = ilog2(data->blksz);
+
+       /*
+        * take special care of the case that data size from data->sg
+        * is not equal to blocks x blksz
+        */
+       for_each_sg(sgl, sg, sg_len, i)
+               data_size += sg->length;
+
+       if (data_size != data->blocks * data->blksz)
+               blocks = 1;
+
+       /* xfer count, block size and count need to be set differently */
+       if (ssp_is_old()) {
+               ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
+               cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
+                       BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
+       } else {
+               writel(data_size, host->base + HW_SSP_XFER_SIZE);
+               writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
+                      BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
+                      host->base + HW_SSP_BLOCK_SIZE);
+       }
+
+       if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
+           (cmd->opcode == SD_IO_RW_EXTENDED))
+               cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
+       cmd1 = cmd->arg;
+
+       if (host->sdio_irq_en) {
+               ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+               cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+       }
+
+       /* set the timeout count */
+       timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
+       val = readl(host->base + HW_SSP_TIMING);
+       val &= ~(BM_SSP_TIMING_TIMEOUT);
+       val |= BF_SSP(timeout, TIMING_TIMEOUT);
+       writel(val, host->base + HW_SSP_TIMING);
+
+       /* pio */
+       host->ssp_pio_words[0] = ctrl0;
+       host->ssp_pio_words[1] = cmd0;
+       host->ssp_pio_words[2] = cmd1;
+       host->dma_dir = DMA_NONE;
+       desc = mxs_mmc_prep_dma(host, 0);
+       if (!desc)
+               goto out;
+
+       /* append data sg */
+       WARN_ON(host->data != NULL);
+       host->data = data;
+       host->dma_dir = dma_data_dir;
+       desc = mxs_mmc_prep_dma(host, 1);
+       if (!desc)
+               goto out;
+
+       dmaengine_submit(desc);
+       return;
+out:
+       dev_warn(mmc_dev(host->mmc),
+                "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+                             struct mmc_command *cmd)
+{
+       host->cmd = cmd;
+
+       switch (mmc_cmd_type(cmd)) {
+       case MMC_CMD_BC:
+               mxs_mmc_bc(host);
+               break;
+       case MMC_CMD_BCR:
+               mxs_mmc_ac(host);
+               break;
+       case MMC_CMD_AC:
+               mxs_mmc_ac(host);
+               break;
+       case MMC_CMD_ADTC:
+               mxs_mmc_adtc(host);
+               break;
+       default:
+               dev_warn(mmc_dev(host->mmc),
+                        "%s: unknown MMC command\n", __func__);
+               break;
+       }
+}
+
+static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+
+       WARN_ON(host->mrq != NULL);
+       host->mrq = mrq;
+       mxs_mmc_start_cmd(host, mrq->cmd);
+}
+
+static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
+{
+       unsigned int ssp_rate, bit_rate;
+       u32 div1, div2;
+       u32 val;
+
+       ssp_rate = clk_get_rate(host->clk);
+
+       for (div1 = 2; div1 < 254; div1 += 2) {
+               div2 = ssp_rate / rate / div1;
+               if (div2 < 0x100)
+                       break;
+       }
+
+       if (div1 >= 254) {
+               dev_err(mmc_dev(host->mmc),
+                       "%s: cannot set clock to %d\n", __func__, rate);
+               return;
+       }
+
+       if (div2 == 0)
+               bit_rate = ssp_rate / div1;
+       else
+               bit_rate = ssp_rate / div1 / div2;
+
+       val = readl(host->base + HW_SSP_TIMING);
+       val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+       val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
+       val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+       writel(val, host->base + HW_SSP_TIMING);
+
+       host->clk_rate = bit_rate;
+
+       dev_dbg(mmc_dev(host->mmc),
+               "%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
+               __func__, div1, div2, ssp_rate, bit_rate, rate);
+}
+
+static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+
+       if (ios->bus_width == MMC_BUS_WIDTH_8)
+               host->bus_width = 2;
+       else if (ios->bus_width == MMC_BUS_WIDTH_4)
+               host->bus_width = 1;
+       else
+               host->bus_width = 0;
+
+       if (ios->clock)
+               mxs_mmc_set_clk_rate(host, ios->clock);
+}
+
+static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       host->sdio_irq_en = enable;
+
+       if (enable) {
+               writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+                      host->base + HW_SSP_CTRL0 + MXS_SET_ADDR);
+               writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+                      host->base + HW_SSP_CTRL1 + MXS_SET_ADDR);
+
+               if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
+                       mmc_signal_sdio_irq(host->mmc);
+
+       } else {
+               writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+                      host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR);
+               writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+                      host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+       }
+
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops mxs_mmc_ops = {
+       .request = mxs_mmc_request,
+       .get_ro = mxs_mmc_get_ro,
+       .get_cd = mxs_mmc_get_cd,
+       .set_ios = mxs_mmc_set_ios,
+       .enable_sdio_irq = mxs_mmc_enable_sdio_irq,
+};
+
+static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct mxs_mmc_host *host = param;
+
+       if (!mxs_dma_is_apbh(chan))
+               return false;
+
+       if (chan->chan_id != host->dma_res->start)
+               return false;
+
+       chan->private = &host->dma_data;
+
+       return true;
+}
+
+static int mxs_mmc_probe(struct platform_device *pdev)
+{
+       struct mxs_mmc_host *host;
+       struct mmc_host *mmc;
+       struct resource *iores, *dmares, *r;
+       struct mxs_mmc_platform_data *pdata;
+       int ret = 0, irq_err, irq_dma;
+       dma_cap_mask_t mask;
+
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       irq_err = platform_get_irq(pdev, 0);
+       irq_dma = platform_get_irq(pdev, 1);
+       if (!iores || !dmares || irq_err < 0 || irq_dma < 0)
+               return -EINVAL;
+
+       r = request_mem_region(iores->start, resource_size(iores), pdev->name);
+       if (!r)
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out_release_mem;
+       }
+
+       host = mmc_priv(mmc);
+       host->base = ioremap(r->start, resource_size(r));
+       if (!host->base) {
+               ret = -ENOMEM;
+               goto out_mmc_free;
+       }
+
+       /* only major verion does matter */
+       host->version = readl(host->base + HW_SSP_VERSION) >>
+                       BP_SSP_VERSION_MAJOR;
+
+       host->mmc = mmc;
+       host->res = r;
+       host->dma_res = dmares;
+       host->irq = irq_err;
+       host->sdio_irq_en = 0;
+
+       host->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(host->clk)) {
+               ret = PTR_ERR(host->clk);
+               goto out_iounmap;
+       }
+       clk_enable(host->clk);
+
+       mxs_mmc_reset(host);
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       host->dma_data.chan_irq = irq_dma;
+       host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+       if (!host->dmach) {
+               dev_err(mmc_dev(host->mmc),
+                       "%s: failed to request dma\n", __func__);
+               goto out_clk_put;
+       }
+
+       /* set mmc core parameters */
+       mmc->ops = &mxs_mmc_ops;
+       mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
+                   MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
+
+       pdata = mmc_dev(host->mmc)->platform_data;
+       if (pdata) {
+               if (pdata->flags & SLOTF_8_BIT_CAPABLE)
+                       mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+               if (pdata->flags & SLOTF_4_BIT_CAPABLE)
+                       mmc->caps |= MMC_CAP_4_BIT_DATA;
+       }
+
+       mmc->f_min = 400000;
+       mmc->f_max = 288000000;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+       mmc->max_segs = 52;
+       mmc->max_blk_size = 1 << 0xf;
+       mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff;
+       mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff;
+       mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+
+       platform_set_drvdata(pdev, mmc);
+
+       ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host);
+       if (ret)
+               goto out_free_dma;
+
+       spin_lock_init(&host->lock);
+
+       ret = mmc_add_host(mmc);
+       if (ret)
+               goto out_free_irq;
+
+       dev_info(mmc_dev(host->mmc), "initialized\n");
+
+       return 0;
+
+out_free_irq:
+       free_irq(host->irq, host);
+out_free_dma:
+       if (host->dmach)
+               dma_release_channel(host->dmach);
+out_clk_put:
+       clk_disable(host->clk);
+       clk_put(host->clk);
+out_iounmap:
+       iounmap(host->base);
+out_mmc_free:
+       mmc_free_host(mmc);
+out_release_mem:
+       release_mem_region(iores->start, resource_size(iores));
+       return ret;
+}
+
+static int mxs_mmc_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct resource *res = host->res;
+
+       mmc_remove_host(mmc);
+
+       free_irq(host->irq, host);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (host->dmach)
+               dma_release_channel(host->dmach);
+
+       clk_disable(host->clk);
+       clk_put(host->clk);
+
+       iounmap(host->base);
+
+       mmc_free_host(mmc);
+
+       release_mem_region(res->start, resource_size(res));
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxs_mmc_suspend(struct device *dev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+       int ret = 0;
+
+       ret = mmc_suspend_host(mmc);
+
+       clk_disable(host->clk);
+
+       return ret;
+}
+
+static int mxs_mmc_resume(struct device *dev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       struct mxs_mmc_host *host = mmc_priv(mmc);
+       int ret = 0;
+
+       clk_enable(host->clk);
+
+       ret = mmc_resume_host(mmc);
+
+       return ret;
+}
+
+static const struct dev_pm_ops mxs_mmc_pm_ops = {
+       .suspend        = mxs_mmc_suspend,
+       .resume         = mxs_mmc_resume,
+};
+#endif
+
+static struct platform_driver mxs_mmc_driver = {
+       .probe          = mxs_mmc_probe,
+       .remove         = mxs_mmc_remove,
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &mxs_mmc_pm_ops,
+#endif
+       },
+};
+
+static int __init mxs_mmc_init(void)
+{
+       return platform_driver_register(&mxs_mmc_driver);
+}
+
+static void __exit mxs_mmc_exit(void)
+{
+       platform_driver_unregister(&mxs_mmc_driver);
+}
+
+module_init(mxs_mmc_init);
+module_exit(mxs_mmc_exit);
+
+MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
index 9b82910b9dbb3ec01ab07a0ff2f19f6ec59a9ed7..3b5248567973dc794d2cf1c8232317d118f1727a 100644 (file)
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-pltfm.h>
 #include <mach/hardware.h>
+#include <mach/esdhc.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -30,6 +32,39 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
        writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
 }
 
+static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+{
+       /* fake CARD_PRESENT flag on mx25/35 */
+       u32 val = readl(host->ioaddr + reg);
+
+       if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+               struct esdhc_platform_data *boarddata =
+                               host->mmc->parent->platform_data;
+
+               if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+                               && gpio_get_value(boarddata->cd_gpio))
+                       /* no card, if a valid gpio says so... */
+                       val &= SDHCI_CARD_PRESENT;
+               else
+                       /* ... in all other cases assume card is present */
+                       val |= SDHCI_CARD_PRESENT;
+       }
+
+       return val;
+}
+
+static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
+{
+       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE))
+               /*
+                * 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);
+
+       writel(val, host->ioaddr + reg);
+}
+
 static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 {
        if (unlikely(reg == SDHCI_HOST_VERSION))
@@ -100,10 +135,39 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
        return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+       struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+       if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+               return gpio_get_value(boarddata->wp_gpio);
+       else
+               return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+       .read_w = esdhc_readw_le,
+       .write_w = esdhc_writew_le,
+       .write_b = esdhc_writeb_le,
+       .set_clock = esdhc_set_clock,
+       .get_max_clock = esdhc_pltfm_get_max_clock,
+       .get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
+static irqreturn_t cd_irq(int irq, void *data)
+{
+       struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+       tasklet_schedule(&sdhost->card_tasklet);
+       return IRQ_HANDLED;
+};
+
 static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
        struct clk *clk;
+       int err;
 
        clk = clk_get(mmc_dev(host->mmc), NULL);
        if (IS_ERR(clk)) {
@@ -116,32 +180,78 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
        if (cpu_is_mx35() || cpu_is_mx51())
                host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-       /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
-       if (cpu_is_mx25() || cpu_is_mx35())
+       if (cpu_is_mx25() || cpu_is_mx35()) {
+               /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
                host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+               /* write_protect can't be routed to controller, use gpio */
+               sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+       }
+
+       if (boarddata) {
+               err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+               if (err) {
+                       dev_warn(mmc_dev(host->mmc),
+                               "no write-protect pin available!\n");
+                       boarddata->wp_gpio = err;
+               }
+
+               err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+               if (err) {
+                       dev_warn(mmc_dev(host->mmc),
+                               "no card-detect pin available!\n");
+                       goto no_card_detect_pin;
+               }
+
+               /* i.MX5x has issues to be researched */
+               if (!cpu_is_mx25() && !cpu_is_mx35())
+                       goto not_supported;
+
+               err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+                                IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+                                mmc_hostname(host->mmc), host);
+               if (err) {
+                       dev_warn(mmc_dev(host->mmc), "request irq error\n");
+                       goto no_card_detect_irq;
+               }
+
+               sdhci_esdhc_ops.write_l = esdhc_writel_le;
+               sdhci_esdhc_ops.read_l = esdhc_readl_le;
+               /* Now we have a working card_detect again */
+               host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+       }
+
+       return 0;
 
+ no_card_detect_irq:
+       gpio_free(boarddata->cd_gpio);
+ no_card_detect_pin:
+       boarddata->cd_gpio = err;
+ not_supported:
        return 0;
 }
 
 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;
+
+       if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+               gpio_free(boarddata->wp_gpio);
+
+       if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+               gpio_free(boarddata->cd_gpio);
+
+               if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+                       free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+       }
 
        clk_disable(pltfm_host->clk);
        clk_put(pltfm_host->clk);
 }
 
-static struct sdhci_ops sdhci_esdhc_ops = {
-       .read_w = esdhc_readw_le,
-       .write_w = esdhc_writew_le,
-       .write_b = esdhc_writeb_le,
-       .set_clock = esdhc_set_clock,
-       .get_max_clock = esdhc_pltfm_get_max_clock,
-       .get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
 struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
+       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+                       | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
        /* ADMA has issues. Might be fixable */
        .ops = &sdhci_esdhc_ops,
        .init = esdhc_pltfm_init,
index afaf1bc4913a3930794a9cae674d79b9da1f88f3..c55aae828aac1eb450657da0dac9eafdfd427d4e 100644 (file)
@@ -19,7 +19,6 @@
  */
 
 #define ESDHC_DEFAULT_QUIRKS   (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
-                               SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
                                SDHCI_QUIRK_NO_BUSY_IRQ | \
                                SDHCI_QUIRK_NONSTANDARD_CLOCK | \
                                SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
index fcd0e1fcba44635b450409318b10c30562fc8a42..08161f690ae872320c9799e48774bc5b714eea2a 100644 (file)
@@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
 }
 
 struct sdhci_of_data sdhci_esdhc = {
-       .quirks = ESDHC_DEFAULT_QUIRKS,
+       /* card detection could be handled via GPIO */
+       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
        .ops = {
                .read_l = sdhci_be32bs_readl,
                .read_w = esdhc_readw,
index 0dc905b20eee122543b9365cdecdfe1185307730..2f8d46854acd0fb5430ec22ac15ed439ec3b8710 100644 (file)
@@ -546,6 +546,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .driver_data    = (kernel_ulong_t)&sdhci_ricoh_mmc,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_RICOH,
+               .device         = 0xe823,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_ricoh_mmc,
+       },
+
        {
                .vendor         = PCI_VENDOR_ID_ENE,
                .device         = PCI_DEVICE_ID_ENE_CB712_SD,
@@ -900,9 +908,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
 {
        struct sdhci_pci_slot *slot;
        struct sdhci_host *host;
-
-       resource_size_t addr;
-
        int ret;
 
        if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
@@ -949,7 +954,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
                goto free;
        }
 
-       addr = pci_resource_start(pdev, bar);
        host->ioaddr = pci_ioremap_bar(pdev, bar);
        if (!host->ioaddr) {
                dev_err(&pdev->dev, "failed to remap registers\n");
index 5309ab95aada9a39914300833b1be38f4ec07ad9..69e3ee321eb59ad593290706e091d359e5912db6 100644 (file)
@@ -499,6 +499,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
         * SDHCI block, or a missing configuration that needs to be set. */
        host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
 
+       /* This host supports the Auto CMD12 */
+       host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
        if (pdata->cd_type == S3C_SDHCI_CD_NONE ||
            pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
                host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
index 4823ee94a63fe2f363eb4b40ce4cbf7656cbad81..f7e1f964395fd5bb46264e98c0e474046204293b 100644 (file)
@@ -169,7 +169,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
                if (rc) {
                        dev_err(mmc_dev(host->mmc),
                                "failed to allocate wp gpio\n");
-                       goto out_cd;
+                       goto out_irq;
                }
                tegra_gpio_enable(plat->wp_gpio);
                gpio_direction_input(plat->wp_gpio);
@@ -195,6 +195,9 @@ out_wp:
                gpio_free(plat->wp_gpio);
        }
 
+out_irq:
+       if (gpio_is_valid(plat->cd_gpio))
+               free_irq(gpio_to_irq(plat->cd_gpio), host);
 out_cd:
        if (gpio_is_valid(plat->cd_gpio)) {
                tegra_gpio_disable(plat->cd_gpio);
@@ -225,6 +228,7 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
        }
 
        if (gpio_is_valid(plat->cd_gpio)) {
+               free_irq(gpio_to_irq(plat->cd_gpio), host);
                tegra_gpio_disable(plat->cd_gpio);
                gpio_free(plat->cd_gpio);
        }
index 12884c270171d2e81e5a87c2854e0005cdf085cb..af97015a2fc7f57b216992a2032869f40cbf5e59 100644 (file)
@@ -169,7 +169,7 @@ struct sh_mmcif_host {
        struct dma_chan         *chan_rx;
        struct dma_chan         *chan_tx;
        struct completion       dma_complete;
-       unsigned int            dma_sglen;
+       bool                    dma_active;
 };
 
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
@@ -194,10 +194,12 @@ static void mmcif_dma_complete(void *arg)
                return;
 
        if (host->data->flags & MMC_DATA_READ)
-               dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+               dma_unmap_sg(host->chan_rx->device->dev,
+                            host->data->sg, host->data->sg_len,
                             DMA_FROM_DEVICE);
        else
-               dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+               dma_unmap_sg(host->chan_tx->device->dev,
+                            host->data->sg, host->data->sg_len,
                             DMA_TO_DEVICE);
 
        complete(&host->dma_complete);
@@ -211,9 +213,10 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
        dma_cookie_t cookie = -EINVAL;
        int ret;
 
-       ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE);
+       ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+                        DMA_FROM_DEVICE);
        if (ret > 0) {
-               host->dma_sglen = ret;
+               host->dma_active = true;
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
                        DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
@@ -221,14 +224,9 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
        if (desc) {
                desc->callback = mmcif_dma_complete;
                desc->callback_param = host;
-               cookie = desc->tx_submit(desc);
-               if (cookie < 0) {
-                       desc = NULL;
-                       ret = cookie;
-               } else {
-                       sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
-                       chan->device->device_issue_pending(chan);
-               }
+               cookie = dmaengine_submit(desc);
+               sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
+               dma_async_issue_pending(chan);
        }
        dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
                __func__, host->data->sg_len, ret, cookie);
@@ -238,7 +236,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
                if (ret >= 0)
                        ret = -EIO;
                host->chan_rx = NULL;
-               host->dma_sglen = 0;
+               host->dma_active = false;
                dma_release_channel(chan);
                /* Free the Tx channel too */
                chan = host->chan_tx;
@@ -263,9 +261,10 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
        dma_cookie_t cookie = -EINVAL;
        int ret;
 
-       ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE);
+       ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+                        DMA_TO_DEVICE);
        if (ret > 0) {
-               host->dma_sglen = ret;
+               host->dma_active = true;
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
                        DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
@@ -273,14 +272,9 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
        if (desc) {
                desc->callback = mmcif_dma_complete;
                desc->callback_param = host;
-               cookie = desc->tx_submit(desc);
-               if (cookie < 0) {
-                       desc = NULL;
-                       ret = cookie;
-               } else {
-                       sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
-                       chan->device->device_issue_pending(chan);
-               }
+               cookie = dmaengine_submit(desc);
+               sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
+               dma_async_issue_pending(chan);
        }
        dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
                __func__, host->data->sg_len, ret, cookie);
@@ -290,7 +284,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
                if (ret >= 0)
                        ret = -EIO;
                host->chan_tx = NULL;
-               host->dma_sglen = 0;
+               host->dma_active = false;
                dma_release_channel(chan);
                /* Free the Rx channel too */
                chan = host->chan_rx;
@@ -317,7 +311,7 @@ static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
                                 struct sh_mmcif_plat_data *pdata)
 {
-       host->dma_sglen = 0;
+       host->dma_active = false;
 
        /* We can only either use DMA for both Tx and Rx or not use it at all */
        if (pdata->dma) {
@@ -364,7 +358,7 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
                dma_release_channel(chan);
        }
 
-       host->dma_sglen = 0;
+       host->dma_active = false;
 }
 
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
@@ -753,7 +747,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
        }
        sh_mmcif_get_response(host, cmd);
        if (host->data) {
-               if (!host->dma_sglen) {
+               if (!host->dma_active) {
                        ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
                } else {
                        long time =
@@ -765,7 +759,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
                                ret = time;
                        sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
                                        BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
-                       host->dma_sglen = 0;
+                       host->dma_active = false;
                }
                if (ret < 0)
                        mrq->data->bytes_xfered = 0;
@@ -850,15 +844,15 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        struct sh_mmcif_host *host = mmc_priv(mmc);
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
 
-       if (ios->power_mode == MMC_POWER_OFF) {
+       if (ios->power_mode == MMC_POWER_UP) {
+               if (p->set_pwr)
+                       p->set_pwr(host->pd, ios->power_mode);
+       } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
                /* clock stop */
                sh_mmcif_clock_control(host, 0);
-               if (p->down_pwr)
+               if (ios->power_mode == MMC_POWER_OFF && p->down_pwr)
                        p->down_pwr(host->pd);
                return;
-       } else if (ios->power_mode == MMC_POWER_UP) {
-               if (p->set_pwr)
-                       p->set_pwr(host->pd, ios->power_mode);
        }
 
        if (ios->clock)
index e3c6ef20839193462150eadb2cfea55b0234a7d3..ac52eb65395efb35055b39c771a9eeefe9d354ab 100644 (file)
@@ -152,7 +152,6 @@ struct tmio_mmc_host {
        struct tasklet_struct   dma_complete;
        struct tasklet_struct   dma_issue;
 #ifdef CONFIG_TMIO_MMC_DMA
-       unsigned int            dma_sglen;
        u8                      bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN)));
        struct scatterlist      bounce_sg;
 #endif
@@ -220,44 +219,48 @@ static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
        return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
 }
 
-static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags)
+static void tmio_mmc_kunmap_atomic(struct scatterlist *sg, unsigned long *flags, void *virt)
 {
-       kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+       kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
        local_irq_restore(*flags);
 }
 
 #ifdef CONFIG_MMC_DEBUG
 
-#define STATUS_TO_TEXT(a) \
+#define STATUS_TO_TEXT(a, status, i) \
        do { \
-               if (status & TMIO_STAT_##a) \
+               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_TO_TEXT(CARD_INSERT);
-       STATUS_TO_TEXT(SIGSTATE);
-       STATUS_TO_TEXT(WRPROTECT);
-       STATUS_TO_TEXT(CARD_REMOVE_A);
-       STATUS_TO_TEXT(CARD_INSERT_A);
-       STATUS_TO_TEXT(SIGSTATE_A);
-       STATUS_TO_TEXT(CMD_IDX_ERR);
-       STATUS_TO_TEXT(STOPBIT_ERR);
-       STATUS_TO_TEXT(ILL_FUNC);
-       STATUS_TO_TEXT(CMD_BUSY);
-       STATUS_TO_TEXT(CMDRESPEND);
-       STATUS_TO_TEXT(DATAEND);
-       STATUS_TO_TEXT(CRCFAIL);
-       STATUS_TO_TEXT(DATATIMEOUT);
-       STATUS_TO_TEXT(CMDTIMEOUT);
-       STATUS_TO_TEXT(RXOVERFLOW);
-       STATUS_TO_TEXT(TXUNDERRUN);
-       STATUS_TO_TEXT(RXRDY);
-       STATUS_TO_TEXT(TXRQ);
-       STATUS_TO_TEXT(ILL_ACCESS);
+       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");
 }
 
@@ -507,7 +510,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 
        host->sg_off += count;
 
-       tmio_mmc_kunmap_atomic(sg_virt, &flags);
+       tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt);
 
        if (host->sg_off == host->sg_ptr->length)
                tmio_mmc_next_sg(host);
@@ -767,7 +770,7 @@ static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
                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(sg_vaddr, &flags);
+               tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr);
        }
 }
 
@@ -825,23 +828,16 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
                sg = host->sg_ptr;
        }
 
-       ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE);
-       if (ret > 0) {
-               host->dma_sglen = ret;
+       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 = desc->tx_submit(desc);
-               if (cookie < 0) {
-                       desc = NULL;
-                       ret = cookie;
-               } else {
-                       chan->device->device_issue_pending(chan);
-               }
+               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);
@@ -901,26 +897,20 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
                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_vaddr, &flags);
+               tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr);
                host->sg_ptr = &host->bounce_sg;
                sg = host->sg_ptr;
        }
 
-       ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE);
-       if (ret > 0) {
-               host->dma_sglen = ret;
+       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 = desc->tx_submit(desc);
-               if (cookie < 0) {
-                       desc = NULL;
-                       ret = cookie;
-               }
+               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);
@@ -964,7 +954,7 @@ 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;
 
-       chan->device->device_issue_pending(chan);
+       dma_async_issue_pending(chan);
 }
 
 static void tmio_tasklet_fn(unsigned long arg)
@@ -978,10 +968,12 @@ static void tmio_tasklet_fn(unsigned long arg)
                goto out;
 
        if (host->data->flags & MMC_DATA_READ)
-               dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
+               dma_unmap_sg(host->chan_rx->device->dev,
+                            host->sg_ptr, host->sg_len,
                             DMA_FROM_DEVICE);
        else
-               dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
+               dma_unmap_sg(host->chan_tx->device->dev,
+                            host->sg_ptr, host->sg_len,
                             DMA_TO_DEVICE);
 
        tmio_mmc_do_data_irq(host);
index 9ed84ddb478060358cce983c0996b6268b1edd93..8c5b4881ccd6068fc766fd6e0ae77dbbe2669664 100644 (file)
@@ -802,12 +802,9 @@ static const struct mmc_host_ops via_sdc_ops = {
 
 static void via_reset_pcictrl(struct via_crdr_mmc_host *host)
 {
-       void __iomem *addrbase;
        unsigned long flags;
        u8 gatt;
 
-       addrbase = host->pcictrl_mmiobase;
-
        spin_lock_irqsave(&host->lock, flags);
 
        via_save_pcictrlreg(host);
index b38d987da67d9c810d069ec9303313aa2978243d..9560b9d624bd56b1bef99b972b3f2d7931819977 100644 (file)
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CAIF_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG
 
 # Serial interface
 obj-$(CONFIG_CAIF_TTY) += caif_serial.o
index cb23580fcffa5894d1f10db8dce271575c7a1781..b0be0234abf6a3bc8a1060434a2b5c6af88112f5 100644 (file)
@@ -17,4 +17,4 @@ skfp-objs :=  skfddi.o    hwmtm.o    fplustm.o  smt.o      cfm.o     \
 #   projects. To keep the source common for all those drivers (and
 #   thus simplify fixes to it), please do not clean it up!
 
-EXTRA_CFLAGS += -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes 
+ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
index dabdcfed4efd1fc8b96d02635fa0ea40f19037fb..609710d64eb5c196a506a33ae2d832aa1cb5d7bb 100644 (file)
@@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
 # -DDEBUG \
 # -DLMC_PACKET_LOG
 
-EXTRA_CFLAGS += -I. $(DBGDEF)
+ccflags-y := -I. $(DBGDEF)
index 30acd39d76a2892de5a684b9b716201c74b9da1f..2c8f71f0ed456e5718e322350339ff8b55556d0a 100644 (file)
@@ -30,9 +30,9 @@
 
 /* Following defines can be used to remove unneeded parts of the driver, e.g.,
  * to limit the size of the kernel module. Definitions can be added here in
- * hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
+ * hostap_config.h or they can be added to make command with ccflags-y,
  * e.g.,
- * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
+ * 'make pccard ccflags-y="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
  */
 
 /* Do not include debug messages into the driver */
index 1907eafb9b16b72aea2502869b420dbe87dbe8b5..5728a918e508ba9bf9636ac98f615b25fcd48c28 100644 (file)
@@ -5,7 +5,5 @@ zd1211rw-objs := zd_chip.o zd_mac.o \
                zd_rf_al7230b.o zd_rf_uw2453.o \
                zd_rf.o zd_usb.o
 
-ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG
 
index 9383063d2b16896bfcc740855221c5eccfbf0570..bcd5d54b7d4d2b3cfc938acf6141cc65bb4ec8ec 100644 (file)
@@ -296,25 +296,25 @@ static struct pci_port_ops dino_port_ops = {
        .outl   = dino_out32
 };
 
-static void dino_mask_irq(unsigned int irq)
+static void dino_mask_irq(struct irq_data *d)
 {
-       struct dino_device *dino_dev = get_irq_chip_data(irq);
-       int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+       struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+       int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
-       DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+       DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
        /* Clear the matching bit in the IMR register */
        dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
        __raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
 }
 
-static void dino_unmask_irq(unsigned int irq)
+static void dino_unmask_irq(struct irq_data *d)
 {
-       struct dino_device *dino_dev = get_irq_chip_data(irq);
-       int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+       struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+       int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
        u32 tmp;
 
-       DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+       DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
        /*
        ** clear pending IRQ bits
@@ -346,9 +346,9 @@ static void dino_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip dino_interrupt_type = {
-       .name   = "GSC-PCI",
-       .unmask = dino_unmask_irq,
-       .mask   = dino_mask_irq,
+       .name           = "GSC-PCI",
+       .irq_unmask     = dino_unmask_irq,
+       .irq_mask       = dino_mask_irq,
 };
 
 
index e860038b0b841952f29021a5fa752f6d9ee4ea3e..deeec32a5803c30834469819102f7efac98342ed 100644 (file)
@@ -144,8 +144,9 @@ static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered *
 
 
 /* called by free irq */
-static void eisa_mask_irq(unsigned int irq)
+static void eisa_mask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        unsigned long flags;
 
        EISA_DBG("disable irq %d\n", irq);
@@ -164,8 +165,9 @@ static void eisa_mask_irq(unsigned int irq)
 }
 
 /* called by request irq */
-static void eisa_unmask_irq(unsigned int irq)
+static void eisa_unmask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        unsigned long flags;
        EISA_DBG("enable irq %d\n", irq);
                
@@ -183,9 +185,9 @@ static void eisa_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip eisa_interrupt_type = {
-       .name   =       "EISA",
-       .unmask =       eisa_unmask_irq,
-       .mask   =       eisa_mask_irq,
+       .name           =       "EISA",
+       .irq_unmask     =       eisa_unmask_irq,
+       .irq_mask       =       eisa_mask_irq,
 };
 
 static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
index 772b1939ac218a2b9fc936ce57bc567761f050fc..ef31080cf5912323d31284fd3ddb2b0036158aea 100644 (file)
@@ -105,13 +105,13 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit)
        return NO_IRQ;
 }
 
-static void gsc_asic_mask_irq(unsigned int irq)
+static void gsc_asic_mask_irq(struct irq_data *d)
 {
-       struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-       int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+       struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+       int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
        u32 imr;
 
-       DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+       DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
                        irq_dev->name, imr);
 
        /* Disable the IRQ line by clearing the bit in the IMR */
@@ -120,13 +120,13 @@ static void gsc_asic_mask_irq(unsigned int irq)
        gsc_writel(imr, irq_dev->hpa + OFFSET_IMR);
 }
 
-static void gsc_asic_unmask_irq(unsigned int irq)
+static void gsc_asic_unmask_irq(struct irq_data *d)
 {
-       struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-       int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+       struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+       int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
        u32 imr;
 
-       DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+       DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
                        irq_dev->name, imr);
 
        /* Enable the IRQ line by setting the bit in the IMR */
@@ -140,9 +140,9 @@ static void gsc_asic_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip gsc_asic_interrupt_type = {
-       .name   =       "GSC-ASIC",
-       .unmask =       gsc_asic_unmask_irq,
-       .mask   =       gsc_asic_mask_irq,
+       .name           =       "GSC-ASIC",
+       .irq_unmask     =       gsc_asic_unmask_irq,
+       .irq_mask       =       gsc_asic_mask_irq,
 };
 
 int gsc_assign_irq(struct irq_chip *type, void *data)
index 0327894bf2355c23d3e2b3daae80c8a2cadf7aeb..95930d016235ae3a39fdfe71e1b409291d21d370 100644 (file)
@@ -615,10 +615,10 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
 }
 
 
-static void iosapic_mask_irq(unsigned int irq)
+static void iosapic_mask_irq(struct irq_data *d)
 {
        unsigned long flags;
-       struct vector_info *vi = get_irq_chip_data(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
        u32 d0, d1;
 
        spin_lock_irqsave(&iosapic_lock, flags);
@@ -628,9 +628,9 @@ static void iosapic_mask_irq(unsigned int irq)
        spin_unlock_irqrestore(&iosapic_lock, flags);
 }
 
-static void iosapic_unmask_irq(unsigned int irq)
+static void iosapic_unmask_irq(struct irq_data *d)
 {
-       struct vector_info *vi = get_irq_chip_data(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
        u32 d0, d1;
 
        /* data is initialized by fixup_irq */
@@ -666,34 +666,34 @@ printk("\n");
         * enables their IRQ. It can lead to "interesting" race conditions
         * in the driver initialization sequence.
         */
-       DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
+       DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
                        vi->eoi_addr, vi->eoi_data);
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
 }
 
-static void iosapic_eoi_irq(unsigned int irq)
+static void iosapic_eoi_irq(struct irq_data *d)
 {
-       struct vector_info *vi = get_irq_chip_data(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
 
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
-       cpu_eoi_irq(irq);
+       cpu_eoi_irq(d);
 }
 
 #ifdef CONFIG_SMP
-static int iosapic_set_affinity_irq(unsigned int irq,
-                                    const struct cpumask *dest)
+static int iosapic_set_affinity_irq(struct irq_data *d,
+                                   const struct cpumask *dest, bool force)
 {
-       struct vector_info *vi = get_irq_chip_data(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
        u32 d0, d1, dummy_d0;
        unsigned long flags;
        int dest_cpu;
 
-       dest_cpu = cpu_check_affinity(irq, dest);
+       dest_cpu = cpu_check_affinity(d, dest);
        if (dest_cpu < 0)
                return -1;
 
-       cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
-       vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
+       cpumask_copy(d->affinity, cpumask_of(dest_cpu));
+       vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
 
        spin_lock_irqsave(&iosapic_lock, flags);
        /* d1 contains the destination CPU, so only want to set that
@@ -708,13 +708,13 @@ static int iosapic_set_affinity_irq(unsigned int irq,
 #endif
 
 static struct irq_chip iosapic_interrupt_type = {
-       .name   =       "IO-SAPIC-level",
-       .unmask =       iosapic_unmask_irq,
-       .mask   =       iosapic_mask_irq,
-       .ack    =       cpu_ack_irq,
-       .eoi    =       iosapic_eoi_irq,
+       .name           =       "IO-SAPIC-level",
+       .irq_unmask     =       iosapic_unmask_irq,
+       .irq_mask       =       iosapic_mask_irq,
+       .irq_ack        =       cpu_ack_irq,
+       .irq_eoi        =       iosapic_eoi_irq,
 #ifdef CONFIG_SMP
-       .set_affinity = iosapic_set_affinity_irq,
+       .irq_set_affinity =     iosapic_set_affinity_irq,
 #endif
 };
 
index 28241532c0fd1b56c7f6bfa50d788c5fef1e9e3a..a4d8ff66a63901833ec06a6eb69830d6246d0d8e 100644 (file)
@@ -286,8 +286,9 @@ superio_init(struct pci_dev *pcidev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
 
-static void superio_mask_irq(unsigned int irq)
+static void superio_mask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        u8 r8;
 
        if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -303,8 +304,9 @@ static void superio_mask_irq(unsigned int irq)
        outb (r8,IC_PIC1+1);
 }
 
-static void superio_unmask_irq(unsigned int irq)
+static void superio_unmask_irq(struct irq_data *d)
 {
+       unsigned int irq = d->irq;
        u8 r8;
 
        if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -320,9 +322,9 @@ static void superio_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip superio_interrupt_type = {
-       .name   =       SUPERIO,
-       .unmask =       superio_unmask_irq,
-       .mask   =       superio_mask_irq,
+       .name           =       SUPERIO,
+       .irq_unmask     =       superio_unmask_irq,
+       .irq_mask       =       superio_mask_irq,
 };
 
 #ifdef DEBUG_SUPERIO_INIT
index a59af5b24f0ac9d9f0e4ea7c88cc2ad00ddddbb0..222dfb737b11a699d559c12c23e26a7577ab99de 100644 (file)
@@ -138,6 +138,24 @@ config TC1100_WMI
          This is a driver for the WMI extensions (wireless and bluetooth power
          control) of the HP Compaq TC1100 tablet.
 
+config HP_ACCEL
+       tristate "HP laptop accelerometer"
+       depends on INPUT && ACPI
+       select SENSORS_LIS3LV02D
+       select NEW_LEDS
+       select LEDS_CLASS
+       help
+         This driver provides support for the "Mobile Data Protection System 3D"
+         or "3D DriveGuard" feature of HP laptops. On such systems the driver
+         should load automatically (via ACPI alias).
+
+         Support for a led indicating disk protection will be provided as
+         hp::hddprotect. For more information on the feature, refer to
+         Documentation/hwmon/lis3lv02d.
+
+         To compile this driver as a module, choose M here: the module will
+         be called hp_accel.
+
 config HP_WMI
        tristate "HP WMI extras"
        depends on ACPI_WMI
index 4ec4ff8f918240e657153d7bdd0a11202ba8d498..299aefb3e74ce222b0a146703b601fe73b1f933d 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_DELL_LAPTOP)     += dell-laptop.o
 obj-$(CONFIG_DELL_WMI)         += dell-wmi.o
 obj-$(CONFIG_ACER_WMI)         += acer-wmi.o
 obj-$(CONFIG_ACERHDF)          += acerhdf.o
+obj-$(CONFIG_HP_ACCEL)         += hp_accel.o
 obj-$(CONFIG_HP_WMI)           += hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)       += tc1100-wmi.o
 obj-$(CONFIG_SONY_LAPTOP)      += sony-laptop.o
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
new file mode 100644 (file)
index 0000000..1b52d00
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  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/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/leds.h>
+#include <linux/atomic.h>
+#include <acpi/acpi_drivers.h>
+#include "../../misc/lis3lv02d/lis3lv02d.h"
+
+#define DRIVER_NAME     "hp_accel"
+#define ACPI_MDPS_CLASS "accelerometer"
+
+/* Delayed LEDs infrastructure ------------------------------------ */
+
+/* Special LED class that can defer work */
+struct delayed_led_classdev {
+       struct led_classdev led_classdev;
+       struct work_struct work;
+       enum led_brightness new_brightness;
+
+       unsigned int led;               /* For driver */
+       void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
+};
+
+static inline void delayed_set_status_worker(struct work_struct *work)
+{
+       struct delayed_led_classdev *data =
+                       container_of(work, struct delayed_led_classdev, work);
+
+       data->set_brightness(data, data->new_brightness);
+}
+
+static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
+                             enum led_brightness brightness)
+{
+       struct delayed_led_classdev *data = container_of(led_cdev,
+                            struct delayed_led_classdev, led_classdev);
+       data->new_brightness = brightness;
+       schedule_work(&data->work);
+}
+
+/* HP-specific accelerometer driver ------------------------------------ */
+
+/* For automatic insertion of the module */
+static struct acpi_device_id lis3lv02d_device_ids[] = {
+       {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
+
+
+/**
+ * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * @lis3: pointer to the device struct
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
+{
+       struct acpi_device *dev = lis3->bus_priv;
+       if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
+                                NULL, NULL) != AE_OK)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * lis3lv02d_acpi_read - ACPI ALRD method: read a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to read
+ * @ret:    result of the operation
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
+{
+       struct acpi_device *dev = lis3->bus_priv;
+       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+       struct acpi_object_list args = { 1, &arg0 };
+       unsigned long long lret;
+       acpi_status status;
+
+       arg0.integer.value = reg;
+
+       status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
+       *ret = lret;
+       return (status != AE_OK) ? -EINVAL : 0;
+}
+
+/**
+ * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to write to
+ * @val:    the value to write
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+       struct acpi_device *dev = lis3->bus_priv;
+       unsigned long long ret; /* Not used when writting */
+       union acpi_object in_obj[2];
+       struct acpi_object_list args = { 2, in_obj };
+
+       in_obj[0].type          = ACPI_TYPE_INTEGER;
+       in_obj[0].integer.value = reg;
+       in_obj[1].type          = ACPI_TYPE_INTEGER;
+       in_obj[1].integer.value = val;
+
+       if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
+{
+       lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
+       pr_info("hardware type %s found\n", dmi->ident);
+
+       return 1;
+}
+
+/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
+ * If the value is negative, the opposite of the hw value is used. */
+#define DEFINE_CONV(name, x, y, z)                           \
+       static union axis_conversion lis3lv02d_axis_##name = \
+               { .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
+
+#define AXIS_DMI_MATCH(_ident, _name, _axis) {         \
+       .ident = _ident,                                \
+       .callback = lis3lv02d_dmi_matched,              \
+       .matches = {                                    \
+               DMI_MATCH(DMI_PRODUCT_NAME, _name)      \
+       },                                              \
+       .driver_data = &lis3lv02d_axis_##_axis          \
+}
+
+#define AXIS_DMI_MATCH2(_ident, _class1, _name1,       \
+                               _class2, _name2,        \
+                               _axis) {                \
+       .ident = _ident,                                \
+       .callback = lis3lv02d_dmi_matched,              \
+       .matches = {                                    \
+               DMI_MATCH(DMI_##_class1, _name1),       \
+               DMI_MATCH(DMI_##_class2, _name2),       \
+       },                                              \
+       .driver_data = &lis3lv02d_axis_##_axis          \
+}
+static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+       /* product names are truncated to match all kinds of a same model */
+       AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
+       AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+       AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
+       AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
+       AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+       AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
+       AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
+       AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+       AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
+       AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
+       AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+       AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
+       AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
+       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
+       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
+       /* Intel-based HP Pavilion dv5 */
+       AXIS_DMI_MATCH2("HPDV5_I",
+                       PRODUCT_NAME, "HP Pavilion dv5",
+                       BOARD_NAME, "3603",
+                       x_inverted),
+       /* AMD-based HP Pavilion dv5 */
+       AXIS_DMI_MATCH2("HPDV5_A",
+                       PRODUCT_NAME, "HP Pavilion dv5",
+                       BOARD_NAME, "3600",
+                       y_inverted),
+       AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
+       AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+       AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
+       AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
+       AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
+       AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
+       AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
+       AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+       AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
+       { NULL, }
+/* Laptop models without axis info (yet):
+ * "NC6910" "HP Compaq 6910"
+ * "NC2400" "HP Compaq nc2400"
+ * "NX74x0" "HP Compaq nx74"
+ * "NX6325" "HP Compaq nx6325"
+ * "NC4400" "HP Compaq nc4400"
+ */
+};
+
+static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
+{
+       struct acpi_device *dev = lis3_dev.bus_priv;
+       unsigned long long ret; /* Not used when writing */
+       union acpi_object in_obj[1];
+       struct acpi_object_list args = { 1, in_obj };
+
+       in_obj[0].type          = ACPI_TYPE_INTEGER;
+       in_obj[0].integer.value = !!value;
+
+       acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
+}
+
+static struct delayed_led_classdev hpled_led = {
+       .led_classdev = {
+               .name                   = "hp::hddprotect",
+               .default_trigger        = "none",
+               .brightness_set         = delayed_sysfs_set,
+               .flags                  = LED_CORE_SUSPENDRESUME,
+       },
+       .set_brightness = hpled_set,
+};
+
+static acpi_status
+lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
+{
+       if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+               struct acpi_resource_extended_irq *irq;
+               u32 *device_irq = context;
+
+               irq = &resource->data.extended_irq;
+               *device_irq = irq->interrupts[0];
+       }
+
+       return AE_OK;
+}
+
+static void lis3lv02d_enum_resources(struct acpi_device *device)
+{
+       acpi_status status;
+
+       status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+                                       lis3lv02d_get_resource, &lis3_dev.irq);
+       if (ACPI_FAILURE(status))
+               printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
+}
+
+static int lis3lv02d_add(struct acpi_device *device)
+{
+       int ret;
+
+       if (!device)
+               return -EINVAL;
+
+       lis3_dev.bus_priv = device;
+       lis3_dev.init = lis3lv02d_acpi_init;
+       lis3_dev.read = lis3lv02d_acpi_read;
+       lis3_dev.write = lis3lv02d_acpi_write;
+       strcpy(acpi_device_name(device), DRIVER_NAME);
+       strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+       device->driver_data = &lis3_dev;
+
+       /* obtain IRQ number of our device from ACPI */
+       lis3lv02d_enum_resources(device);
+
+       /* If possible use a "standard" axes order */
+       if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+               pr_info("Using custom axes %d,%d,%d\n",
+                       lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+       } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+               pr_info("laptop model unknown, using default axes configuration\n");
+               lis3_dev.ac = lis3lv02d_axis_normal;
+       }
+
+       /* call the core layer do its init */
+       ret = lis3lv02d_init_device(&lis3_dev);
+       if (ret)
+               return ret;
+
+       INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+       ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+       if (ret) {
+               lis3lv02d_joystick_disable();
+               lis3lv02d_poweroff(&lis3_dev);
+               flush_work(&hpled_led.work);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int lis3lv02d_remove(struct acpi_device *device, int type)
+{
+       if (!device)
+               return -EINVAL;
+
+       lis3lv02d_joystick_disable();
+       lis3lv02d_poweroff(&lis3_dev);
+
+       led_classdev_unregister(&hpled_led.led_classdev);
+       flush_work(&hpled_led.work);
+
+       return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+
+#ifdef CONFIG_PM
+static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+{
+       /* make sure the device is off when we suspend */
+       lis3lv02d_poweroff(&lis3_dev);
+       return 0;
+}
+
+static int lis3lv02d_resume(struct acpi_device *device)
+{
+       lis3lv02d_poweron(&lis3_dev);
+       return 0;
+}
+#else
+#define lis3lv02d_suspend NULL
+#define lis3lv02d_resume NULL
+#endif
+
+/* For the HP MDPS aka 3D Driveguard */
+static struct acpi_driver lis3lv02d_driver = {
+       .name  = DRIVER_NAME,
+       .class = ACPI_MDPS_CLASS,
+       .ids   = lis3lv02d_device_ids,
+       .ops = {
+               .add     = lis3lv02d_add,
+               .remove  = lis3lv02d_remove,
+               .suspend = lis3lv02d_suspend,
+               .resume  = lis3lv02d_resume,
+       }
+};
+
+static int __init lis3lv02d_init_module(void)
+{
+       int ret;
+
+       if (acpi_disabled)
+               return -ENODEV;
+
+       ret = acpi_bus_register_driver(&lis3lv02d_driver);
+       if (ret < 0)
+               return ret;
+
+       pr_info("driver loaded\n");
+
+       return 0;
+}
+
+static void __exit lis3lv02d_exit_module(void)
+{
+       acpi_bus_unregister_driver(&lis3lv02d_driver);
+}
+
+MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init_module);
+module_exit(lis3lv02d_exit_module);
index 42517da07049e38e04da56a0ce4cdb78a87795eb..4feb7e9e71ee6c14fb8ce8585437ccd3d7dde24c 100644 (file)
@@ -6,6 +6,4 @@ obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o
 obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o
 obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
 
-ifeq ($(CONFIG_PPS_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
index b6139fe187bfe7389f1b30970dc03c16660ca161..89b8eca825b55f28dc6a29afa8eabed91730bd3e 100644 (file)
@@ -5,6 +5,4 @@ obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
 
 obj-$(CONFIG_RAPIDIO)          += switches/
 
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
index 48d67a6b98c89febb63780c598ad394f2fb15bc8..c4d3acc3c71560f63b605b410072ace4828c81a5 100644 (file)
@@ -7,7 +7,3 @@ obj-$(CONFIG_RAPIDIO_CPS_XX)    += idtcps.o
 obj-$(CONFIG_RAPIDIO_TSI568)   += tsi568.o
 obj-$(CONFIG_RAPIDIO_TSI500)   += tsi500.o
 obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o
-
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
index 2afdaf3ff98660f53c72a189503786ebeac0a27c..5f6c3838dcf6ab3b6c71c785dc8747fd107fd9b7 100644 (file)
@@ -2,9 +2,7 @@
 # Makefile for RTC class/drivers.
 #
 
-ifeq ($(CONFIG_RTC_DEBUG),y)
-       EXTRA_CFLAGS            += -DDEBUG
-endif
+ccflags-$(CONFIG_RTC_DEBUG)    := -DDEBUG
 
 obj-$(CONFIG_RTC_LIB)          += rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)      += hctosys.o
index f1cca4ee541006c6767b5242f124dfcefcc6d6a0..92df4d6b6147c677a76a4852bf521cd43ea88711 100644 (file)
@@ -5,4 +5,4 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 aacraid-objs   := linit.o aachba.o commctrl.o comminit.o commsup.o \
                   dpcsup.o rx.o sa.o rkt.o nark.o
 
-EXTRA_CFLAGS   := -Idrivers/scsi
+ccflags-y      := -Idrivers/scsi
index e78ce0fa44d2dd8c9d0eb8fe87ffd3141b9c2915..c0a15c75458506373e481fc36e79a857af8abc59 100644 (file)
@@ -22,9 +22,7 @@
 # along with the aic94xx driver; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-ifeq ($(CONFIG_AIC94XX_DEBUG),y)
-       EXTRA_CFLAGS += -DASD_DEBUG -DASD_ENTER_EXIT
-endif
+ccflags-$(CONFIG_AIC94XX_DEBUG) := -DASD_DEBUG -DASD_ENTER_EXIT
 
 obj-$(CONFIG_SCSI_AIC94XX) += aic94xx.o
 aic94xx-y += aic94xx_init.o \
index 566a10024598b630f44d28544a22de8cd636ccca..2e70140f70c3d88f3aee051601e945bcd0f7abec 100644 (file)
@@ -32,4 +32,4 @@ libsas-y +=  sas_init.o     \
                sas_scsi_host.o \
                sas_task.o
 libsas-$(CONFIG_SCSI_SAS_ATA) +=       sas_ata.o
-libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=  sas_host_smp.o
\ No newline at end of file
+libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=  sas_host_smp.o
index ad05d6edb8f6906eaf28943d71738fa98a5848b7..14de249917f8c226c2159cea4cf767aa56029239 100644 (file)
 # *******************************************************************/
 ######################################################################
 
-ifneq ($(GCOV),)
-  EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
-  EXTRA_CFLAGS += -O0
-endif
+ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage
+ccflags-$(GCOV) += -O0
 
 obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 
index 52ac4264677d3a053065f2dc3c3513bbc8e7626c..ffbf759e46f1ec83db27607a210e1e0354f4398c 100644 (file)
@@ -21,9 +21,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-ifeq ($(CONFIG_SCSI_MVSAS_DEBUG),y)
-       EXTRA_CFLAGS += -DMV_DEBUG
-endif
+ccflags-$(CONFIG_SCSI_MVSAS_DEBUG) := -DMV_DEBUG
 
 obj-$(CONFIG_SCSI_MVSAS) += mvsas.o
 mvsas-y +=  mv_init.o  \
index eca379059db652691ae7988024cf6b9a818a54a5..683bf148b5b7675beecb001365fa307da11dc206 100644 (file)
@@ -1,5 +1,5 @@
 
-EXTRA_CFLAGS           += -Idrivers/scsi
+ccflags-y              := -Idrivers/scsi
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_QLOGIC)    += qlogic_cs.o
index 991de3c15cfcbc4bcc61096272e747f40e30448c..633c2395a92a2c918cfd068d541f99063f9470f2 100644 (file)
@@ -3,14 +3,14 @@
  *
  *  SCSI error/timeout handling
  *      Initial versions: Eric Youngdale.  Based upon conversations with
- *                        Leonard Zubkoff and David Miller at Linux Expo, 
+ *                        Leonard Zubkoff and David Miller at Linux Expo,
  *                        ideas originating from all over the place.
  *
  *     Restructured scsi_unjam_host and associated functions.
  *     September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  *
  *     Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
- *     minor  cleanups.
+ *     minor cleanups.
  *     September 30, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
@@ -129,14 +129,15 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
 {
        struct scsi_cmnd *scmd = req->special;
        enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
+       struct Scsi_Host *host = scmd->device->host;
 
        trace_scsi_dispatch_cmd_timeout(scmd);
        scsi_log_completion(scmd, TIMEOUT_ERROR);
 
-       if (scmd->device->host->transportt->eh_timed_out)
-               rtn = scmd->device->host->transportt->eh_timed_out(scmd);
-       else if (scmd->device->host->hostt->eh_timed_out)
-               rtn = scmd->device->host->hostt->eh_timed_out(scmd);
+       if (host->transportt->eh_timed_out)
+               rtn = host->transportt->eh_timed_out(scmd);
+       else if (host->hostt->eh_timed_out)
+               rtn = host->hostt->eh_timed_out(scmd);
 
        if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
                     !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
@@ -195,7 +196,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
                                ++total_failures;
                                if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
                                        ++cmd_cancel;
-                               else 
+                               else
                                        ++cmd_failed;
                        }
                }
@@ -214,7 +215,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
 
        SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d"
                                          " devices require eh work\n",
-                                 total_failures, devices_failed));
+                                  total_failures, devices_failed));
 }
 #endif
 
@@ -294,7 +295,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                        return NEEDS_RETRY;
                }
                /*
-                * if the device is in the process of becoming ready, we 
+                * if the device is in the process of becoming ready, we
                 * should retry.
                 */
                if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
@@ -488,7 +489,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
  */
 static void scsi_eh_done(struct scsi_cmnd *scmd)
 {
-       struct completion     *eh_action;
+       struct completion *eh_action;
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s scmd: %p result: %x\n",
@@ -507,22 +508,23 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
 {
        unsigned long flags;
        int rtn;
+       struct Scsi_Host *host = scmd->device->host;
+       struct scsi_host_template *hostt = host->hostt;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
                                          __func__));
 
-       if (!scmd->device->host->hostt->eh_host_reset_handler)
+       if (!hostt->eh_host_reset_handler)
                return FAILED;
 
-       rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
+       rtn = hostt->eh_host_reset_handler(scmd);
 
        if (rtn == SUCCESS) {
-               if (!scmd->device->host->hostt->skip_settle_delay)
+               if (!hostt->skip_settle_delay)
                        ssleep(HOST_RESET_SETTLE_TIME);
-               spin_lock_irqsave(scmd->device->host->host_lock, flags);
-               scsi_report_bus_reset(scmd->device->host,
-                                     scmd_channel(scmd));
-               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+               spin_lock_irqsave(host->host_lock, flags);
+               scsi_report_bus_reset(host, scmd_channel(scmd));
+               spin_unlock_irqrestore(host->host_lock, flags);
        }
 
        return rtn;
@@ -536,22 +538,23 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
 {
        unsigned long flags;
        int rtn;
+       struct Scsi_Host *host = scmd->device->host;
+       struct scsi_host_template *hostt = host->hostt;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
                                          __func__));
 
-       if (!scmd->device->host->hostt->eh_bus_reset_handler)
+       if (!hostt->eh_bus_reset_handler)
                return FAILED;
 
-       rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
+       rtn = hostt->eh_bus_reset_handler(scmd);
 
        if (rtn == SUCCESS) {
-               if (!scmd->device->host->hostt->skip_settle_delay)
+               if (!hostt->skip_settle_delay)
                        ssleep(BUS_RESET_SETTLE_TIME);
-               spin_lock_irqsave(scmd->device->host->host_lock, flags);
-               scsi_report_bus_reset(scmd->device->host,
-                                     scmd_channel(scmd));
-               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+               spin_lock_irqsave(host->host_lock, flags);
+               scsi_report_bus_reset(host, scmd_channel(scmd));
+               spin_unlock_irqrestore(host->host_lock, flags);
        }
 
        return rtn;
@@ -577,16 +580,18 @@ static int scsi_try_target_reset(struct scsi_cmnd *scmd)
 {
        unsigned long flags;
        int rtn;
+       struct Scsi_Host *host = scmd->device->host;
+       struct scsi_host_template *hostt = host->hostt;
 
-       if (!scmd->device->host->hostt->eh_target_reset_handler)
+       if (!hostt->eh_target_reset_handler)
                return FAILED;
 
-       rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+       rtn = hostt->eh_target_reset_handler(scmd);
        if (rtn == SUCCESS) {
-               spin_lock_irqsave(scmd->device->host->host_lock, flags);
+               spin_lock_irqsave(host->host_lock, flags);
                __starget_for_each_device(scsi_target(scmd->device), NULL,
                                          __scsi_report_device_reset);
-               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+               spin_unlock_irqrestore(host->host_lock, flags);
        }
 
        return rtn;
@@ -605,27 +610,28 @@ static int scsi_try_target_reset(struct scsi_cmnd *scmd)
 static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
 {
        int rtn;
+       struct scsi_host_template *hostt = scmd->device->host->hostt;
 
-       if (!scmd->device->host->hostt->eh_device_reset_handler)
+       if (!hostt->eh_device_reset_handler)
                return FAILED;
 
-       rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+       rtn = hostt->eh_device_reset_handler(scmd);
        if (rtn == SUCCESS)
                __scsi_report_device_reset(scmd->device, NULL);
        return rtn;
 }
 
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
 {
-       if (!scmd->device->host->hostt->eh_abort_handler)
+       if (!hostt->eh_abort_handler)
                return FAILED;
 
-       return scmd->device->host->hostt->eh_abort_handler(scmd);
+       return hostt->eh_abort_handler(scmd);
 }
 
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-       if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
+       if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
                if (scsi_try_bus_device_reset(scmd) != SUCCESS)
                        if (scsi_try_target_reset(scmd) != SUCCESS)
                                if (scsi_try_bus_reset(scmd) != SUCCESS)
@@ -846,7 +852,7 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd);
  *
  * Description:
  *    See if we need to request sense information.  if so, then get it
- *    now, so we have a better idea of what to do.  
+ *    now, so we have a better idea of what to do.
  *
  * Notes:
  *    This has the unfortunate side effect that if a shost adapter does
@@ -958,7 +964,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
                SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
                                                  "0x%p\n", current->comm,
                                                  scmd));
-               rtn = scsi_try_to_abort_cmd(scmd);
+               rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd);
                if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
                        scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
                        if (!scsi_device_online(scmd->device) ||
@@ -966,7 +972,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
                            !scsi_eh_tur(scmd)) {
                                scsi_eh_finish_cmd(scmd, done_q);
                        }
-                               
                } else
                        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
                                                          " cmd failed:"
@@ -1010,7 +1015,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
  *
  * Notes:
  *    If commands are failing due to not ready, initializing command required,
- *     try revalidating the device, which will end up sending a start unit. 
+ *     try revalidating the device, which will end up sending a start unit.
  */
 static int scsi_eh_stu(struct Scsi_Host *shost,
                              struct list_head *work_q,
@@ -1064,7 +1069,7 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
  *    Try a bus device reset.  Still, look to see whether we have multiple
  *    devices that are jammed or not - if we have multiple devices, it
  *    makes no sense to try bus_device_reset - we really would need to try
- *    a bus_reset instead. 
+ *    a bus_reset instead.
  */
 static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
                                    struct list_head *work_q,
@@ -1164,7 +1169,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
 }
 
 /**
- * scsi_eh_bus_reset - send a bus reset 
+ * scsi_eh_bus_reset - send a bus reset
  * @shost:     &scsi host being recovered.
  * @work_q:     &list_head for pending commands.
  * @done_q:    &list_head for processed commands.
@@ -1181,7 +1186,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
         * we really want to loop over the various channels, and do this on
         * a channel by channel basis.  we should also check to see if any
         * of the failed commands are on soft_reset devices, and if so, skip
-        * the reset.  
+        * the reset.
         */
 
        for (channel = 0; channel <= shost->max_channel; channel++) {
@@ -1223,7 +1228,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
 }
 
 /**
- * scsi_eh_host_reset - send a host reset 
+ * scsi_eh_host_reset - send a host reset
  * @work_q:    list_head for processed commands.
  * @done_q:    list_head for processed commands.
  */
@@ -1376,7 +1381,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
                return SUCCESS;
                /*
                 * when the low level driver returns did_soft_error,
-                * it is responsible for keeping an internal retry counter 
+                * it is responsible for keeping an internal retry counter
                 * in order to avoid endless loops (db)
                 *
                 * actually this is a bug in this function here.  we should
@@ -1414,7 +1419,6 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
                         */
                        break;
                /* fallthrough */
-
        case DID_BUS_BUSY:
        case DID_PARITY:
                goto maybe_retry;
@@ -1982,7 +1986,7 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
                if (sb_len > 7)
                        sshdr->additional_length = sense_buffer[7];
        } else {
-               /* 
+               /*
                 * fixed format
                 */
                if (sb_len > 2)
index 38072e4e74bd66776e64ae6fdd9c1ad97dac3aae..e35a17687c05f77b9ecc55b4002d0b13386081b6 100644 (file)
@@ -1646,7 +1646,7 @@ static int autosuspend_check(struct usb_device *udev)
        return 0;
 }
 
-static int usb_runtime_suspend(struct device *dev)
+int usb_runtime_suspend(struct device *dev)
 {
        struct usb_device       *udev = to_usb_device(dev);
        int                     status;
@@ -1667,7 +1667,7 @@ static int usb_runtime_suspend(struct device *dev)
        return status;
 }
 
-static int usb_runtime_resume(struct device *dev)
+int usb_runtime_resume(struct device *dev)
 {
        struct usb_device       *udev = to_usb_device(dev);
        int                     status;
@@ -1679,7 +1679,7 @@ static int usb_runtime_resume(struct device *dev)
        return status;
 }
 
-static int usb_runtime_idle(struct device *dev)
+int usb_runtime_idle(struct device *dev)
 {
        struct usb_device       *udev = to_usb_device(dev);
 
@@ -1691,19 +1691,10 @@ static int usb_runtime_idle(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops usb_bus_pm_ops = {
-       .runtime_suspend =      usb_runtime_suspend,
-       .runtime_resume =       usb_runtime_resume,
-       .runtime_idle =         usb_runtime_idle,
-};
-
 #endif /* CONFIG_USB_SUSPEND */
 
 struct bus_type usb_bus_type = {
        .name =         "usb",
        .match =        usb_device_match,
        .uevent =       usb_uevent,
-#ifdef CONFIG_USB_SUSPEND
-       .pm =           &usb_bus_pm_ops,
-#endif
 };
index 079cb57bab4f214f5d6aecf5a538044a404477da..d9d4b169404f9d46fbda9f5fa7cc09d00468d0a2 100644 (file)
@@ -315,6 +315,11 @@ static const struct dev_pm_ops usb_device_pm_ops = {
        .thaw =         usb_dev_thaw,
        .poweroff =     usb_dev_poweroff,
        .restore =      usb_dev_restore,
+#ifdef CONFIG_USB_SUSPEND
+       .runtime_suspend =      usb_runtime_suspend,
+       .runtime_resume =       usb_runtime_resume,
+       .runtime_idle =         usb_runtime_idle,
+#endif
 };
 
 #endif /* CONFIG_PM */
index a9cf484ecae4c9efd39d298f607127d1f4e32fc3..d450b742137e45f4c9c728044ce394f578cac302 100644 (file)
@@ -77,6 +77,9 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 extern void usb_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 extern int usb_remote_wakeup(struct usb_device *dev);
+extern int usb_runtime_suspend(struct device *dev);
+extern int usb_runtime_resume(struct device *dev);
+extern int usb_runtime_idle(struct device *dev);
 
 #else
 
index 6c782d3ae1bede62c0bc8a7c93526c144d102600..f7d631ebee8e34981360a83e5c56c97555238a43 100644 (file)
@@ -4,7 +4,4 @@ intelfb-y := intelfbdrv.o intelfbhw.o
 intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
 intelfb-objs := $(intelfb-y)
 
-ifdef CONFIG_FB_INTEL_DEBUG
-#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
-EXTRA_CFLAGS += -DDEBUG -DREGDUMP
-endif
+ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
index a082debe824b9969bf3cb76018d638471b6700ae..a74439affce9c7a4b09c0783e226911ce3894a2c 100644 (file)
@@ -1461,13 +1461,6 @@ static struct board {
                MGA_G100,
                &vbG100,
                "MGA-G100 (AGP)"},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200EV_PCI,        0xFF,
-               0,                      0,
-               DEVF_G200,
-               230000,
-               MGA_G200,
-               &vbG200,
-               "MGA-G200eV (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,  0xFF,
                0,                      0,
                DEVF_G200,
@@ -2119,8 +2112,6 @@ static struct pci_device_id matroxfb_devices[] = {
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200EV_PCI,
-               PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,
index b2c4f54446f3c720e22dd51ce6717c5d1e9a6b3e..3988b4a78339aab8ff6dd1fd3656560ccd9aee3f 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Linux affs filesystem routines.
 #
 
-#EXTRA_CFLAGS=-DDEBUG=1
+#ccflags-y := -DDEBUG=1
 
 obj-$(CONFIG_AFFS_FS) += affs.o
 
index 685ecff3ab31728d2362a9be39f98dfbc76947c4..b14cebfd90477ead4b15f0c1583da6393c247de5 100644 (file)
@@ -97,7 +97,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
        if (!inode)
                return -ENOSPC;
        mutex_lock(&info->bfs_lock);
-       ino = find_first_zero_bit(info->si_imap, info->si_lasti);
+       ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1);
        if (ino > info->si_lasti) {
                mutex_unlock(&info->bfs_lock);
                iput(inode);
index 6c22e61da39779be11ef3e9765de1b1df17743d4..1bab69a0d347696d28f854f6b1928f09937ac5f5 100644 (file)
@@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \
 
 # If you want debugging output, please uncomment the following line.
 
-# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1
+# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1
index c6d31a3bab8863af2c5403e487f1cfc23bf63310..72fe6cda9108a162177e91093514a68854323f5a 100644 (file)
@@ -1671,9 +1671,6 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-#define MAX_SELECT_SECONDS \
-       ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
 int compat_core_sys_select(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
        struct timespec *end_time)
index 1bb547c9cad6d98d5c2816a3bf01d46481a72224..c6bd815dc7943c1035e82cd6010b83ba2b00b584 100644 (file)
@@ -479,6 +479,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
        struct dentry *root = sb->s_root;
        struct pts_fs_info *fsi = DEVPTS_SB(sb);
        struct pts_mount_opts *opts = &fsi->mount_opts;
+       int ret = 0;
        char s[12];
 
        /* We're supposed to be given the slave end of a pty */
@@ -504,11 +505,14 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
        if (!IS_ERR(dentry)) {
                d_add(dentry, inode);
                fsnotify_create(root->d_inode, dentry);
+       } else {
+               iput(inode);
+               ret = -ENOMEM;
        }
 
        mutex_unlock(&root->d_inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
@@ -544,17 +548,12 @@ void devpts_pty_kill(struct tty_struct *tty)
        mutex_lock(&root->d_inode->i_mutex);
 
        dentry = d_find_alias(inode);
-       if (IS_ERR(dentry))
-               goto out;
-
-       if (dentry) {
-               inode->i_nlink--;
-               d_delete(dentry);
-               dput(dentry);   /* d_alloc_name() in devpts_pty_new() */
-       }
 
+       inode->i_nlink--;
+       d_delete(dentry);
+       dput(dentry);   /* d_alloc_name() in devpts_pty_new() */
        dput(dentry);           /* d_find_alias above */
-out:
+
        mutex_unlock(&root->d_inode->i_mutex);
 }
 
index ba99e1abb1aa3427aca0e95f116e4deaa85ff793..5e62d26a4fecec227d81700b0b9fd6542b715ad6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1875,7 +1875,7 @@ static void wait_for_dump_helpers(struct file *file)
 
 
 /*
- * uhm_pipe_setup
+ * umh_pipe_setup
  * helper function to customize the process used
  * to collect the core in userspace.  Specifically
  * it sets up a pipe and installs it as fd 0 (stdin)
index 4e303c22d5ee53613682530bd1705a0a3cec8382..b1a524d798e720cf18ad7ad4decdab430a2b9c5e 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -66,8 +66,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
                                /* suppress POLLHUP until we have
                                 * seen a writer */
                                filp->f_version = pipe->w_counter;
-                       } else 
-                       {
+                       } else {
                                wait_for_partner(inode, &pipe->w_counter);
                                if(signal_pending(current))
                                        goto err_rd;
index 21f7e46da4c015925b5ff4ae1b6856f25653ea64..f3d23ef4e876a913aa48608bfe71aa2d192ecb05 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -I$(src)
+ccflags-y := -I$(src)
 obj-$(CONFIG_GFS2_FS) += gfs2.o
 gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \
        glops.o inode.o log.o lops.o main.o meta_io.o \
index 9910c039f026254a9caea134a5a7ac8d40c9c76f..16fefd373fc2570449c97a34697f315536022f19 100644 (file)
@@ -1715,7 +1715,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 EXPORT_SYMBOL(init_special_inode);
 
 /**
- * Init uid,gid,mode for new inode according to posix standards
+ * inode_init_owner - Init uid,gid,mode for new inode according to posix standards
  * @inode: New inode
  * @dir: Directory inode
  * @mode: mode of the new inode
index 17191546d52768691e405da4cc53735d9589e275..8318059b42c6b950b9b3e338ff8c15654ca1798a 100644 (file)
@@ -64,6 +64,7 @@ extern int copy_mount_string(const void __user *, char **);
 
 extern unsigned int mnt_get_count(struct vfsmount *mnt);
 extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+extern struct vfsmount *lookup_mnt(struct path *);
 extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
                                struct vfsmount *);
 extern void release_mounts(struct list_head *);
index 1eebeb72b20276191fcad6199d8bf0b79a4d9921..1d9b9fcb2db48ec682b4e696bbab9dbb79fd26b9 100644 (file)
@@ -548,6 +548,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 {
        int error = 0;
        int __user *argp = (int __user *)arg;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        switch (cmd) {
        case FIOCLEX:
@@ -567,13 +568,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
                break;
 
        case FIOQSIZE:
-               if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
-                   S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
-                   S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
-                       loff_t res =
-                               inode_get_bytes(filp->f_path.dentry->d_inode);
-                       error = copy_to_user((loff_t __user *)arg, &res,
-                                            sizeof(res)) ? -EFAULT : 0;
+               if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
+                   S_ISLNK(inode->i_mode)) {
+                       loff_t res = inode_get_bytes(inode);
+                       error = copy_to_user(argp, &res, sizeof(res)) ?
+                                       -EFAULT : 0;
                } else
                        error = -ENOTTY;
                break;
@@ -590,14 +589,10 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
                return ioctl_fiemap(filp, arg);
 
        case FIGETBSZ:
-       {
-               struct inode *inode = filp->f_path.dentry->d_inode;
-               int __user *p = (int __user *)arg;
-               return put_user(inode->i_sb->s_blocksize, p);
-       }
+               return put_user(inode->i_sb->s_blocksize, argp);
 
        default:
-               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+               if (S_ISREG(inode->i_mode))
                        error = file_ioctl(filp, cmd, arg);
                else
                        error = vfs_ioctl(filp, cmd, arg);
index 3adb6395e42de858ada7adec76b964dfef250e41..a58fa72d7e59e511cc849eb01cee92fa5afb1320 100644 (file)
@@ -13,4 +13,4 @@ jfs-y    := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \
 
 jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o
 
-EXTRA_CFLAGS += -D_JFS_4K
+ccflags-y := -D_JFS_4K
index 68ea095100a817262d1858bba4754c22c5206016..c66af563f2ceef35fbf68b01527866f8128711d0 100644 (file)
@@ -11,6 +11,6 @@ ncpfs-$(CONFIG_NCPFS_EXTRAS)   += symlink.o
 ncpfs-$(CONFIG_NCPFS_NFS_NS)   += symlink.o
 
 # If you want debugging output, please uncomment the following line
-# EXTRA_CFLAGS += -DDEBUG_NCP=1
+# ccflags-y := -DDEBUG_NCP=1
 
 CFLAGS_ncplib_kernel.o := -finline-functions
index c0b8344db0c65129d08d6a299a051fed0ce430fd..bf1c68009ffd8b64001ecdd4d9f266654d2a3656 100644 (file)
@@ -98,7 +98,7 @@ rename_retry:
                namelen--;
        buflen -= namelen;
        if (buflen < 0) {
-               spin_lock(&dentry->d_lock);
+               spin_unlock(&dentry->d_lock);
                rcu_read_unlock();
                goto Elong;
        }
@@ -108,7 +108,7 @@ rename_retry:
        rcu_read_unlock();
        return end;
 Elong_unlock:
-       spin_lock(&dentry->d_lock);
+       spin_unlock(&dentry->d_lock);
        rcu_read_unlock();
        if (read_seqretry(&rename_lock, seq))
                goto rename_retry;
index d7fd696e595ccdcb67f42e7a1d9b9e21f6dec3dc..0a0a66d98cce85f327b32080c8a97045e8babdf7 100644 (file)
@@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
                                    group_offset, bitmap))
                printk(KERN_WARNING "%s: entry number %llu already freed\n",
                       __func__, (unsigned long long)req->pr_entry_nr);
-
-       nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+       else
+               nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
 
        kunmap(req->pr_bitmap_bh->b_page);
        kunmap(req->pr_desc_bh->b_page);
@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
                                    group_offset, bitmap))
                printk(KERN_WARNING "%s: entry number %llu already freed\n",
                       __func__, (unsigned long long)req->pr_entry_nr);
-
-       nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+       else
+               nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
 
        kunmap(req->pr_bitmap_bh->b_page);
        kunmap(req->pr_desc_bh->b_page);
@@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
                for (j = i, n = 0;
                     (j < nitems) && nilfs_palloc_group_is_in(inode, group,
                                                              entry_nrs[j]);
-                    j++, n++) {
+                    j++) {
                        nilfs_palloc_group(inode, entry_nrs[j], &group_offset);
                        if (!nilfs_clear_bit_atomic(
                                    nilfs_mdt_bgl_lock(inode, group),
@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
                                       "%s: entry number %llu already freed\n",
                                       __func__,
                                       (unsigned long long)entry_nrs[j]);
+                       } else {
+                               n++;
                        }
                }
                nilfs_palloc_group_desc_add_entries(inode, group, desc, n);
index 3ee67c67cc52ee5d6d0711023bb2c2ad43c1e32c..4723f04e9b12a0e904f945997b5e1aa73cfc757b 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/errno.h>
 #include "nilfs.h"
 #include "bmap.h"
-#include "sb.h"
 #include "btree.h"
 #include "direct.h"
 #include "btnode.h"
@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
 /*
  * Internal use only
  */
-
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
-{
-       inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
-{
-       inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
 __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
                              const struct buffer_head *bh)
 {
index bde1c0aa2e15a3a0c3eb9f4071d78dce586f0d17..40d9f453d31c121d29dc09279bfa57ece7d79d7d 100644 (file)
@@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
 __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
 __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
 
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
-
 
 /* Assume that bmap semaphore is locked. */
 static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
index 300c2bc00c3f4c29034459d885fa4adf34850c99..d451ae0e0bf373917b88e4591b60f4ad912bc3db 100644 (file)
@@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
        if (ret < 0)
                goto out;
        nilfs_btree_commit_insert(btree, path, level, key, ptr);
-       nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+       nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
 
  out:
        nilfs_btree_free_path(path);
@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
        if (ret < 0)
                goto out;
        nilfs_btree_commit_delete(btree, path, level, dat);
-       nilfs_bmap_sub_blocks(btree, stats.bs_nblocks);
+       nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
 
 out:
        nilfs_btree_free_path(path);
@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
                return ret;
        nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
                                              di, ni, bh);
-       nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+       nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
        return 0;
 }
 
index 9d45773b79e63f9d7be433ca604caef7fc518cea..3a1923943b14c9300bd8af952451efa86177c09c 100644 (file)
@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
        nilfs_commit_chunk(page, mapping, from, to);
        nilfs_put_page(page);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/*     NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
 }
 
 /*
@@ -531,7 +530,6 @@ got_it:
        nilfs_set_de_type(de, inode);
        nilfs_commit_chunk(page, page->mapping, from, to);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/*     NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
        nilfs_mark_inode_dirty(dir);
        /* OFFSET_CACHE */
 out_put:
@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
        dir->inode = 0;
        nilfs_commit_chunk(page, mapping, from, to);
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-/*     NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */
 out:
        nilfs_put_page(page);
        return err;
@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = {
        .readdir        = nilfs_readdir,
        .unlocked_ioctl = nilfs_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl   = nilfs_ioctl,
+       .compat_ioctl   = nilfs_compat_ioctl,
 #endif /* CONFIG_COMPAT */
        .fsync          = nilfs_sync_file,
 
index 324d80c57518ad09a83cab70ee1ca6abfae4d644..82f4865e86dd5de3b33570be200a205c87d95ccf 100644 (file)
@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
                if (NILFS_BMAP_USE_VBN(bmap))
                        nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
 
-               nilfs_bmap_add_blocks(bmap, 1);
+               nilfs_inode_add_blocks(bmap->b_inode, 1);
        }
        return ret;
 }
@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
        if (!ret) {
                nilfs_bmap_commit_end_ptr(bmap, &req, dat);
                nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
-               nilfs_bmap_sub_blocks(bmap, 1);
+               nilfs_inode_sub_blocks(bmap->b_inode, 1);
        }
        return ret;
 }
index 2f560c9fb808192cdddad3277c345e04440b1fb6..93589fccdd9744c59d6783931eca235b727d5432 100644 (file)
@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct nilfs_transaction_info ti;
        int ret;
 
-       if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs)))
+       if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
                return VM_FAULT_SIGBUS; /* -ENOSPC */
 
        lock_page(page);
@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = {
        .aio_write      = generic_file_aio_write,
        .unlocked_ioctl = nilfs_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl   = nilfs_ioctl,
+       .compat_ioctl   = nilfs_compat_ioctl,
 #endif /* CONFIG_COMPAT */
        .mmap           = nilfs_file_mmap,
        .open           = generic_file_open,
index 2fd440d8d6b8d9b2b469c2aaec757bca05a9ac58..d5625be236a8c430e8b025b542cdcae98ce5f9b4 100644 (file)
@@ -41,6 +41,24 @@ struct nilfs_iget_args {
        int for_gc;
 };
 
+void nilfs_inode_add_blocks(struct inode *inode, int n)
+{
+       struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+       inode_add_bytes(inode, (1 << inode->i_blkbits) * n);
+       if (root)
+               atomic_add(n, &root->blocks_count);
+}
+
+void nilfs_inode_sub_blocks(struct inode *inode, int n)
+{
+       struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+       inode_sub_bytes(inode, (1 << inode->i_blkbits) * n);
+       if (root)
+               atomic_sub(n, &root->blocks_count);
+}
+
 /**
  * nilfs_get_block() - get a file block on the filesystem (callback function)
  * @inode - inode struct of the target file
@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = {
 struct inode *nilfs_new_inode(struct inode *dir, int mode)
 {
        struct super_block *sb = dir->i_sb;
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct inode *inode;
        struct nilfs_inode_info *ii;
        struct nilfs_root *root;
@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
                /* No lock is needed; iget() ensures it. */
        }
 
-       ii->i_flags = NILFS_I(dir)->i_flags;
-       if (S_ISLNK(mode))
-               ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL);
-       if (!S_ISDIR(mode))
-               ii->i_flags &= ~NILFS_DIRSYNC_FL;
+       ii->i_flags = nilfs_mask_flags(
+               mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
 
        /* ii->i_file_acl = 0; */
        /* ii->i_dir_acl = 0; */
        ii->i_dir_start_lookup = 0;
        nilfs_set_inode_flags(inode);
-       spin_lock(&sbi->s_next_gen_lock);
-       inode->i_generation = sbi->s_next_generation++;
-       spin_unlock(&sbi->s_next_gen_lock);
+       spin_lock(&nilfs->ns_next_gen_lock);
+       inode->i_generation = nilfs->ns_next_generation++;
+       spin_unlock(&nilfs->ns_next_gen_lock);
        insert_inode_hash(inode);
 
        err = nilfs_init_acl(inode, dir);
@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode)
 
        inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
                            S_DIRSYNC);
-       if (flags & NILFS_SYNC_FL)
+       if (flags & FS_SYNC_FL)
                inode->i_flags |= S_SYNC;
-       if (flags & NILFS_APPEND_FL)
+       if (flags & FS_APPEND_FL)
                inode->i_flags |= S_APPEND;
-       if (flags & NILFS_IMMUTABLE_FL)
+       if (flags & FS_IMMUTABLE_FL)
                inode->i_flags |= S_IMMUTABLE;
-#ifndef NILFS_ATIME_DISABLE
-       if (flags & NILFS_NOATIME_FL)
-#endif
+       if (flags & FS_NOATIME_FL)
                inode->i_flags |= S_NOATIME;
-       if (flags & NILFS_DIRSYNC_FL)
+       if (flags & FS_DIRSYNC_FL)
                inode->i_flags |= S_DIRSYNC;
        mapping_set_gfp_mask(inode->i_mapping,
                             mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb,
                              struct nilfs_root *root, unsigned long ino,
                              struct inode *inode)
 {
-       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct buffer_head *bh;
        struct nilfs_inode *raw_inode;
        int err;
@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode)
        struct nilfs_transaction_info ti;
        struct super_block *sb = inode->i_sb;
        struct nilfs_inode_info *ii = NILFS_I(inode);
+       int ret;
 
        if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
                if (inode->i_data.nrpages)
@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode)
        nilfs_mark_inode_dirty(inode);
        end_writeback(inode);
 
-       nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
-       atomic_dec(&ii->i_root->inodes_count);
+       ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
+       if (!ret)
+               atomic_dec(&ii->i_root->inodes_count);
 
        nilfs_clear_inode(inode);
 
@@ -792,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
 
 int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_inode_info *ii = NILFS_I(inode);
        int err;
 
-       spin_lock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
        if (ii->i_bh == NULL) {
-               spin_unlock(&sbi->s_inode_lock);
+               spin_unlock(&nilfs->ns_inode_lock);
                err = nilfs_ifile_get_inode_block(ii->i_root->ifile,
                                                  inode->i_ino, pbh);
                if (unlikely(err))
                        return err;
-               spin_lock(&sbi->s_inode_lock);
+               spin_lock(&nilfs->ns_inode_lock);
                if (ii->i_bh == NULL)
                        ii->i_bh = *pbh;
                else {
@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
                *pbh = ii->i_bh;
 
        get_bh(*pbh);
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
        return 0;
 }
 
 int nilfs_inode_dirty(struct inode *inode)
 {
        struct nilfs_inode_info *ii = NILFS_I(inode);
-       struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        int ret = 0;
 
        if (!list_empty(&ii->i_dirty)) {
-               spin_lock(&sbi->s_inode_lock);
+               spin_lock(&nilfs->ns_inode_lock);
                ret = test_bit(NILFS_I_DIRTY, &ii->i_state) ||
                        test_bit(NILFS_I_BUSY, &ii->i_state);
-               spin_unlock(&sbi->s_inode_lock);
+               spin_unlock(&nilfs->ns_inode_lock);
        }
        return ret;
 }
 
 int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
        struct nilfs_inode_info *ii = NILFS_I(inode);
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 
-       atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks);
+       atomic_add(nr_dirty, &nilfs->ns_ndirtyblks);
 
        if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state))
                return 0;
 
-       spin_lock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
        if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
            !test_bit(NILFS_I_BUSY, &ii->i_state)) {
                /* Because this routine may race with nilfs_dispose_list(),
@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
                if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) {
                        /* This will happen when somebody is freeing
                           this inode. */
-                       nilfs_warning(sbi->s_super, __func__,
+                       nilfs_warning(inode->i_sb, __func__,
                                      "cannot get inode (ino=%lu)\n",
                                      inode->i_ino);
-                       spin_unlock(&sbi->s_inode_lock);
+                       spin_unlock(&nilfs->ns_inode_lock);
                        return -EINVAL; /* NILFS_I_DIRTY may remain for
                                           freeing inode */
                }
                list_del(&ii->i_dirty);
-               list_add_tail(&ii->i_dirty, &sbi->s_dirty_files);
+               list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files);
                set_bit(NILFS_I_QUEUED, &ii->i_state);
        }
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
        return 0;
 }
 
index 496738963fdbd029aa2a39723442020c5c4d9e93..95c04c2f2b3e06f619e1db52283b750479075296 100644 (file)
@@ -26,7 +26,9 @@
 #include <linux/capability.h>  /* capable() */
 #include <linux/uaccess.h>     /* copy_from_user(), copy_to_user() */
 #include <linux/vmalloc.h>
+#include <linux/compat.h>      /* compat_ptr() */
 #include <linux/mount.h>       /* mnt_want_write(), mnt_drop_write() */
+#include <linux/buffer_head.h>
 #include <linux/nilfs2_fs.h>
 #include "nilfs.h"
 #include "segment.h"
@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
        return ret;
 }
 
+static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
+{
+       unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
+
+       return put_user(flags, (int __user *)argp);
+}
+
+static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
+                               void __user *argp)
+{
+       struct nilfs_transaction_info ti;
+       unsigned int flags, oldflags;
+       int ret;
+
+       if (!is_owner_or_cap(inode))
+               return -EACCES;
+
+       if (get_user(flags, (int __user *)argp))
+               return -EFAULT;
+
+       ret = mnt_want_write(filp->f_path.mnt);
+       if (ret)
+               return ret;
+
+       flags = nilfs_mask_flags(inode->i_mode, flags);
+
+       mutex_lock(&inode->i_mutex);
+
+       oldflags = NILFS_I(inode)->i_flags;
+
+       /*
+        * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
+        * relevant capability.
+        */
+       ret = -EPERM;
+       if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
+           !capable(CAP_LINUX_IMMUTABLE))
+               goto out;
+
+       ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
+       if (ret)
+               goto out;
+
+       NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
+               (flags & FS_FL_USER_MODIFIABLE);
+
+       nilfs_set_inode_flags(inode);
+       inode->i_ctime = CURRENT_TIME;
+       if (IS_SYNC(inode))
+               nilfs_set_transaction_flag(NILFS_TI_SYNC);
+
+       nilfs_mark_inode_dirty(inode);
+       ret = nilfs_transaction_commit(inode->i_sb);
+out:
+       mutex_unlock(&inode->i_mutex);
+       mnt_drop_write(filp->f_path.mnt);
+       return ret;
+}
+
+static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
+{
+       return put_user(inode->i_generation, (int __user *)argp);
+}
+
 static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
                                     unsigned int cmd, void __user *argp)
 {
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
-       struct inode *cpfile = nilfs->ns_cpfile;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_transaction_info ti;
        struct nilfs_cpmode cpmode;
        int ret;
@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
 
        nilfs_transaction_begin(inode->i_sb, &ti, 0);
        ret = nilfs_cpfile_change_cpmode(
-               cpfile, cpmode.cm_cno, cpmode.cm_mode);
+               nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
        if (unlikely(ret < 0))
                nilfs_transaction_abort(inode->i_sb);
        else
@@ -137,7 +202,7 @@ static int
 nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
                              unsigned int cmd, void __user *argp)
 {
-       struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_transaction_info ti;
        __u64 cno;
        int ret;
@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
                goto out;
 
        nilfs_transaction_begin(inode->i_sb, &ti, 0);
-       ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
+       ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
        if (unlikely(ret < 0))
                nilfs_transaction_abort(inode->i_sb);
        else
@@ -180,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
                                  unsigned int cmd, void __user *argp)
 {
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_cpstat cpstat;
        int ret;
 
@@ -211,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
                                  unsigned int cmd, void __user *argp)
 {
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_sustat sustat;
        int ret;
 
@@ -267,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
                                  unsigned int cmd, void __user *argp)
 {
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_argv argv;
        int ret;
 
@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                                   struct nilfs_argv *argv, void *buf)
 {
        size_t nmembs = argv->v_nmembs;
-       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct inode *inode;
        struct nilfs_vdesc *vdesc;
        struct buffer_head *bh, *n;
@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
                ret = PTR_ERR(kbufs[4]);
                goto out;
        }
-       nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+       nilfs = inode->i_sb->s_fs_info;
 
        for (n = 0; n < 4; n++) {
                ret = -EINVAL;
@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
                return ret;
 
        if (argp != NULL) {
-               nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+               nilfs = inode->i_sb->s_fs_info;
                down_read(&nilfs->ns_segctor_sem);
                cno = nilfs->ns_cno - 1;
                up_read(&nilfs->ns_segctor_sem);
@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
                                                  void *, size_t, size_t))
 
 {
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
        struct nilfs_argv argv;
        int ret;
 
@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        void __user *argp = (void __user *)arg;
 
        switch (cmd) {
+       case FS_IOC_GETFLAGS:
+               return nilfs_ioctl_getflags(inode, argp);
+       case FS_IOC_SETFLAGS:
+               return nilfs_ioctl_setflags(inode, filp, argp);
+       case FS_IOC_GETVERSION:
+               return nilfs_ioctl_getversion(inode, argp);
        case NILFS_IOCTL_CHANGE_CPMODE:
                return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
        case NILFS_IOCTL_DELETE_CHECKPOINT:
@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return -ENOTTY;
        }
 }
+
+#ifdef CONFIG_COMPAT
+long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case FS_IOC32_GETFLAGS:
+               cmd = FS_IOC_GETFLAGS;
+               break;
+       case FS_IOC32_SETFLAGS:
+               cmd = FS_IOC_SETFLAGS;
+               break;
+       case FS_IOC32_GETVERSION:
+               cmd = FS_IOC_GETVERSION;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
index b13734bf3521d7370c03f623b46d023dd80241c0..ed68563ec708bd135c7abe0145a960de771424fb 100644 (file)
@@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode)
 
 static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode)
 {
-       return NILFS_SB(inode->i_sb)->s_nilfs;
+       return inode->i_sb->s_fs_info;
 }
 
 /* Default GFP flags using highmem */
index 161791d26458b3c6669dbb11cdd6741a8ae9facb..546849b3e88f1935585067628e158f4233631d17 100644 (file)
@@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
        if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
                return ERR_PTR(-ESTALE);
 
-       root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+       root = nilfs_lookup_root(sb->s_fs_info, cno);
        if (!root)
                return ERR_PTR(-ESTALE);
 
index 777e8fd043049dcfb53def4e5cc78ec50a9ec991..856e8e4e0b74df250ef4c619eb6096f01f4866d7 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/blkdev.h>
 #include <linux/nilfs2_fs.h>
 #include "the_nilfs.h"
-#include "sb.h"
 #include "bmap.h"
 
 /*
@@ -122,7 +121,7 @@ enum {
 #define NILFS_SYS_INO_BITS   \
   ((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS)
 
-#define NILFS_FIRST_INO(sb)  (NILFS_SB(sb)->s_nilfs->ns_first_ino)
+#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
 
 #define NILFS_MDT_INODE(sb, ino) \
   ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino))))
@@ -212,6 +211,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
 
 #define NILFS_ATIME_DISABLE
 
+/* Flags that should be inherited by new inodes from their parent. */
+#define NILFS_FL_INHERITED                                             \
+       (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL |          \
+        FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\
+        FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL)
+
+/* Mask out flags that are inappropriate for the given type of inode. */
+static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags)
+{
+       if (S_ISDIR(mode))
+               return flags;
+       else if (S_ISREG(mode))
+               return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL);
+       else
+               return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
+}
+
 /* dir.c */
 extern int nilfs_add_link(struct dentry *, struct inode *);
 extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int);
 
 /* ioctl.c */
 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
+long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
                                       void **);
 
 /* inode.c */
+void nilfs_inode_add_blocks(struct inode *inode, int n);
+void nilfs_inode_sub_blocks(struct inode *inode, int n);
 extern struct inode *nilfs_new_inode(struct inode *, int);
 extern void nilfs_free_inode(struct inode *);
 extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
@@ -275,11 +294,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *,
                                             struct nilfs_super_block *);
 extern void nilfs_set_log_cursor(struct nilfs_super_block *,
                                 struct the_nilfs *);
-extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
-                                                     int flip);
-extern int nilfs_commit_super(struct nilfs_sb_info *, int);
-extern int nilfs_cleanup_super(struct nilfs_sb_info *);
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
+                                              int flip);
+int nilfs_commit_super(struct super_block *sb, int flag);
+int nilfs_cleanup_super(struct super_block *sb);
+int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
                            struct nilfs_root **root);
 int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
 
index 3dfcd3b7d3891a030ea8dd7a01c0a51a73aea0bf..ba4a64518f389d6dcad64830050d4fdf635746a8 100644 (file)
@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
 }
 
 static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
-                                             struct nilfs_sb_info *sbi,
+                                             struct super_block *sb,
                                              struct nilfs_recovery_info *ri)
 {
        struct list_head *head = &ri->ri_used_segments;
@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
 }
 
 static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
-                                     struct nilfs_sb_info *sbi,
+                                     struct super_block *sb,
                                      struct nilfs_root *root,
                                      struct list_head *head,
                                      unsigned long *nr_salvaged_blocks)
@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
        int err = 0, err2 = 0;
 
        list_for_each_entry_safe(rb, n, head, list) {
-               inode = nilfs_iget(sbi->s_super, root, rb->ino);
+               inode = nilfs_iget(sb, root, rb->ino);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        inode = NULL;
@@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
  * nilfs_do_roll_forward - salvage logical segments newer than the latest
  * checkpoint
  * @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
  * @ri: pointer to a nilfs_recovery_info
  */
 static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
-                                struct nilfs_sb_info *sbi,
+                                struct super_block *sb,
                                 struct nilfs_root *root,
                                 struct nilfs_recovery_info *ri)
 {
@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
                                goto failed;
                        if (flags & NILFS_SS_LOGEND) {
                                err = nilfs_recover_dsync_blocks(
-                                       nilfs, sbi, root, &dsync_blocks,
+                                       nilfs, sb, root, &dsync_blocks,
                                        &nsalvaged_blocks);
                                if (unlikely(err))
                                        goto failed;
@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 
        if (nsalvaged_blocks) {
                printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
-                      sbi->s_super->s_id, nsalvaged_blocks);
+                      sb->s_id, nsalvaged_blocks);
                ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
        }
  out:
@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
        printk(KERN_ERR
               "NILFS (device %s): Error roll-forwarding "
               "(err=%d, pseg block=%llu). ",
-              sbi->s_super->s_id, err, (unsigned long long)pseg_start);
+              sb->s_id, err, (unsigned long long)pseg_start);
        goto out;
 }
 
@@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
 /**
  * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
  * @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
  * @ri: pointer to a nilfs_recovery_info struct to store search results.
  *
  * Return Value: On success, 0 is returned.  On error, one of the following
@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
  * %-ENOMEM - Insufficient memory available.
  */
 int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
-                             struct nilfs_sb_info *sbi,
+                             struct super_block *sb,
                              struct nilfs_recovery_info *ri)
 {
        struct nilfs_root *root;
@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
        if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
                return 0;
 
-       err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root);
+       err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
        if (unlikely(err)) {
                printk(KERN_ERR
                       "NILFS: error loading the latest checkpoint.\n");
                return err;
        }
 
-       err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
+       err = nilfs_do_roll_forward(nilfs, sb, root, ri);
        if (unlikely(err))
                goto failed;
 
        if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
-               err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri);
+               err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
                if (unlikely(err)) {
                        printk(KERN_ERR "NILFS: Error preparing segments for "
                               "recovery.\n");
                        goto failed;
                }
 
-               err = nilfs_attach_segment_constructor(sbi, root);
+               err = nilfs_attach_log_writer(sb, root);
                if (unlikely(err))
                        goto failed;
 
                set_nilfs_discontinued(nilfs);
-               err = nilfs_construct_segment(sbi->s_super);
-               nilfs_detach_segment_constructor(sbi);
+               err = nilfs_construct_segment(sb);
+               nilfs_detach_log_writer(sb);
 
                if (unlikely(err)) {
                        printk(KERN_ERR "NILFS: Oops! recovery failed. "
diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h
deleted file mode 100644 (file)
index 7a17715..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * sb.h - NILFS on-memory super block structure.
- *
- * Copyright (C) 2005-2008 Nippon Telegraph and Telephone 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Written by Ryusuke Konishi <ryusuke@osrg.net>
- *
- */
-
-#ifndef _NILFS_SB
-#define _NILFS_SB
-
-#include <linux/types.h>
-#include <linux/fs.h>
-
-struct the_nilfs;
-struct nilfs_sc_info;
-
-/*
- * NILFS super-block data in memory
- */
-struct nilfs_sb_info {
-       /* Mount options */
-       unsigned long s_mount_opt;
-       uid_t s_resuid;
-       gid_t s_resgid;
-
-       unsigned long s_interval;       /* construction interval */
-       unsigned long s_watermark;      /* threshold of data amount
-                                          for the segment construction */
-
-       /* Fundamental members */
-       struct super_block *s_super;    /* reverse pointer to super_block */
-       struct the_nilfs *s_nilfs;
-
-       /* Segment constructor */
-       struct list_head s_dirty_files; /* dirty files list */
-       struct nilfs_sc_info *s_sc_info; /* segment constructor info */
-       spinlock_t s_inode_lock;        /* Lock for the nilfs inode.
-                                          It covers s_dirty_files list */
-
-       /* Inode allocator */
-       spinlock_t s_next_gen_lock;
-       u32 s_next_generation;
-};
-
-static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb)
-{
-       return sb->s_fs_info;
-}
-
-static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi)
-{
-       return sbi->s_sc_info;
-}
-
-/*
- * Bit operations for the mount option
- */
-#define nilfs_clear_opt(sbi, opt)  \
-       do { (sbi)->s_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
-#define nilfs_set_opt(sbi, opt)  \
-       do { (sbi)->s_mount_opt |= NILFS_MOUNT_##opt; } while (0)
-#define nilfs_test_opt(sbi, opt)   ((sbi)->s_mount_opt & NILFS_MOUNT_##opt)
-#define nilfs_write_opt(sbi, mask, opt)                                        \
-       do { (sbi)->s_mount_opt =                                       \
-               (((sbi)->s_mount_opt & ~NILFS_MOUNT_##mask) |           \
-                NILFS_MOUNT_##opt);                                    \
-       } while (0)
-
-#endif /* _NILFS_SB */
index 2de9f636792a7545290bbd95ce90b80f28345063..afe4f2183454d49a4be19b902c200b1922ebcc4e 100644 (file)
@@ -104,8 +104,7 @@ struct nilfs_sc_operations {
 static void nilfs_segctor_start_timer(struct nilfs_sc_info *);
 static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);
 static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *);
-static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *,
-                              int);
+static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
 
 #define nilfs_cnt32_gt(a, b)   \
        (typecheck(__u32, a) && typecheck(__u32, b) && \
@@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb,
                            struct nilfs_transaction_info *ti,
                            int vacancy_check)
 {
-       struct nilfs_sb_info *sbi;
        struct the_nilfs *nilfs;
        int ret = nilfs_prepare_segment_lock(ti);
 
@@ -193,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb,
 
        vfs_check_frozen(sb, SB_FREEZE_WRITE);
 
-       sbi = NILFS_SB(sb);
-       nilfs = sbi->s_nilfs;
+       nilfs = sb->s_fs_info;
        down_read(&nilfs->ns_segctor_sem);
        if (vacancy_check && nilfs_near_disk_full(nilfs)) {
                up_read(&nilfs->ns_segctor_sem);
@@ -225,8 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb,
 int nilfs_transaction_commit(struct super_block *sb)
 {
        struct nilfs_transaction_info *ti = current->journal_info;
-       struct nilfs_sb_info *sbi;
-       struct nilfs_sc_info *sci;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        int err = 0;
 
        BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
@@ -235,16 +231,15 @@ int nilfs_transaction_commit(struct super_block *sb)
                ti->ti_count--;
                return 0;
        }
-       sbi = NILFS_SB(sb);
-       sci = NILFS_SC(sbi);
-       if (sci != NULL) {
+       if (nilfs->ns_writer) {
+               struct nilfs_sc_info *sci = nilfs->ns_writer;
+
                if (ti->ti_flags & NILFS_TI_COMMIT)
                        nilfs_segctor_start_timer(sci);
-               if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) >
-                   sci->sc_watermark)
+               if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)
                        nilfs_segctor_do_flush(sci, 0);
        }
-       up_read(&sbi->s_nilfs->ns_segctor_sem);
+       up_read(&nilfs->ns_segctor_sem);
        current->journal_info = ti->ti_save;
 
        if (ti->ti_flags & NILFS_TI_SYNC)
@@ -257,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb)
 void nilfs_transaction_abort(struct super_block *sb)
 {
        struct nilfs_transaction_info *ti = current->journal_info;
+       struct the_nilfs *nilfs = sb->s_fs_info;
 
        BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
        if (ti->ti_count > 0) {
                ti->ti_count--;
                return;
        }
-       up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem);
+       up_read(&nilfs->ns_segctor_sem);
 
        current->journal_info = ti->ti_save;
        if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
@@ -272,9 +268,8 @@ void nilfs_transaction_abort(struct super_block *sb)
 
 void nilfs_relax_pressure_in_lock(struct super_block *sb)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct nilfs_sc_info *sci = NILFS_SC(sbi);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
 
        if (!sci || !sci->sc_flush_request)
                return;
@@ -294,11 +289,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)
        downgrade_write(&nilfs->ns_segctor_sem);
 }
 
-static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
+static void nilfs_transaction_lock(struct super_block *sb,
                                   struct nilfs_transaction_info *ti,
                                   int gcflag)
 {
        struct nilfs_transaction_info *cur_ti = current->journal_info;
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
 
        WARN_ON(cur_ti);
        ti->ti_flags = NILFS_TI_WRITER;
@@ -309,30 +306,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
        current->journal_info = ti;
 
        for (;;) {
-               down_write(&sbi->s_nilfs->ns_segctor_sem);
-               if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags))
+               down_write(&nilfs->ns_segctor_sem);
+               if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))
                        break;
 
-               nilfs_segctor_do_immediate_flush(NILFS_SC(sbi));
+               nilfs_segctor_do_immediate_flush(sci);
 
-               up_write(&sbi->s_nilfs->ns_segctor_sem);
+               up_write(&nilfs->ns_segctor_sem);
                yield();
        }
        if (gcflag)
                ti->ti_flags |= NILFS_TI_GC;
 }
 
-static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi)
+static void nilfs_transaction_unlock(struct super_block *sb)
 {
        struct nilfs_transaction_info *ti = current->journal_info;
+       struct the_nilfs *nilfs = sb->s_fs_info;
 
        BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
        BUG_ON(ti->ti_count > 0);
 
-       up_write(&sbi->s_nilfs->ns_segctor_sem);
+       up_write(&nilfs->ns_segctor_sem);
        current->journal_info = ti->ti_save;
        if (!list_empty(&ti->ti_garbage))
-               nilfs_dispose_list(sbi, &ti->ti_garbage, 0);
+               nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
 }
 
 static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
@@ -714,7 +712,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,
        }
 }
 
-static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
+static void nilfs_dispose_list(struct the_nilfs *nilfs,
                               struct list_head *head, int force)
 {
        struct nilfs_inode_info *ii, *n;
@@ -722,7 +720,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
        unsigned nv = 0;
 
        while (!list_empty(head)) {
-               spin_lock(&sbi->s_inode_lock);
+               spin_lock(&nilfs->ns_inode_lock);
                list_for_each_entry_safe(ii, n, head, i_dirty) {
                        list_del_init(&ii->i_dirty);
                        if (force) {
@@ -733,14 +731,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
                        } else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) {
                                set_bit(NILFS_I_QUEUED, &ii->i_state);
                                list_add_tail(&ii->i_dirty,
-                                             &sbi->s_dirty_files);
+                                             &nilfs->ns_dirty_files);
                                continue;
                        }
                        ivec[nv++] = ii;
                        if (nv == SC_N_INODEVEC)
                                break;
                }
-               spin_unlock(&sbi->s_inode_lock);
+               spin_unlock(&nilfs->ns_inode_lock);
 
                for (pii = ivec; nv > 0; pii++, nv--)
                        iput(&(*pii)->vfs_inode);
@@ -773,24 +771,23 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_confirm(struct nilfs_sc_info *sci)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        int ret = 0;
 
-       if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root))
+       if (nilfs_test_metadata_dirty(nilfs, sci->sc_root))
                set_bit(NILFS_SC_DIRTY, &sci->sc_flags);
 
-       spin_lock(&sbi->s_inode_lock);
-       if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci))
+       spin_lock(&nilfs->ns_inode_lock);
+       if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci))
                ret++;
 
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
        return ret;
 }
 
 static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 
        nilfs_mdt_clear_dirty(sci->sc_root->ifile);
        nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
@@ -800,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
 {
-       struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        struct buffer_head *bh_cp;
        struct nilfs_checkpoint *raw_cp;
        int err;
@@ -824,8 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        struct buffer_head *bh_cp;
        struct nilfs_checkpoint *raw_cp;
        int err;
@@ -1049,8 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci,
 
 static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        struct list_head *head;
        struct nilfs_inode_info *ii;
        size_t ndone;
@@ -1859,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
 {
        struct nilfs_segment_buffer *segbuf;
        struct page *bd_page = NULL, *fs_page = NULL;
-       struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        int update_sr = false;
 
        list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) {
@@ -1963,30 +1958,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci)
        return ret;
 }
 
-static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
-                                       struct nilfs_sb_info *sbi)
+static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
+                                            struct the_nilfs *nilfs)
 {
        struct nilfs_inode_info *ii, *n;
        struct inode *ifile = sci->sc_root->ifile;
 
-       spin_lock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
  retry:
-       list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) {
+       list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) {
                if (!ii->i_bh) {
                        struct buffer_head *ibh;
                        int err;
 
-                       spin_unlock(&sbi->s_inode_lock);
+                       spin_unlock(&nilfs->ns_inode_lock);
                        err = nilfs_ifile_get_inode_block(
                                ifile, ii->vfs_inode.i_ino, &ibh);
                        if (unlikely(err)) {
-                               nilfs_warning(sbi->s_super, __func__,
+                               nilfs_warning(sci->sc_super, __func__,
                                              "failed to get inode block.\n");
                                return err;
                        }
                        nilfs_mdt_mark_buffer_dirty(ibh);
                        nilfs_mdt_mark_dirty(ifile);
-                       spin_lock(&sbi->s_inode_lock);
+                       spin_lock(&nilfs->ns_inode_lock);
                        if (likely(!ii->i_bh))
                                ii->i_bh = ibh;
                        else
@@ -1999,18 +1994,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
                list_del(&ii->i_dirty);
                list_add_tail(&ii->i_dirty, &sci->sc_dirty_files);
        }
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
 
        return 0;
 }
 
-static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
-                                         struct nilfs_sb_info *sbi)
+static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
+                                            struct the_nilfs *nilfs)
 {
        struct nilfs_transaction_info *ti = current->journal_info;
        struct nilfs_inode_info *ii, *n;
 
-       spin_lock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
        list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
                if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) ||
                    test_bit(NILFS_I_DIRTY, &ii->i_state))
@@ -2022,7 +2017,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
                list_del(&ii->i_dirty);
                list_add_tail(&ii->i_dirty, &ti->ti_garbage);
        }
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
 }
 
 /*
@@ -2030,15 +2025,14 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
  */
 static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        struct page *failed_page;
        int err;
 
        sci->sc_stage.scnt = NILFS_ST_INIT;
        sci->sc_cno = nilfs->ns_cno;
 
-       err = nilfs_segctor_check_in_files(sci, sbi);
+       err = nilfs_segctor_collect_dirty_files(sci, nilfs);
        if (unlikely(err))
                goto out;
 
@@ -2116,7 +2110,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
        } while (sci->sc_stage.scnt != NILFS_ST_DONE);
 
  out:
-       nilfs_segctor_check_out_files(sci, sbi);
+       nilfs_segctor_drop_written_files(sci, nilfs);
        return err;
 
  failed_to_write:
@@ -2169,8 +2163,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn)
  */
 void nilfs_flush_segment(struct super_block *sb, ino_t ino)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct nilfs_sc_info *sci = NILFS_SC(sbi);
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
 
        if (!sci || nilfs_doing_construction())
                return;
@@ -2259,8 +2253,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
  */
 int nilfs_construct_segment(struct super_block *sb)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct nilfs_sc_info *sci = NILFS_SC(sbi);
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
        struct nilfs_transaction_info *ti;
        int err;
 
@@ -2297,8 +2291,8 @@ int nilfs_construct_segment(struct super_block *sb)
 int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
                                  loff_t start, loff_t end)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct nilfs_sc_info *sci = NILFS_SC(sbi);
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
        struct nilfs_inode_info *ii;
        struct nilfs_transaction_info ti;
        int err = 0;
@@ -2306,33 +2300,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
        if (!sci)
                return -EROFS;
 
-       nilfs_transaction_lock(sbi, &ti, 0);
+       nilfs_transaction_lock(sb, &ti, 0);
 
        ii = NILFS_I(inode);
        if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) ||
-           nilfs_test_opt(sbi, STRICT_ORDER) ||
+           nilfs_test_opt(nilfs, STRICT_ORDER) ||
            test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) ||
-           nilfs_discontinued(sbi->s_nilfs)) {
-               nilfs_transaction_unlock(sbi);
+           nilfs_discontinued(nilfs)) {
+               nilfs_transaction_unlock(sb);
                err = nilfs_segctor_sync(sci);
                return err;
        }
 
-       spin_lock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
        if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
            !test_bit(NILFS_I_BUSY, &ii->i_state)) {
-               spin_unlock(&sbi->s_inode_lock);
-               nilfs_transaction_unlock(sbi);
+               spin_unlock(&nilfs->ns_inode_lock);
+               nilfs_transaction_unlock(sb);
                return 0;
        }
-       spin_unlock(&sbi->s_inode_lock);
+       spin_unlock(&nilfs->ns_inode_lock);
        sci->sc_dsync_inode = ii;
        sci->sc_dsync_start = start;
        sci->sc_dsync_end = end;
 
        err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
 
-       nilfs_transaction_unlock(sbi);
+       nilfs_transaction_unlock(sb);
        return err;
 }
 
@@ -2388,8 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
  */
 static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        struct nilfs_super_block **sbp;
        int err = 0;
 
@@ -2407,11 +2400,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
                    nilfs_discontinued(nilfs)) {
                        down_write(&nilfs->ns_sem);
                        err = -EIO;
-                       sbp = nilfs_prepare_super(sbi,
+                       sbp = nilfs_prepare_super(sci->sc_super,
                                                  nilfs_sb_will_flip(nilfs));
                        if (likely(sbp)) {
                                nilfs_set_log_cursor(sbp[0], nilfs);
-                               err = nilfs_commit_super(sbi, NILFS_SB_COMMIT);
+                               err = nilfs_commit_super(sci->sc_super,
+                                                        NILFS_SB_COMMIT);
                        }
                        up_write(&nilfs->ns_sem);
                }
@@ -2443,16 +2437,15 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
 int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
                         void **kbufs)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct nilfs_sc_info *sci = NILFS_SC(sbi);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
+       struct nilfs_sc_info *sci = nilfs->ns_writer;
        struct nilfs_transaction_info ti;
        int err;
 
        if (unlikely(!sci))
                return -EROFS;
 
-       nilfs_transaction_lock(sbi, &ti, 1);
+       nilfs_transaction_lock(sb, &ti, 1);
 
        err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
        if (unlikely(err))
@@ -2480,14 +2473,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(sci->sc_interval);
        }
-       if (nilfs_test_opt(sbi, DISCARD)) {
+       if (nilfs_test_opt(nilfs, DISCARD)) {
                int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,
                                                 sci->sc_nfreesegs);
                if (ret) {
                        printk(KERN_WARNING
                               "NILFS warning: error %d on discard request, "
                               "turning discards off for the device\n", ret);
-                       nilfs_clear_opt(sbi, DISCARD);
+                       nilfs_clear_opt(nilfs, DISCARD);
                }
        }
 
@@ -2495,16 +2488,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
        sci->sc_freesegs = NULL;
        sci->sc_nfreesegs = 0;
        nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
-       nilfs_transaction_unlock(sbi);
+       nilfs_transaction_unlock(sb);
        return err;
 }
 
 static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
        struct nilfs_transaction_info ti;
 
-       nilfs_transaction_lock(sbi, &ti, 0);
+       nilfs_transaction_lock(sci->sc_super, &ti, 0);
        nilfs_segctor_construct(sci, mode);
 
        /*
@@ -2515,7 +2507,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
        if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags))
                nilfs_segctor_start_timer(sci);
 
-       nilfs_transaction_unlock(sbi);
+       nilfs_transaction_unlock(sci->sc_super);
 }
 
 static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci)
@@ -2561,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)
 static int nilfs_segctor_thread(void *arg)
 {
        struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg;
-       struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        int timeout = 0;
 
        sci->sc_timer.data = (unsigned long)current;
@@ -2672,17 +2664,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)
 /*
  * Setup & clean-up functions
  */
-static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,
+static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
                                               struct nilfs_root *root)
 {
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_sc_info *sci;
 
        sci = kzalloc(sizeof(*sci), GFP_KERNEL);
        if (!sci)
                return NULL;
 
-       sci->sc_sbi = sbi;
-       sci->sc_super = sbi->s_super;
+       sci->sc_super = sb;
 
        nilfs_get_root(root);
        sci->sc_root = root;
@@ -2702,10 +2694,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,
        sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;
        sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK;
 
-       if (sbi->s_interval)
-               sci->sc_interval = sbi->s_interval;
-       if (sbi->s_watermark)
-               sci->sc_watermark = sbi->s_watermark;
+       if (nilfs->ns_interval)
+               sci->sc_interval = nilfs->ns_interval;
+       if (nilfs->ns_watermark)
+               sci->sc_watermark = nilfs->ns_watermark;
        return sci;
 }
 
@@ -2716,12 +2708,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
        /* The segctord thread was stopped and its timer was removed.
           But some tasks remain. */
        do {
-               struct nilfs_sb_info *sbi = sci->sc_sbi;
                struct nilfs_transaction_info ti;
 
-               nilfs_transaction_lock(sbi, &ti, 0);
+               nilfs_transaction_lock(sci->sc_super, &ti, 0);
                ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
-               nilfs_transaction_unlock(sbi);
+               nilfs_transaction_unlock(sci->sc_super);
 
        } while (ret && retrycount-- > 0);
 }
@@ -2736,10 +2727,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
  */
 static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 {
-       struct nilfs_sb_info *sbi = sci->sc_sbi;
+       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
        int flag;
 
-       up_write(&sbi->s_nilfs->ns_segctor_sem);
+       up_write(&nilfs->ns_segctor_sem);
 
        spin_lock(&sci->sc_state_lock);
        nilfs_segctor_kill_thread(sci);
@@ -2753,9 +2744,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
        WARN_ON(!list_empty(&sci->sc_copied_buffers));
 
        if (!list_empty(&sci->sc_dirty_files)) {
-               nilfs_warning(sbi->s_super, __func__,
+               nilfs_warning(sci->sc_super, __func__,
                              "dirty file(s) after the final construction\n");
-               nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1);
+               nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
        }
 
        WARN_ON(!list_empty(&sci->sc_segbufs));
@@ -2763,79 +2754,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 
        nilfs_put_root(sci->sc_root);
 
-       down_write(&sbi->s_nilfs->ns_segctor_sem);
+       down_write(&nilfs->ns_segctor_sem);
 
        del_timer_sync(&sci->sc_timer);
        kfree(sci);
 }
 
 /**
- * nilfs_attach_segment_constructor - attach a segment constructor
- * @sbi: nilfs_sb_info
+ * nilfs_attach_log_writer - attach log writer
+ * @sb: super block instance
  * @root: root object of the current filesystem tree
  *
- * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info,
- * initializes it, and starts the segment constructor.
+ * This allocates a log writer object, initializes it, and starts the
+ * log writer.
  *
  * Return Value: On success, 0 is returned. On error, one of the following
  * negative error code is returned.
  *
  * %-ENOMEM - Insufficient memory available.
  */
-int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
-                                    struct nilfs_root *root)
+int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)
 {
+       struct the_nilfs *nilfs = sb->s_fs_info;
        int err;
 
-       if (NILFS_SC(sbi)) {
+       if (nilfs->ns_writer) {
                /*
                 * This happens if the filesystem was remounted
                 * read/write after nilfs_error degenerated it into a
                 * read-only mount.
                 */
-               nilfs_detach_segment_constructor(sbi);
+               nilfs_detach_log_writer(sb);
        }
 
-       sbi->s_sc_info = nilfs_segctor_new(sbi, root);
-       if (!sbi->s_sc_info)
+       nilfs->ns_writer = nilfs_segctor_new(sb, root);
+       if (!nilfs->ns_writer)
                return -ENOMEM;
 
-       err = nilfs_segctor_start_thread(NILFS_SC(sbi));
+       err = nilfs_segctor_start_thread(nilfs->ns_writer);
        if (err) {
-               kfree(sbi->s_sc_info);
-               sbi->s_sc_info = NULL;
+               kfree(nilfs->ns_writer);
+               nilfs->ns_writer = NULL;
        }
        return err;
 }
 
 /**
- * nilfs_detach_segment_constructor - destroy the segment constructor
- * @sbi: nilfs_sb_info
+ * nilfs_detach_log_writer - destroy log writer
+ * @sb: super block instance
  *
- * nilfs_detach_segment_constructor() kills the segment constructor daemon,
- * frees the struct nilfs_sc_info, and destroy the dirty file list.
+ * This kills log writer daemon, frees the log writer object, and
+ * destroys list of dirty files.
  */
-void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi)
+void nilfs_detach_log_writer(struct super_block *sb)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        LIST_HEAD(garbage_list);
 
        down_write(&nilfs->ns_segctor_sem);
-       if (NILFS_SC(sbi)) {
-               nilfs_segctor_destroy(NILFS_SC(sbi));
-               sbi->s_sc_info = NULL;
+       if (nilfs->ns_writer) {
+               nilfs_segctor_destroy(nilfs->ns_writer);
+               nilfs->ns_writer = NULL;
        }
 
        /* Force to free the list of dirty files */
-       spin_lock(&sbi->s_inode_lock);
-       if (!list_empty(&sbi->s_dirty_files)) {
-               list_splice_init(&sbi->s_dirty_files, &garbage_list);
-               nilfs_warning(sbi->s_super, __func__,
-                             "Non empty dirty list after the last "
-                             "segment construction\n");
-       }
-       spin_unlock(&sbi->s_inode_lock);
+       spin_lock(&nilfs->ns_inode_lock);
+       if (!list_empty(&nilfs->ns_dirty_files)) {
+               list_splice_init(&nilfs->ns_dirty_files, &garbage_list);
+               nilfs_warning(sb, __func__,
+                             "Hit dirty file after stopped log writer\n");
+       }
+       spin_unlock(&nilfs->ns_inode_lock);
        up_write(&nilfs->ns_segctor_sem);
 
-       nilfs_dispose_list(sbi, &garbage_list, 1);
+       nilfs_dispose_list(nilfs, &garbage_list, 1);
 }
index cd8056e7cbed076ecdfb63284b7a97149a4c5003..6c02a86745fb19417d093da0af0ed205ac00a1a7 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/nilfs2_fs.h>
-#include "sb.h"
+#include "nilfs.h"
 
 struct nilfs_root;
 
@@ -88,7 +88,6 @@ struct nilfs_segsum_pointer {
 /**
  * struct nilfs_sc_info - Segment constructor information
  * @sc_super: Back pointer to super_block struct
- * @sc_sbi: Back pointer to nilfs_sb_info struct
  * @sc_root: root object of the current filesystem tree
  * @sc_nblk_inc: Block count of current generation
  * @sc_dirty_files: List of files to be written
@@ -131,7 +130,6 @@ struct nilfs_segsum_pointer {
  */
 struct nilfs_sc_info {
        struct super_block     *sc_super;
-       struct nilfs_sb_info   *sc_sbi;
        struct nilfs_root      *sc_root;
 
        unsigned long           sc_nblk_inc;
@@ -235,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t);
 extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
                                void **);
 
-int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
-                                    struct nilfs_root *root);
-extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
+int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root);
+void nilfs_detach_log_writer(struct super_block *sb);
 
 /* recovery.c */
 extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t,
                                       struct buffer_head **, int);
 extern int nilfs_search_super_root(struct the_nilfs *,
                                   struct nilfs_recovery_info *);
-extern int nilfs_salvage_orphan_logs(struct the_nilfs *,
-                                    struct nilfs_sb_info *,
-                                    struct nilfs_recovery_info *);
+int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb,
+                             struct nilfs_recovery_info *ri);
 extern void nilfs_dispose_segment_list(struct list_head *);
 
 #endif /* _NILFS_SEGMENT_H */
index 1673b3d99842018206640c77ea9922840c5a2bc4..062cca065195ea7f430f45cf9259896be44be788 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/parser.h>
-#include <linux/random.h>
 #include <linux/crc32.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
@@ -72,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep;
 struct kmem_cache *nilfs_segbuf_cachep;
 struct kmem_cache *nilfs_btree_path_cache;
 
-static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount);
+static int nilfs_setup_super(struct super_block *sb, int is_mount);
 static int nilfs_remount(struct super_block *sb, int *flags, char *data);
 
-static void nilfs_set_error(struct nilfs_sb_info *sbi)
+static void nilfs_set_error(struct super_block *sb)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp;
 
        down_write(&nilfs->ns_sem);
        if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
                nilfs->ns_mount_state |= NILFS_ERROR_FS;
-               sbp = nilfs_prepare_super(sbi, 0);
+               sbp = nilfs_prepare_super(sb, 0);
                if (likely(sbp)) {
                        sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
                        if (sbp[1])
                                sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
-                       nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
+                       nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
                }
        }
        up_write(&nilfs->ns_sem);
@@ -109,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi)
 void nilfs_error(struct super_block *sb, const char *function,
                 const char *fmt, ...)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct va_format vaf;
        va_list args;
 
@@ -124,15 +123,15 @@ void nilfs_error(struct super_block *sb, const char *function,
        va_end(args);
 
        if (!(sb->s_flags & MS_RDONLY)) {
-               nilfs_set_error(sbi);
+               nilfs_set_error(sb);
 
-               if (nilfs_test_opt(sbi, ERRORS_RO)) {
+               if (nilfs_test_opt(nilfs, ERRORS_RO)) {
                        printk(KERN_CRIT "Remounting filesystem read-only\n");
                        sb->s_flags |= MS_RDONLY;
                }
        }
 
-       if (nilfs_test_opt(sbi, ERRORS_PANIC))
+       if (nilfs_test_opt(nilfs, ERRORS_PANIC))
                panic("NILFS (device %s): panic forced after error\n",
                      sb->s_id);
 }
@@ -189,14 +188,14 @@ void nilfs_destroy_inode(struct inode *inode)
        call_rcu(&inode->i_rcu, nilfs_i_callback);
 }
 
-static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag)
+static int nilfs_sync_super(struct super_block *sb, int flag)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        int err;
 
  retry:
        set_buffer_dirty(nilfs->ns_sbh[0]);
-       if (nilfs_test_opt(sbi, BARRIER)) {
+       if (nilfs_test_opt(nilfs, BARRIER)) {
                err = __sync_dirty_buffer(nilfs->ns_sbh[0],
                                          WRITE_SYNC | WRITE_FLUSH_FUA);
        } else {
@@ -263,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp,
        spin_unlock(&nilfs->ns_last_segment_lock);
 }
 
-struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
+struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
                                               int flip)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp = nilfs->ns_sbp;
 
        /* nilfs->ns_sem must be locked by the caller. */
@@ -276,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
                        memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
                } else {
                        printk(KERN_CRIT "NILFS: superblock broke on dev %s\n",
-                              sbi->s_super->s_id);
+                              sb->s_id);
                        return NULL;
                }
        } else if (sbp[1] &&
@@ -290,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
        return sbp;
 }
 
-int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
+int nilfs_commit_super(struct super_block *sb, int flag)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp = nilfs->ns_sbp;
        time_t t;
 
@@ -312,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
                                            nilfs->ns_sbsize));
        }
        clear_nilfs_sb_dirty(nilfs);
-       return nilfs_sync_super(sbi, flag);
+       return nilfs_sync_super(sb, flag);
 }
 
 /**
  * nilfs_cleanup_super() - write filesystem state for cleanup
- * @sbi: nilfs_sb_info to be unmounted or degraded to read-only
+ * @sb: super block instance to be unmounted or degraded to read-only
  *
  * This function restores state flags in the on-disk super block.
  * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the
  * filesystem was not clean previously.
  */
-int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
+int nilfs_cleanup_super(struct super_block *sb)
 {
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp;
        int flag = NILFS_SB_COMMIT;
        int ret = -EIO;
 
-       sbp = nilfs_prepare_super(sbi, 0);
+       sbp = nilfs_prepare_super(sb, 0);
        if (sbp) {
-               sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state);
-               nilfs_set_log_cursor(sbp[0], sbi->s_nilfs);
+               sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
+               nilfs_set_log_cursor(sbp[0], nilfs);
                if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) {
                        /*
                         * make the "clean" flag also to the opposite
@@ -342,21 +342,20 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
                        sbp[1]->s_state = sbp[0]->s_state;
                        flag = NILFS_SB_COMMIT_ALL;
                }
-               ret = nilfs_commit_super(sbi, flag);
+               ret = nilfs_commit_super(sb, flag);
        }
        return ret;
 }
 
 static void nilfs_put_super(struct super_block *sb)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
 
-       nilfs_detach_segment_constructor(sbi);
+       nilfs_detach_log_writer(sb);
 
        if (!(sb->s_flags & MS_RDONLY)) {
                down_write(&nilfs->ns_sem);
-               nilfs_cleanup_super(sbi);
+               nilfs_cleanup_super(sb);
                up_write(&nilfs->ns_sem);
        }
 
@@ -365,15 +364,12 @@ static void nilfs_put_super(struct super_block *sb)
        iput(nilfs->ns_dat);
 
        destroy_nilfs(nilfs);
-       sbi->s_super = NULL;
        sb->s_fs_info = NULL;
-       kfree(sbi);
 }
 
 static int nilfs_sync_fs(struct super_block *sb, int wait)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp;
        int err = 0;
 
@@ -383,10 +379,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
 
        down_write(&nilfs->ns_sem);
        if (nilfs_sb_dirty(nilfs)) {
-               sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs));
+               sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs));
                if (likely(sbp)) {
                        nilfs_set_log_cursor(sbp[0], nilfs);
-                       nilfs_commit_super(sbi, NILFS_SB_COMMIT);
+                       nilfs_commit_super(sb, NILFS_SB_COMMIT);
                }
        }
        up_write(&nilfs->ns_sem);
@@ -394,10 +390,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
        return err;
 }
 
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
                            struct nilfs_root **rootp)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_root *root;
        struct nilfs_checkpoint *raw_cp;
        struct buffer_head *bh_cp;
@@ -426,7 +422,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
                goto failed;
        }
 
-       err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size,
+       err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size,
                               &raw_cp->cp_ifile_inode, &root->ifile);
        if (err)
                goto failed_bh;
@@ -450,8 +446,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
 
 static int nilfs_freeze(struct super_block *sb)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        int err;
 
        if (sb->s_flags & MS_RDONLY)
@@ -459,21 +454,20 @@ static int nilfs_freeze(struct super_block *sb)
 
        /* Mark super block clean */
        down_write(&nilfs->ns_sem);
-       err = nilfs_cleanup_super(sbi);
+       err = nilfs_cleanup_super(sb);
        up_write(&nilfs->ns_sem);
        return err;
 }
 
 static int nilfs_unfreeze(struct super_block *sb)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
 
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
        down_write(&nilfs->ns_sem);
-       nilfs_setup_super(sbi, false);
+       nilfs_setup_super(sb, false);
        up_write(&nilfs->ns_sem);
        return 0;
 }
@@ -530,22 +524,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
        struct super_block *sb = vfs->mnt_sb;
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root;
 
-       if (!nilfs_test_opt(sbi, BARRIER))
+       if (!nilfs_test_opt(nilfs, BARRIER))
                seq_puts(seq, ",nobarrier");
        if (root->cno != NILFS_CPTREE_CURRENT_CNO)
                seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno);
-       if (nilfs_test_opt(sbi, ERRORS_PANIC))
+       if (nilfs_test_opt(nilfs, ERRORS_PANIC))
                seq_puts(seq, ",errors=panic");
-       if (nilfs_test_opt(sbi, ERRORS_CONT))
+       if (nilfs_test_opt(nilfs, ERRORS_CONT))
                seq_puts(seq, ",errors=continue");
-       if (nilfs_test_opt(sbi, STRICT_ORDER))
+       if (nilfs_test_opt(nilfs, STRICT_ORDER))
                seq_puts(seq, ",order=strict");
-       if (nilfs_test_opt(sbi, NORECOVERY))
+       if (nilfs_test_opt(nilfs, NORECOVERY))
                seq_puts(seq, ",norecovery");
-       if (nilfs_test_opt(sbi, DISCARD))
+       if (nilfs_test_opt(nilfs, DISCARD))
                seq_puts(seq, ",discard");
 
        return 0;
@@ -594,7 +588,7 @@ static match_table_t tokens = {
 
 static int parse_options(char *options, struct super_block *sb, int is_remount)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
+       struct the_nilfs *nilfs = sb->s_fs_info;
        char *p;
        substring_t args[MAX_OPT_ARGS];
 
@@ -609,29 +603,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_barrier:
-                       nilfs_set_opt(sbi, BARRIER);
+                       nilfs_set_opt(nilfs, BARRIER);
                        break;
                case Opt_nobarrier:
-                       nilfs_clear_opt(sbi, BARRIER);
+                       nilfs_clear_opt(nilfs, BARRIER);
                        break;
                case Opt_order:
                        if (strcmp(args[0].from, "relaxed") == 0)
                                /* Ordered data semantics */
-                               nilfs_clear_opt(sbi, STRICT_ORDER);
+                               nilfs_clear_opt(nilfs, STRICT_ORDER);
                        else if (strcmp(args[0].from, "strict") == 0)
                                /* Strict in-order semantics */
-                               nilfs_set_opt(sbi, STRICT_ORDER);
+                               nilfs_set_opt(nilfs, STRICT_ORDER);
                        else
                                return 0;
                        break;
                case Opt_err_panic:
-                       nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC);
+                       nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC);
                        break;
                case Opt_err_ro:
-                       nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO);
+                       nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO);
                        break;
                case Opt_err_cont:
-                       nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT);
+                       nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT);
                        break;
                case Opt_snapshot:
                        if (is_remount) {
@@ -642,13 +636,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
                        }
                        break;
                case Opt_norecovery:
-                       nilfs_set_opt(sbi, NORECOVERY);
+                       nilfs_set_opt(nilfs, NORECOVERY);
                        break;
                case Opt_discard:
-                       nilfs_set_opt(sbi, DISCARD);
+                       nilfs_set_opt(nilfs, DISCARD);
                        break;
                case Opt_nodiscard:
-                       nilfs_clear_opt(sbi, DISCARD);
+                       nilfs_clear_opt(nilfs, DISCARD);
                        break;
                default:
                        printk(KERN_ERR
@@ -660,22 +654,24 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
 }
 
 static inline void
-nilfs_set_default_options(struct nilfs_sb_info *sbi,
+nilfs_set_default_options(struct super_block *sb,
                          struct nilfs_super_block *sbp)
 {
-       sbi->s_mount_opt =
+       struct the_nilfs *nilfs = sb->s_fs_info;
+
+       nilfs->ns_mount_opt =
                NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER;
 }
 
-static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
+static int nilfs_setup_super(struct super_block *sb, int is_mount)
 {
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_super_block **sbp;
        int max_mnt_count;
        int mnt_count;
 
        /* nilfs->ns_sem must be locked by the caller. */
-       sbp = nilfs_prepare_super(sbi, 0);
+       sbp = nilfs_prepare_super(sb, 0);
        if (!sbp)
                return -EIO;
 
@@ -706,7 +702,7 @@ skip_mount_setup:
        /* synchronize sbp[1] with sbp[0] */
        if (sbp[1])
                memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
-       return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
+       return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
 }
 
 struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
@@ -727,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb,
                                 struct nilfs_super_block *sbp,
                                 char *data)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
+       struct the_nilfs *nilfs = sb->s_fs_info;
 
        sb->s_magic = le16_to_cpu(sbp->s_magic);
 
@@ -736,12 +732,12 @@ int nilfs_store_magic_and_option(struct super_block *sb,
        sb->s_flags |= MS_NOATIME;
 #endif
 
-       nilfs_set_default_options(sbi, sbp);
+       nilfs_set_default_options(sb, sbp);
 
-       sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid);
-       sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid);
-       sbi->s_interval = le32_to_cpu(sbp->s_c_interval);
-       sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max);
+       nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid);
+       nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid);
+       nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval);
+       nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max);
 
        return !parse_options(data, sb, 0) ? -EINVAL : 0 ;
 }
@@ -822,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb,
 static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
                                 struct dentry **root_dentry)
 {
-       struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs;
+       struct the_nilfs *nilfs = s->s_fs_info;
        struct nilfs_root *root;
        int ret;
 
@@ -840,7 +836,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
                goto out;
        }
 
-       ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root);
+       ret = nilfs_attach_checkpoint(s, cno, false, &root);
        if (ret) {
                printk(KERN_ERR "NILFS: error loading snapshot "
                       "(checkpoint number=%llu).\n",
@@ -874,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry)
 
 int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
 {
-       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        struct nilfs_root *root;
        struct inode *inode;
        struct dentry *dentry;
@@ -887,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
                return true;    /* protect recent checkpoints */
 
        ret = false;
-       root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+       root = nilfs_lookup_root(nilfs, cno);
        if (root) {
                inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
                if (inode) {
@@ -917,43 +913,21 @@ static int
 nilfs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct the_nilfs *nilfs;
-       struct nilfs_sb_info *sbi;
        struct nilfs_root *fsroot;
        struct backing_dev_info *bdi;
        __u64 cno;
        int err;
 
-       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-       if (!sbi)
+       nilfs = alloc_nilfs(sb->s_bdev);
+       if (!nilfs)
                return -ENOMEM;
 
-       sb->s_fs_info = sbi;
-       sbi->s_super = sb;
-
-       nilfs = alloc_nilfs(sb->s_bdev);
-       if (!nilfs) {
-               err = -ENOMEM;
-               goto failed_sbi;
-       }
-       sbi->s_nilfs = nilfs;
+       sb->s_fs_info = nilfs;
 
-       err = init_nilfs(nilfs, sbi, (char *)data);
+       err = init_nilfs(nilfs, sb, (char *)data);
        if (err)
                goto failed_nilfs;
 
-       spin_lock_init(&sbi->s_inode_lock);
-       INIT_LIST_HEAD(&sbi->s_dirty_files);
-
-       /*
-        * Following initialization is overlapped because
-        * nilfs_sb_info structure has been cleared at the beginning.
-        * But we reserve them to keep our interest and make ready
-        * for the future change.
-        */
-       get_random_bytes(&sbi->s_next_generation,
-                        sizeof(sbi->s_next_generation));
-       spin_lock_init(&sbi->s_next_gen_lock);
-
        sb->s_op = &nilfs_sops;
        sb->s_export_op = &nilfs_export_ops;
        sb->s_root = NULL;
@@ -962,12 +936,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
        sb->s_bdi = bdi ? : &default_backing_dev_info;
 
-       err = load_nilfs(nilfs, sbi);
+       err = load_nilfs(nilfs, sb);
        if (err)
                goto failed_nilfs;
 
        cno = nilfs_last_cno(nilfs);
-       err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot);
+       err = nilfs_attach_checkpoint(sb, cno, true, &fsroot);
        if (err) {
                printk(KERN_ERR "NILFS: error loading last checkpoint "
                       "(checkpoint number=%llu).\n", (unsigned long long)cno);
@@ -975,7 +949,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        if (!(sb->s_flags & MS_RDONLY)) {
-               err = nilfs_attach_segment_constructor(sbi, fsroot);
+               err = nilfs_attach_log_writer(sb, fsroot);
                if (err)
                        goto failed_checkpoint;
        }
@@ -988,14 +962,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 
        if (!(sb->s_flags & MS_RDONLY)) {
                down_write(&nilfs->ns_sem);
-               nilfs_setup_super(sbi, true);
+               nilfs_setup_super(sb, true);
                up_write(&nilfs->ns_sem);
        }
 
        return 0;
 
  failed_segctor:
-       nilfs_detach_segment_constructor(sbi);
+       nilfs_detach_log_writer(sb);
 
  failed_checkpoint:
        nilfs_put_root(fsroot);
@@ -1007,23 +981,18 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 
  failed_nilfs:
        destroy_nilfs(nilfs);
-
- failed_sbi:
-       sb->s_fs_info = NULL;
-       kfree(sbi);
        return err;
 }
 
 static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 {
-       struct nilfs_sb_info *sbi = NILFS_SB(sb);
-       struct the_nilfs *nilfs = sbi->s_nilfs;
+       struct the_nilfs *nilfs = sb->s_fs_info;
        unsigned long old_sb_flags;
        unsigned long old_mount_opt;
        int err;
 
        old_sb_flags = sb->s_flags;
-       old_mount_opt = sbi->s_mount_opt;
+       old_mount_opt = nilfs->ns_mount_opt;
 
        if (!parse_options(data, sb, 1)) {
                err = -EINVAL;
@@ -1043,8 +1012,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                goto out;
        if (*flags & MS_RDONLY) {
-               /* Shutting down the segment constructor */
-               nilfs_detach_segment_constructor(sbi);
+               /* Shutting down log writer */
+               nilfs_detach_log_writer(sb);
                sb->s_flags |= MS_RDONLY;
 
                /*
@@ -1052,7 +1021,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
                 * the RDONLY flag and then mark the partition as valid again.
                 */
                down_write(&nilfs->ns_sem);
-               nilfs_cleanup_super(sbi);
+               nilfs_cleanup_super(sb);
                up_write(&nilfs->ns_sem);
        } else {
                __u64 features;
@@ -1079,12 +1048,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
                sb->s_flags &= ~MS_RDONLY;
 
                root = NILFS_I(sb->s_root->d_inode)->i_root;
-               err = nilfs_attach_segment_constructor(sbi, root);
+               err = nilfs_attach_log_writer(sb, root);
                if (err)
                        goto restore_opts;
 
                down_write(&nilfs->ns_sem);
-               nilfs_setup_super(sbi, true);
+               nilfs_setup_super(sb, true);
                up_write(&nilfs->ns_sem);
        }
  out:
@@ -1092,13 +1061,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 
  restore_opts:
        sb->s_flags = old_sb_flags;
-       sbi->s_mount_opt = old_mount_opt;
+       nilfs->ns_mount_opt = old_mount_opt;
        return err;
 }
 
 struct nilfs_super_data {
        struct block_device *bdev;
-       struct nilfs_sb_info *sbi;
        __u64 cno;
        int flags;
 };
index ad4ac607cf5734fda535667e898ad9b4cccaab63..d2acd1a651f31caf260d964c719fed086b43cb85 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
+#include <linux/random.h>
 #include <linux/crc32.h>
 #include "nilfs.h"
 #include "segment.h"
@@ -75,7 +76,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
        nilfs->ns_bdev = bdev;
        atomic_set(&nilfs->ns_ndirtyblks, 0);
        init_rwsem(&nilfs->ns_sem);
+       INIT_LIST_HEAD(&nilfs->ns_dirty_files);
        INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
+       spin_lock_init(&nilfs->ns_inode_lock);
+       spin_lock_init(&nilfs->ns_next_gen_lock);
        spin_lock_init(&nilfs->ns_last_segment_lock);
        nilfs->ns_cptree = RB_ROOT;
        spin_lock_init(&nilfs->ns_cptree_lock);
@@ -197,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs,
 /**
  * load_nilfs - load and recover the nilfs
  * @nilfs: the_nilfs structure to be released
- * @sbi: nilfs_sb_info used to recover past segment
+ * @sb: super block isntance used to recover past segment
  *
  * load_nilfs() searches and load the latest super root,
  * attaches the last segment, and does recovery if needed.
  * The caller must call this exclusively for simultaneous mounts.
  */
-int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
+int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
 {
        struct nilfs_recovery_info ri;
-       unsigned int s_flags = sbi->s_super->s_flags;
+       unsigned int s_flags = sb->s_flags;
        int really_read_only = bdev_read_only(nilfs->ns_bdev);
        int valid_fs = nilfs_valid_fs(nilfs);
        int err;
@@ -271,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
                        goto scan_error;
        }
 
-       err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root);
+       err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root);
        if (unlikely(err)) {
                printk(KERN_ERR "NILFS: error loading super root.\n");
                goto failed;
@@ -283,7 +287,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
        if (s_flags & MS_RDONLY) {
                __u64 features;
 
-               if (nilfs_test_opt(sbi, NORECOVERY)) {
+               if (nilfs_test_opt(nilfs, NORECOVERY)) {
                        printk(KERN_INFO "NILFS: norecovery option specified. "
                               "skipping roll-forward recovery\n");
                        goto skip_recovery;
@@ -304,21 +308,21 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
                        err = -EROFS;
                        goto failed_unload;
                }
-               sbi->s_super->s_flags &= ~MS_RDONLY;
-       } else if (nilfs_test_opt(sbi, NORECOVERY)) {
+               sb->s_flags &= ~MS_RDONLY;
+       } else if (nilfs_test_opt(nilfs, NORECOVERY)) {
                printk(KERN_ERR "NILFS: recovery cancelled because norecovery "
                       "option was specified for a read/write mount\n");
                err = -EINVAL;
                goto failed_unload;
        }
 
-       err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri);
+       err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
        if (err)
                goto failed_unload;
 
        down_write(&nilfs->ns_sem);
        nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */
-       err = nilfs_cleanup_super(sbi);
+       err = nilfs_cleanup_super(sb);
        up_write(&nilfs->ns_sem);
 
        if (err) {
@@ -330,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 
  skip_recovery:
        nilfs_clear_recovery_info(&ri);
-       sbi->s_super->s_flags = s_flags;
+       sb->s_flags = s_flags;
        return 0;
 
  scan_error:
@@ -344,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 
  failed:
        nilfs_clear_recovery_info(&ri);
-       sbi->s_super->s_flags = s_flags;
+       sb->s_flags = s_flags;
        return err;
 }
 
@@ -475,10 +479,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
                        return -EIO;
                }
                printk(KERN_WARNING
-                      "NILFS warning: unable to read primary superblock\n");
-       } else if (!sbp[1])
+                      "NILFS warning: unable to read primary superblock "
+                      "(blocksize = %d)\n", blocksize);
+       } else if (!sbp[1]) {
                printk(KERN_WARNING
-                      "NILFS warning: unable to read secondary superblock\n");
+                      "NILFS warning: unable to read secondary superblock "
+                      "(blocksize = %d)\n", blocksize);
+       }
 
        /*
         * Compare two super blocks and set 1 in swp if the secondary
@@ -505,7 +512,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 
        if (!valid[!swp])
                printk(KERN_WARNING "NILFS warning: broken superblock. "
-                      "using spare superblock.\n");
+                      "using spare superblock (blocksize = %d).\n", blocksize);
        if (swp)
                nilfs_swap_super_block(nilfs);
 
@@ -519,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 /**
  * init_nilfs - initialize a NILFS instance.
  * @nilfs: the_nilfs structure
- * @sbi: nilfs_sb_info
  * @sb: super block
  * @data: mount options
  *
@@ -530,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
  * Return Value: On success, 0 is returned. On error, a negative error
  * code is returned.
  */
-int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
+int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
 {
-       struct super_block *sb = sbi->s_super;
        struct nilfs_super_block *sbp;
        int blocksize;
        int err;
@@ -588,6 +593,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
        nilfs->ns_blocksize_bits = sb->s_blocksize_bits;
        nilfs->ns_blocksize = blocksize;
 
+       get_random_bytes(&nilfs->ns_next_generation,
+                        sizeof(nilfs->ns_next_generation));
+
        err = nilfs_store_disk_layout(nilfs, sbp);
        if (err)
                goto failed_sbh;
index fd85e4c05c6b2b850da079b2282280754f72eaf6..f4968145c2a3ee22bdbff5fb7d4e2dd40f6fd392 100644 (file)
@@ -31,7 +31,8 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/slab.h>
-#include "sb.h"
+
+struct nilfs_sc_info;
 
 /* the_nilfs struct */
 enum {
@@ -65,13 +66,23 @@ enum {
  * @ns_last_cno: checkpoint number of the latest segment
  * @ns_prot_seq: least sequence number of segments which must not be reclaimed
  * @ns_prev_seq: base sequence number used to decide if advance log cursor
- * @ns_segctor_sem: segment constructor semaphore
+ * @ns_writer: log writer
+ * @ns_segctor_sem: semaphore protecting log write
  * @ns_dat: DAT file inode
  * @ns_cpfile: checkpoint file inode
  * @ns_sufile: segusage file inode
  * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
  * @ns_cptree_lock: lock protecting @ns_cptree
+ * @ns_dirty_files: list of dirty files
+ * @ns_inode_lock: lock protecting @ns_dirty_files
  * @ns_gc_inodes: dummy inodes to keep live blocks
+ * @ns_next_generation: next generation number for inodes
+ * @ns_next_gen_lock: lock protecting @ns_next_generation
+ * @ns_mount_opt: mount options
+ * @ns_resuid: uid for reserved blocks
+ * @ns_resgid: gid for reserved blocks
+ * @ns_interval: checkpoint creation interval
+ * @ns_watermark: watermark for the number of dirty buffers
  * @ns_blocksize_bits: bit length of block size
  * @ns_blocksize: block size
  * @ns_nsegments: number of segments in filesystem
@@ -131,6 +142,7 @@ struct the_nilfs {
        u64                     ns_prot_seq;
        u64                     ns_prev_seq;
 
+       struct nilfs_sc_info   *ns_writer;
        struct rw_semaphore     ns_segctor_sem;
 
        /*
@@ -145,9 +157,25 @@ struct the_nilfs {
        struct rb_root          ns_cptree;
        spinlock_t              ns_cptree_lock;
 
+       /* Dirty inode list */
+       struct list_head        ns_dirty_files;
+       spinlock_t              ns_inode_lock;
+
        /* GC inode list */
        struct list_head        ns_gc_inodes;
 
+       /* Inode allocator */
+       u32                     ns_next_generation;
+       spinlock_t              ns_next_gen_lock;
+
+       /* Mount options */
+       unsigned long           ns_mount_opt;
+
+       uid_t                   ns_resuid;
+       gid_t                   ns_resgid;
+       unsigned long           ns_interval;
+       unsigned long           ns_watermark;
+
        /* Disk layout information (static) */
        unsigned int            ns_blocksize_bits;
        unsigned int            ns_blocksize;
@@ -180,6 +208,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
 THE_NILFS_FNS(GC_RUNNING, gc_running)
 THE_NILFS_FNS(SB_DIRTY, sb_dirty)
 
+/*
+ * Mount option operations
+ */
+#define nilfs_clear_opt(nilfs, opt)  \
+       do { (nilfs)->ns_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
+#define nilfs_set_opt(nilfs, opt)  \
+       do { (nilfs)->ns_mount_opt |= NILFS_MOUNT_##opt; } while (0)
+#define nilfs_test_opt(nilfs, opt) ((nilfs)->ns_mount_opt & NILFS_MOUNT_##opt)
+#define nilfs_write_opt(nilfs, mask, opt)                              \
+       do { (nilfs)->ns_mount_opt =                                    \
+               (((nilfs)->ns_mount_opt & ~NILFS_MOUNT_##mask) |        \
+                NILFS_MOUNT_##opt);                                    \
+       } while (0)
+
 /**
  * struct nilfs_root - nilfs root object
  * @cno: checkpoint number
@@ -224,15 +266,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs)
 void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
 struct the_nilfs *alloc_nilfs(struct block_device *bdev);
 void destroy_nilfs(struct the_nilfs *nilfs);
-int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
-int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
+int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data);
+int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb);
 int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
 int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
 struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno);
 struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
                                             __u64 cno);
 void nilfs_put_root(struct nilfs_root *root);
-struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
 int nilfs_near_disk_full(struct the_nilfs *);
 void nilfs_fall_back_super_block(struct the_nilfs *);
 void nilfs_swap_super_block(struct the_nilfs *);
index 4ff028fcfd6e36a6cd576a8ce084d5486df696c4..30206b238433bac48582af6c252dc9413575de1d 100644 (file)
@@ -2,18 +2,13 @@
 
 obj-$(CONFIG_NTFS_FS) += ntfs.o
 
-ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
-            index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
-            unistr.o upcase.o
+ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
+         index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
+         unistr.o upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.30\"
+ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o
 
-ifeq ($(CONFIG_NTFS_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-y := -DNTFS_VERSION=\"2.1.30\"
+ccflags-$(CONFIG_NTFS_DEBUG)   += -DDEBUG
+ccflags-$(CONFIG_NTFS_RW)      += -DNTFS_RW
 
-ifeq ($(CONFIG_NTFS_RW),y)
-EXTRA_CFLAGS += -DNTFS_RW
-
-ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o
-endif
index 07d9fd85435028f2ca2e0ad1b298a490741b6c70..d8a0313e99e6af42b8412e91bb44cb2d7bb410b8 100644 (file)
@@ -1,6 +1,6 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
-EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
+ccflags-y += -DCATCH_BH_JBD_RACES
 
 obj-$(CONFIG_OCFS2_FS) +=      \
        ocfs2.o                 \
index dcebf0d920fa17cbd0bae8db9bcb2090f4a3e3a6..c8a044efbb150653c32d94460fa929944d25181f 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o
 
index df69b4856d0d82fd908d64acf48472dd8c8e578f..f14be89a67016101afb74705399a7724ec6d55bf 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o
 
index f83ca80cc59a1d72c8b933d7562efc853cfe3f8c..b52cf013ffa145de32e5c641aba7a3625de8cc29 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -835,17 +835,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
 
        validate_creds(cred);
 
-       /*
-        * We must always pass in a valid mount pointer.   Historically
-        * callers got away with not passing it, but we must enforce this at
-        * the earliest possible point now to avoid strange problems deep in the
-        * filesystem stack.
-        */
-       if (!mnt) {
-               printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__);
-               dump_stack();
-               return ERR_PTR(-EINVAL);
-       }
+       /* We must always pass in a valid mount pointer. */
+       BUG_ON(!mnt);
 
        error = -ENFILE;
        f = get_empty_filp();
index 08342232cb1c4f82ddb07db1fc4c8fcb9908d72b..977ed272384574e0220bdfe06439ea3cdd045ad5 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/string.h>
 #include <linux/mount.h>
 #include <linux/ramfs.h>
+#include <linux/parser.h>
 #include <linux/sched.h>
 #include <linux/magic.h>
 #include <linux/pstore.h>
@@ -73,11 +74,16 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
        struct pstore_private *p = dentry->d_inode->i_private;
 
        p->erase(p->id);
-       kfree(p);
 
        return simple_unlink(dir, dentry);
 }
 
+static void pstore_evict_inode(struct inode *inode)
+{
+       end_writeback(inode);
+       kfree(inode->i_private);
+}
+
 static const struct inode_operations pstore_dir_inode_operations = {
        .lookup         = simple_lookup,
        .unlink         = pstore_unlink,
@@ -107,9 +113,52 @@ static struct inode *pstore_get_inode(struct super_block *sb,
        return inode;
 }
 
+enum {
+       Opt_kmsg_bytes, Opt_err
+};
+
+static const match_table_t tokens = {
+       {Opt_kmsg_bytes, "kmsg_bytes=%u"},
+       {Opt_err, NULL}
+};
+
+static void parse_options(char *options)
+{
+       char            *p;
+       substring_t     args[MAX_OPT_ARGS];
+       int             option;
+
+       if (!options)
+               return;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               int token;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_kmsg_bytes:
+                       if (!match_int(&args[0], &option))
+                               pstore_set_kmsg_bytes(option);
+                       break;
+               }
+       }
+}
+
+static int pstore_remount(struct super_block *sb, int *flags, char *data)
+{
+       parse_options(data);
+
+       return 0;
+}
+
 static const struct super_operations pstore_ops = {
        .statfs         = simple_statfs,
        .drop_inode     = generic_delete_inode,
+       .evict_inode    = pstore_evict_inode,
+       .remount_fs     = pstore_remount,
        .show_options   = generic_show_options,
 };
 
@@ -209,6 +258,8 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op                = &pstore_ops;
        sb->s_time_gran         = 1;
 
+       parse_options(data);
+
        inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0);
        if (!inode) {
                err = -ENOMEM;
@@ -252,28 +303,7 @@ static struct file_system_type pstore_fs_type = {
 
 static int __init init_pstore_fs(void)
 {
-       int rc = 0;
-       struct kobject *pstorefs_kobj;
-
-       pstorefs_kobj = kobject_create_and_add("pstore", fs_kobj);
-       if (!pstorefs_kobj) {
-               rc = -ENOMEM;
-               goto done;
-       }
-
-       rc = sysfs_create_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr);
-       if (rc)
-               goto done1;
-
-       rc = register_filesystem(&pstore_fs_type);
-       if (rc == 0)
-               goto done;
-
-       sysfs_remove_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr);
-done1:
-       kobject_put(pstorefs_kobj);
-done:
-       return rc;
+       return register_filesystem(&pstore_fs_type);
 }
 module_init(init_pstore_fs)
 
index 76c26d2fab2925e2f4835e7707fb55a88b5e74c0..8c9f23eb16451a294cfb1b379c8cb8b55c40565d 100644 (file)
@@ -1,7 +1,6 @@
+extern void    pstore_set_kmsg_bytes(int);
 extern void    pstore_get_records(void);
 extern int     pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
                              char *data, size_t size,
                              struct timespec time, int (*erase)(u64));
 extern int     pstore_is_mounted(void);
-
-extern struct kobj_attribute pstore_kmsg_bytes_attr;
index 705fdf8abf6e5b838481029576b86879b8f79152..ce9ad84d5dd9fdbefcf03530396e88e29b6408aa 100644 (file)
 static DEFINE_SPINLOCK(pstore_lock);
 static struct pstore_info *psinfo;
 
-/* How much of the console log to snapshot. /sys/fs/pstore/kmsg_bytes */
+/* How much of the console log to snapshot */
 static unsigned long kmsg_bytes = 10240;
 
-static ssize_t b_show(struct kobject *kobj,
-                     struct kobj_attribute *attr, char *buf)
+void pstore_set_kmsg_bytes(int bytes)
 {
-       return snprintf(buf, PAGE_SIZE, "%lu\n", kmsg_bytes);
+       kmsg_bytes = bytes;
 }
 
-static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
-                      const char *buf, size_t count)
-{
-       return (sscanf(buf, "%lu", &kmsg_bytes) > 0) ? count : 0;
-}
-
-struct kobj_attribute pstore_kmsg_bytes_attr =
-       __ATTR(kmsg_bytes, S_IRUGO | S_IWUSR, b_show, b_store);
-
 /* Tag each group of saved records with a sequence number */
 static int     oopscount;
 
index 792b3cb2cd18a745772e8d6e138656c1c5314eaf..3c3b00165114c8023d4e8e98c1cafb9474095039 100644 (file)
@@ -31,9 +31,7 @@ endif
 # and causing a panic. Since this behavior only affects ppc32, this ifeq
 # will work around it. If any other architecture displays this behavior,
 # add it here.
-ifeq ($(CONFIG_PPC32),y)
-EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1)
-endif
+ccflags-$(CONFIG_PPC32) := $(call cc-ifversion, -lt, 0400, -O1)
 
 TAGS:
        etags *.c
index e56560d2b08a8db433f890f7a8baa344f50a3df1..d33418fdc858fbbe7f929d692dae1533c2e9a271 100644 (file)
@@ -517,9 +517,6 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-#define MAX_SELECT_SECONDS \
-       ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
 int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                           fd_set __user *exp, struct timespec *end_time)
 {
index ba76b9623e7e809f6b3c5e6223020836069dc4ab..92ca208777d562e64bfc769dc41a326f7c3da84e 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -7,6 +7,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/namei.h>
 #include <linux/sched.h>
 #include <linux/writeback.h>
 #include <linux/syscalls.h>
@@ -128,6 +129,29 @@ void emergency_sync(void)
        }
 }
 
+/*
+ * sync a single super
+ */
+SYSCALL_DEFINE1(syncfs, int, fd)
+{
+       struct file *file;
+       struct super_block *sb;
+       int ret;
+       int fput_needed;
+
+       file = fget_light(fd, &fput_needed);
+       if (!file)
+               return -EBADF;
+       sb = file->f_dentry->d_sb;
+
+       down_read(&sb->s_umount);
+       ret = sync_filesystem(sb);
+       up_read(&sb->s_umount);
+
+       fput_light(file, fput_needed);
+       return ret;
+}
+
 /**
  * vfs_fsync_range - helper to sync a range of data & metadata to disk
  * @file:              file to sync
index faca449970995ab41a8fc9117efeceac63cf1991..284a7c89697efd7d083b5a60dfc9671796fe80b1 100644 (file)
 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
 
-EXTRA_CFLAGS +=         -I$(src) -I$(src)/linux-2.6
+ccflags-y := -I$(src) -I$(src)/linux-2.6
+ccflags-$(CONFIG_XFS_DEBUG) += -g
 
 XFS_LINUX := linux-2.6
 
-ifeq ($(CONFIG_XFS_DEBUG),y)
-       EXTRA_CFLAGS += -g
-endif
-
 obj-$(CONFIG_XFS_FS)           += xfs.o
 
 xfs-y                          += linux-2.6/xfs_trace.o
@@ -105,11 +102,10 @@ xfs-y                             += $(addprefix $(XFS_LINUX)/, \
                                   xfs_globals.o \
                                   xfs_ioctl.o \
                                   xfs_iops.o \
+                                  xfs_message.o \
                                   xfs_super.o \
                                   xfs_sync.o \
                                   xfs_xattr.o)
 
 # Objects in support/
-xfs-y                          += $(addprefix support/, \
-                                  debug.o \
-                                  uuid.o)
+xfs-y                          += support/uuid.o
index 666c9db48eb63893cc3da777c44478ccd4d6942b..a907de565db3bf287f7d1a7894fff23f85ca18d5 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/backing-dev.h>
 #include "time.h"
 #include "kmem.h"
+#include "xfs_message.h"
 
 /*
  * Greedy allocation.  May fail and may return vmalloced memory.
@@ -56,8 +57,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
                        return ptr;
                if (!(++retries % 100))
-                       printk(KERN_ERR "XFS: possible memory allocation "
-                                       "deadlock in %s (mode:0x%x)\n",
+                       xfs_err(NULL,
+               "possible memory allocation deadlock in %s (mode:0x%x)",
                                        __func__, lflags);
                congestion_wait(BLK_RW_ASYNC, HZ/50);
        } while (1);
@@ -112,8 +113,8 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
                        return ptr;
                if (!(++retries % 100))
-                       printk(KERN_ERR "XFS: possible memory allocation "
-                                       "deadlock in %s (mode:0x%x)\n",
+                       xfs_err(NULL,
+               "possible memory allocation deadlock in %s (mode:0x%x)",
                                        __func__, lflags);
                congestion_wait(BLK_RW_ASYNC, HZ/50);
        } while (1);
index ec7bbb5645b63d85811e2ee731637139881b370c..8c5c8727745607800f91270ccf7184986b86b75e 100644 (file)
@@ -854,7 +854,7 @@ xfs_aops_discard_page(
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                goto out_invalidate;
 
-       xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+       xfs_alert(ip->i_mount,
                "page discard on page %p, inode 0x%llx, offset %llu.",
                        page, ip->i_ino, offset);
 
@@ -872,7 +872,7 @@ xfs_aops_discard_page(
                if (error) {
                        /* something screwed, just bail */
                        if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                               xfs_alert(ip->i_mount,
                        "page discard unable to remove delalloc mapping.");
                        }
                        break;
@@ -1411,7 +1411,7 @@ xfs_vm_write_failed(
                if (error) {
                        /* something screwed, just bail */
                        if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                               xfs_alert(ip->i_mount,
                        "xfs_vm_write_failed: unable to clean up ino %lld",
                                                ip->i_ino);
                        }
index f83a4c830a65e865f8d680849278f5dfa4eb41a2..5cb230f2cb4f613263cbb1e90c5ec06a5a1eb597 100644 (file)
@@ -401,9 +401,8 @@ _xfs_buf_lookup_pages(
                         * handle buffer allocation failures we can't do much.
                         */
                        if (!(++retries % 100))
-                               printk(KERN_ERR
-                                       "XFS: possible memory allocation "
-                                       "deadlock in %s (mode:0x%x)\n",
+                               xfs_err(NULL,
+               "possible memory allocation deadlock in %s (mode:0x%x)",
                                        __func__, gfp_mask);
 
                        XFS_STATS_INC(xb_page_retries);
@@ -615,8 +614,8 @@ xfs_buf_get(
        if (!(bp->b_flags & XBF_MAPPED)) {
                error = _xfs_buf_map_pages(bp, flags);
                if (unlikely(error)) {
-                       printk(KERN_WARNING "%s: failed to map pages\n",
-                                       __func__);
+                       xfs_warn(target->bt_mount,
+                               "%s: failed to map pages\n", __func__);
                        goto no_buffer;
                }
        }
@@ -850,8 +849,8 @@ xfs_buf_get_uncached(
 
        error = _xfs_buf_map_pages(bp, XBF_MAPPED);
        if (unlikely(error)) {
-               printk(KERN_WARNING "%s: failed to map pages\n",
-                               __func__);
+               xfs_warn(target->bt_mount,
+                       "%s: failed to map pages\n", __func__);
                goto fail_free_mem;
        }
 
@@ -1617,8 +1616,8 @@ xfs_setsize_buftarg_flags(
        btp->bt_smask = sectorsize - 1;
 
        if (set_blocksize(btp->bt_bdev, sectorsize)) {
-               printk(KERN_WARNING
-                       "XFS: Cannot set_blocksize to %u on device %s\n",
+               xfs_warn(btp->bt_mount,
+                       "Cannot set_blocksize to %u on device %s\n",
                        sectorsize, XFS_BUFTARG_NAME(btp));
                return EINVAL;
        }
index 096494997747da5904ed71a9af24d70c1555106e..244be9cbfe78d195ca1ee0a3ff20473f244af0a0 100644 (file)
@@ -39,7 +39,6 @@
 #include <mrlock.h>
 #include <time.h>
 
-#include <support/debug.h>
 #include <support/uuid.h>
 
 #include <linux/semaphore.h>
@@ -86,6 +85,7 @@
 #include <xfs_aops.h>
 #include <xfs_super.h>
 #include <xfs_buf.h>
+#include <xfs_message.h>
 
 /*
  * Feature macros (disable/enable)
@@ -280,4 +280,25 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
 #define __arch_pack
 #endif
 
+#define ASSERT_ALWAYS(expr)    \
+       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+
+#ifndef DEBUG
+#define ASSERT(expr)   ((void)0)
+
+#ifndef STATIC
+# define STATIC static noinline
+#endif
+
+#else /* DEBUG */
+
+#define ASSERT(expr)   \
+       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+
+#ifndef STATIC
+# define STATIC noinline
+#endif
+
+#endif /* DEBUG */
+
 #endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c
new file mode 100644 (file)
index 0000000..508e06f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_types.h"
+#include "xfs_log.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_mount.h"
+
+/*
+ * XFS logging functions
+ */
+static int
+__xfs_printk(
+       const char              *level,
+       const struct xfs_mount  *mp,
+       struct va_format        *vaf)
+{
+       if (mp && mp->m_fsname)
+               return printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf);
+       return printk("%sXFS: %pV\n", level, vaf);
+}
+
+int xfs_printk(
+       const char              *level,
+       const struct xfs_mount  *mp,
+       const char              *fmt, ...)
+{
+       struct va_format        vaf;
+       va_list                 args;
+       int                      r;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       r = __xfs_printk(level, mp, &vaf);
+       va_end(args);
+
+       return r;
+}
+
+#define define_xfs_printk_level(func, kern_level)              \
+int func(const struct xfs_mount *mp, const char *fmt, ...)     \
+{                                                              \
+       struct va_format        vaf;                            \
+       va_list                 args;                           \
+       int                     r;                              \
+                                                               \
+       va_start(args, fmt);                                    \
+                                                               \
+       vaf.fmt = fmt;                                          \
+       vaf.va = &args;                                         \
+                                                               \
+       r = __xfs_printk(kern_level, mp, &vaf);                 \
+       va_end(args);                                           \
+                                                               \
+       return r;                                               \
+}                                                              \
+
+define_xfs_printk_level(xfs_emerg, KERN_EMERG);
+define_xfs_printk_level(xfs_alert, KERN_ALERT);
+define_xfs_printk_level(xfs_crit, KERN_CRIT);
+define_xfs_printk_level(xfs_err, KERN_ERR);
+define_xfs_printk_level(xfs_warn, KERN_WARNING);
+define_xfs_printk_level(xfs_notice, KERN_NOTICE);
+define_xfs_printk_level(xfs_info, KERN_INFO);
+#ifdef DEBUG
+define_xfs_printk_level(xfs_debug, KERN_DEBUG);
+#endif
+
+int
+xfs_alert_tag(
+       const struct xfs_mount  *mp,
+       int                     panic_tag,
+       const char              *fmt, ...)
+{
+       struct va_format        vaf;
+       va_list                 args;
+       int                     do_panic = 0;
+       int                     r;
+
+       if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) {
+               xfs_printk(KERN_ALERT, mp,
+                       "XFS: Transforming an alert into a BUG.");
+               do_panic = 1;
+       }
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       r = __xfs_printk(KERN_ALERT, mp, &vaf);
+       va_end(args);
+
+       BUG_ON(do_panic);
+
+       return r;
+}
+
+void
+assfail(char *expr, char *file, int line)
+{
+       xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d",
+               expr, file, line);
+       BUG();
+}
+
+void
+xfs_hex_dump(void *p, int length)
+{
+       print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1);
+}
diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h
new file mode 100644 (file)
index 0000000..e77ffa1
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __XFS_MESSAGE_H
+#define __XFS_MESSAGE_H 1
+
+struct xfs_mount;
+
+extern int xfs_printk(const char *level, const struct xfs_mount *mp,
+                      const char *fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_alert(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_alert_tag(const struct xfs_mount *mp, int tag,
+                        const char *fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int xfs_crit(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_err(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_warn(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_notice(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_info(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+
+#ifdef DEBUG
+extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+#else
+#define xfs_debug(mp, fmt, ...)        (0)
+#endif
+
+extern void assfail(char *expr, char *f, int l);
+
+extern void xfs_hex_dump(void *p, int length);
+
+#endif /* __XFS_MESSAGE_H */
index 9731898083ae86ee79f546f372684ab5d03dbcc8..818c4cf2de863e5450ac75ad300a1c78bfdbca60 100644 (file)
@@ -172,6 +172,15 @@ xfs_parseargs(
        int                     iosize = 0;
        __uint8_t               iosizelog = 0;
 
+       /*
+        * set up the mount name first so all the errors will refer to the
+        * correct device.
+        */
+       mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL);
+       if (!mp->m_fsname)
+               return ENOMEM;
+       mp->m_fsname_len = strlen(mp->m_fsname) + 1;
+
        /*
         * Copy binary VFS mount flags we are interested in.
         */
@@ -189,6 +198,7 @@ xfs_parseargs(
        mp->m_flags |= XFS_MOUNT_BARRIER;
        mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
        mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
+       mp->m_flags |= XFS_MOUNT_DELAYLOG;
 
        /*
         * These can be overridden by the mount option parsing.
@@ -207,24 +217,21 @@ xfs_parseargs(
 
                if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
                        mp->m_logbufs = simple_strtoul(value, &eov, 10);
                } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
                        mp->m_logbsize = suffix_strtoul(value, &eov, 10);
                } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
@@ -232,14 +239,12 @@ xfs_parseargs(
                        if (!mp->m_logname)
                                return ENOMEM;
                } else if (!strcmp(this_char, MNTOPT_MTPT)) {
-                       cmn_err(CE_WARN,
-                               "XFS: %s option not allowed on this system",
+                       xfs_warn(mp, "%s option not allowed on this system",
                                this_char);
                        return EINVAL;
                } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
@@ -248,8 +253,7 @@ xfs_parseargs(
                                return ENOMEM;
                } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
@@ -257,8 +261,7 @@ xfs_parseargs(
                        iosizelog = ffs(iosize) - 1;
                } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
@@ -280,16 +283,14 @@ xfs_parseargs(
                        mp->m_flags |= XFS_MOUNT_SWALLOC;
                } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
                        dsunit = simple_strtoul(value, &eov, 10);
                } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
                        if (!value || !*value) {
-                               cmn_err(CE_WARN,
-                                       "XFS: %s option requires an argument",
+                               xfs_warn(mp, "%s option requires an argument",
                                        this_char);
                                return EINVAL;
                        }
@@ -297,8 +298,7 @@ xfs_parseargs(
                } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
                        mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
 #if !XFS_BIG_INUMS
-                       cmn_err(CE_WARN,
-                               "XFS: %s option not allowed on this system",
+                       xfs_warn(mp, "%s option not allowed on this system",
                                this_char);
                        return EINVAL;
 #endif
@@ -356,20 +356,19 @@ xfs_parseargs(
                } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
                        mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
                } else if (!strcmp(this_char, "ihashsize")) {
-                       cmn_err(CE_WARN,
-       "XFS: ihashsize no longer used, option is deprecated.");
+                       xfs_warn(mp,
+       "ihashsize no longer used, option is deprecated.");
                } else if (!strcmp(this_char, "osyncisdsync")) {
-                       cmn_err(CE_WARN,
-       "XFS: osyncisdsync has no effect, option is deprecated.");
+                       xfs_warn(mp,
+       "osyncisdsync has no effect, option is deprecated.");
                } else if (!strcmp(this_char, "osyncisosync")) {
-                       cmn_err(CE_WARN,
-       "XFS: osyncisosync has no effect, option is deprecated.");
+                       xfs_warn(mp,
+       "osyncisosync has no effect, option is deprecated.");
                } else if (!strcmp(this_char, "irixsgid")) {
-                       cmn_err(CE_WARN,
-       "XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
+                       xfs_warn(mp,
+       "irixsgid is now a sysctl(2) variable, option is deprecated.");
                } else {
-                       cmn_err(CE_WARN,
-                               "XFS: unknown mount option [%s].", this_char);
+                       xfs_warn(mp, "unknown mount option [%s].", this_char);
                        return EINVAL;
                }
        }
@@ -379,40 +378,37 @@ xfs_parseargs(
         */
        if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&
            !(mp->m_flags & XFS_MOUNT_RDONLY)) {
-               cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only.");
+               xfs_warn(mp, "no-recovery mounts must be read-only.");
                return EINVAL;
        }
 
        if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) {
-               cmn_err(CE_WARN,
-       "XFS: sunit and swidth options incompatible with the noalign option");
+               xfs_warn(mp,
+       "sunit and swidth options incompatible with the noalign option");
                return EINVAL;
        }
 
 #ifndef CONFIG_XFS_QUOTA
        if (XFS_IS_QUOTA_RUNNING(mp)) {
-               cmn_err(CE_WARN,
-                       "XFS: quota support not available in this kernel.");
+               xfs_warn(mp, "quota support not available in this kernel.");
                return EINVAL;
        }
 #endif
 
        if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
            (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
-               cmn_err(CE_WARN,
-                       "XFS: cannot mount with both project and group quota");
+               xfs_warn(mp, "cannot mount with both project and group quota");
                return EINVAL;
        }
 
        if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
-               cmn_err(CE_WARN,
-                       "XFS: sunit and swidth must be specified together");
+               xfs_warn(mp, "sunit and swidth must be specified together");
                return EINVAL;
        }
 
        if (dsunit && (dswidth % dsunit != 0)) {
-               cmn_err(CE_WARN,
-       "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
+               xfs_warn(mp,
+       "stripe width (%d) must be a multiple of the stripe unit (%d)",
                        dswidth, dsunit);
                return EINVAL;
        }
@@ -438,8 +434,7 @@ done:
            mp->m_logbufs != 0 &&
            (mp->m_logbufs < XLOG_MIN_ICLOGS ||
             mp->m_logbufs > XLOG_MAX_ICLOGS)) {
-               cmn_err(CE_WARN,
-                       "XFS: invalid logbufs value: %d [not %d-%d]",
+               xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]",
                        mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
                return XFS_ERROR(EINVAL);
        }
@@ -448,22 +443,16 @@ done:
            (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE ||
             mp->m_logbsize > XLOG_MAX_RECORD_BSIZE ||
             !is_power_of_2(mp->m_logbsize))) {
-               cmn_err(CE_WARN,
-       "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
+               xfs_warn(mp,
+                       "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
                        mp->m_logbsize);
                return XFS_ERROR(EINVAL);
        }
 
-       mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL);
-       if (!mp->m_fsname)
-               return ENOMEM;
-       mp->m_fsname_len = strlen(mp->m_fsname) + 1;
-
        if (iosizelog) {
                if (iosizelog > XFS_MAX_IO_LOG ||
                    iosizelog < XFS_MIN_IO_LOG) {
-                       cmn_err(CE_WARN,
-               "XFS: invalid log iosize: %d [not %d-%d]",
+                       xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",
                                iosizelog, XFS_MIN_IO_LOG,
                                XFS_MAX_IO_LOG);
                        return XFS_ERROR(EINVAL);
@@ -610,7 +599,7 @@ xfs_blkdev_get(
                                    mp);
        if (IS_ERR(*bdevp)) {
                error = PTR_ERR(*bdevp);
-               printk("XFS: Invalid device [%s], error=%d\n", name, error);
+               xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error);
        }
 
        return -error;
@@ -664,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)
        int error;
 
        if (mp->m_logdev_targp != mp->m_ddev_targp) {
-               xfs_fs_cmn_err(CE_NOTE, mp,
+               xfs_notice(mp,
                  "Disabling barriers, not supported with external log device");
                mp->m_flags &= ~XFS_MOUNT_BARRIER;
                return;
        }
 
        if (xfs_readonly_buftarg(mp->m_ddev_targp)) {
-               xfs_fs_cmn_err(CE_NOTE, mp,
-                 "Disabling barriers, underlying device is readonly");
+               xfs_notice(mp,
+                       "Disabling barriers, underlying device is readonly");
                mp->m_flags &= ~XFS_MOUNT_BARRIER;
                return;
        }
 
        error = xfs_barrier_test(mp);
        if (error) {
-               xfs_fs_cmn_err(CE_NOTE, mp,
-                 "Disabling barriers, trial barrier write failed");
+               xfs_notice(mp,
+                       "Disabling barriers, trial barrier write failed");
                mp->m_flags &= ~XFS_MOUNT_BARRIER;
                return;
        }
@@ -743,8 +732,8 @@ xfs_open_devices(
                        goto out_close_logdev;
 
                if (rtdev == ddev || rtdev == logdev) {
-                       cmn_err(CE_WARN,
-       "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
+                       xfs_warn(mp,
+       "Cannot mount filesystem with identical rtdev and ddev/logdev.");
                        error = EINVAL;
                        goto out_close_rtdev;
                }
@@ -1345,8 +1334,8 @@ xfs_fs_remount(
                         * options that we can't actually change.
                         */
 #if 0
-                       printk(KERN_INFO
-       "XFS: mount option \"%s\" not supported for remount\n", p);
+                       xfs_info(mp,
+               "mount option \"%s\" not supported for remount\n", p);
                        return -EINVAL;
 #else
                        break;
@@ -1367,8 +1356,7 @@ xfs_fs_remount(
                if (mp->m_update_flags) {
                        error = xfs_mount_log_sb(mp, mp->m_update_flags);
                        if (error) {
-                               cmn_err(CE_WARN,
-                                       "XFS: failed to write sb changes");
+                               xfs_warn(mp, "failed to write sb changes");
                                return error;
                        }
                        mp->m_update_flags = 0;
@@ -1452,15 +1440,15 @@ xfs_finish_flags(
                        mp->m_logbsize = mp->m_sb.sb_logsunit;
                } else if (mp->m_logbsize > 0 &&
                           mp->m_logbsize < mp->m_sb.sb_logsunit) {
-                       cmn_err(CE_WARN,
-       "XFS: logbuf size must be greater than or equal to log stripe size");
+                       xfs_warn(mp,
+               "logbuf size must be greater than or equal to log stripe size");
                        return XFS_ERROR(EINVAL);
                }
        } else {
                /* Fail a mount if the logbuf is larger than 32K */
                if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) {
-                       cmn_err(CE_WARN,
-       "XFS: logbuf size for version 1 logs must be 16K or 32K");
+                       xfs_warn(mp,
+               "logbuf size for version 1 logs must be 16K or 32K");
                        return XFS_ERROR(EINVAL);
                }
        }
@@ -1477,8 +1465,8 @@ xfs_finish_flags(
         * prohibit r/w mounts of read-only filesystems
         */
        if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
-               cmn_err(CE_WARN,
-       "XFS: cannot mount a read-only filesystem as read-write");
+               xfs_warn(mp,
+                       "cannot mount a read-only filesystem as read-write");
                return XFS_ERROR(EROFS);
        }
 
index e22f0057d21fa8d2d3e04c11a2e62438ac17a3e9..6c10f1d2e3d3a8e4e094c5153d90b5c8ac60973f 100644 (file)
@@ -425,8 +425,7 @@ xfs_quiesce_attr(
        /* Push the superblock and write an unmount record */
        error = xfs_log_sbcount(mp, 1);
        if (error)
-               xfs_fs_cmn_err(CE_WARN, mp,
-                               "xfs_attr_quiesce: failed to log sb changes. "
+               xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
                                "Frozen image may not be consistent.");
        xfs_log_unmount_write(mp);
        xfs_unmountfs_writesb(mp);
@@ -806,7 +805,7 @@ xfs_reclaim_inode(
         * pass on the error.
         */
        if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-               xfs_fs_cmn_err(CE_WARN, ip->i_mount,
+               xfs_warn(ip->i_mount,
                        "inode 0x%llx background reclaim flush failed with %d",
                        (long long)ip->i_ino, error);
        }
index ee3cee097e7eba33b7139987b6c201ef44c82f64..ee2d2adaa438121a1c875a5a7dda6b96f16c20c0 100644 (file)
@@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler(
        ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
 
        if (!ret && write && *valp) {
-               printk("XFS Clearing xfsstats\n");
+               xfs_notice(NULL, "Clearing xfsstats");
                for_each_possible_cpu(c) {
                        preempt_disable();
                        /* save vn_active, it's a universal truth! */
index d22aa3103106c47d7d0ca6b9f1532bd17b4289ea..7e241647850335967262b8763ff14bdb5dd86a5b 100644 (file)
@@ -544,9 +544,10 @@ xfs_qm_dqtobp(
        /*
         * A simple sanity check in case we got a corrupted dquot...
         */
-       if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
+       error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
                           flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
-                          "dqtobp")) {
+                          "dqtobp");
+       if (error) {
                if (!(flags & XFS_QMOPT_DQREPAIR)) {
                        xfs_trans_brelse(tp, bp);
                        return XFS_ERROR(EIO);
@@ -827,7 +828,7 @@ xfs_qm_dqget(
        if (xfs_do_dqerror) {
                if ((xfs_dqerror_target == mp->m_ddev_targp) &&
                    (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) {
-                       cmn_err(CE_DEBUG, "Returning error in dqget");
+                       xfs_debug(mp, "Returning error in dqget");
                        return (EIO);
                }
        }
@@ -1207,8 +1208,9 @@ xfs_qm_dqflush(
        /*
         * A simple sanity check in case we got a corrupted dquot..
         */
-       if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
-                          XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
+       error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
+                          XFS_QMOPT_DOWARN, "dqflush (incore copy)");
+       if (error) {
                xfs_buf_relse(bp);
                xfs_dqfunlock(dqp);
                xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
@@ -1391,8 +1393,8 @@ xfs_qm_dqpurge(
                 */
                error = xfs_qm_dqflush(dqp, SYNC_WAIT);
                if (error)
-                       xfs_fs_cmn_err(CE_WARN, mp,
-                               "xfs_qm_dqpurge: dquot %p flush failed", dqp);
+                       xfs_warn(mp, "%s: dquot %p flush failed",
+                               __func__, dqp);
                xfs_dqflock(dqp);
        }
        ASSERT(atomic_read(&dqp->q_pincount) == 0);
@@ -1425,36 +1427,38 @@ xfs_qm_dqpurge(
 void
 xfs_qm_dqprint(xfs_dquot_t *dqp)
 {
-       cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
-       cmn_err(CE_DEBUG, "---- dquotID =  %d",
+       struct xfs_mount        *mp = dqp->q_mount;
+
+       xfs_debug(mp, "-----------KERNEL DQUOT----------------");
+       xfs_debug(mp, "---- dquotID =  %d",
                (int)be32_to_cpu(dqp->q_core.d_id));
-       cmn_err(CE_DEBUG, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
-       cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount);
-       cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno);
-       cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
-       cmn_err(CE_DEBUG, "---- blkhlimit =  %Lu (0x%x)",
+       xfs_debug(mp, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
+       xfs_debug(mp, "---- fs      =  0x%p", dqp->q_mount);
+       xfs_debug(mp, "---- blkno   =  0x%x", (int) dqp->q_blkno);
+       xfs_debug(mp, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
+       xfs_debug(mp, "---- blkhlimit =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_blk_hardlimit),
                (int)be64_to_cpu(dqp->q_core.d_blk_hardlimit));
-       cmn_err(CE_DEBUG, "---- blkslimit =  %Lu (0x%x)",
+       xfs_debug(mp, "---- blkslimit =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_blk_softlimit),
                (int)be64_to_cpu(dqp->q_core.d_blk_softlimit));
-       cmn_err(CE_DEBUG, "---- inohlimit =  %Lu (0x%x)",
+       xfs_debug(mp, "---- inohlimit =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_ino_hardlimit),
                (int)be64_to_cpu(dqp->q_core.d_ino_hardlimit));
-       cmn_err(CE_DEBUG, "---- inoslimit =  %Lu (0x%x)",
+       xfs_debug(mp, "---- inoslimit =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_ino_softlimit),
                (int)be64_to_cpu(dqp->q_core.d_ino_softlimit));
-       cmn_err(CE_DEBUG, "---- bcount  =  %Lu (0x%x)",
+       xfs_debug(mp, "---- bcount  =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_bcount),
                (int)be64_to_cpu(dqp->q_core.d_bcount));
-       cmn_err(CE_DEBUG, "---- icount  =  %Lu (0x%x)",
+       xfs_debug(mp, "---- icount  =  %Lu (0x%x)",
                be64_to_cpu(dqp->q_core.d_icount),
                (int)be64_to_cpu(dqp->q_core.d_icount));
-       cmn_err(CE_DEBUG, "---- btimer  =  %d",
+       xfs_debug(mp, "---- btimer  =  %d",
                (int)be32_to_cpu(dqp->q_core.d_btimer));
-       cmn_err(CE_DEBUG, "---- itimer  =  %d",
+       xfs_debug(mp, "---- itimer  =  %d",
                (int)be32_to_cpu(dqp->q_core.d_itimer));
-       cmn_err(CE_DEBUG, "---------------------------");
+       xfs_debug(mp, "---------------------------");
 }
 #endif
 
index 2a1f3dc10a02dba4f401a326fd72f07bd40212af..9e0e2fa3f2c8c532157609229734329cd8a3bbee 100644 (file)
@@ -136,9 +136,8 @@ xfs_qm_dquot_logitem_push(
         */
        error = xfs_qm_dqflush(dqp, 0);
        if (error)
-               xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
-                       "xfs_qm_dquot_logitem_push: push error %d on dqp %p",
-                       error, dqp);
+               xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p",
+                       __func__, error, dqp);
        xfs_dqunlock(dqp);
 }
 
index 206a2815ced67399c9cfa248a45d185605e12aee..254ee062bd7dde135e0c238ca3696fe180ec78fe 100644 (file)
@@ -80,7 +80,7 @@ xfs_qm_dquot_list_print(
        int             i = 0;
 
        list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) {
-               cmn_err(CE_DEBUG, "   %d. \"%d (%s)\"   "
+               xfs_debug(mp, "   %d. \"%d (%s)\"   "
                                  "bcnt = %lld, icnt = %lld, refs = %d",
                        i++, be32_to_cpu(dqp->q_core.d_id),
                        DQFLAGTO_TYPESTR(dqp),
@@ -205,7 +205,7 @@ xfs_qm_destroy(
        list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
                xfs_dqlock(dqp);
 #ifdef QUOTADEBUG
-               cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
+               xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp);
 #endif
                list_del_init(&dqp->q_freelist);
                xfs_Gqm->qm_dqfrlist_cnt--;
@@ -341,9 +341,7 @@ xfs_qm_mount_quotas(
         * quotas immediately.
         */
        if (mp->m_sb.sb_rextents) {
-               cmn_err(CE_NOTE,
-                       "Cannot turn on quotas for realtime filesystem %s",
-                       mp->m_fsname);
+               xfs_notice(mp, "Cannot turn on quotas for realtime filesystem");
                mp->m_qflags = 0;
                goto write_changes;
        }
@@ -402,14 +400,13 @@ xfs_qm_mount_quotas(
                         * off, but the on disk superblock doesn't know that !
                         */
                        ASSERT(!(XFS_IS_QUOTA_RUNNING(mp)));
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "XFS mount_quotas: Superblock update failed!");
+                       xfs_alert(mp, "%s: Superblock update failed!",
+                               __func__);
                }
        }
 
        if (error) {
-               xfs_fs_cmn_err(CE_WARN, mp,
-                       "Failed to initialize disk quotas.");
+               xfs_warn(mp, "Failed to initialize disk quotas.");
                return;
        }
 
@@ -1229,13 +1226,6 @@ xfs_qm_qino_alloc(
                return error;
        }
 
-       /*
-        * Keep an extra reference to this quota inode. This inode is
-        * locked exclusively and joined to the transaction already.
-        */
-       ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
-       IHOLD(*ip);
-
        /*
         * Make the changes in the superblock, and log those too.
         * sbfields arg may contain fields other than *QUOTINO;
@@ -1264,7 +1254,7 @@ xfs_qm_qino_alloc(
        xfs_mod_sb(tp, sbfields);
 
        if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
-               xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!");
+               xfs_alert(mp, "%s failed (error %d)!", __func__, error);
                return error;
        }
        return 0;
@@ -1299,7 +1289,7 @@ xfs_qm_reset_dqcounts(
                 * output any warnings because it's perfectly possible to
                 * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.
                 */
-               (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR,
+               (void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,
                                      "xfs_quotacheck");
                ddq->d_bcount = 0;
                ddq->d_icount = 0;
@@ -1676,7 +1666,7 @@ xfs_qm_quotacheck(
         */
        ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist));
 
-       cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
+       xfs_notice(mp, "Quotacheck needed: Please wait.");
 
        /*
         * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
@@ -1754,9 +1744,9 @@ xfs_qm_quotacheck(
 
  error_return:
        if (error) {
-               cmn_err(CE_WARN, "XFS quotacheck %s: Unsuccessful (Error %d): "
-                       "Disabling quotas.",
-                       mp->m_fsname, error);
+               xfs_warn(mp,
+       "Quotacheck: Unsuccessful (Error %d): Disabling quotas.",
+                       error);
                /*
                 * We must turn off quotas.
                 */
@@ -1764,12 +1754,11 @@ xfs_qm_quotacheck(
                ASSERT(xfs_Gqm != NULL);
                xfs_qm_destroy_quotainfo(mp);
                if (xfs_mount_reset_sbqflags(mp)) {
-                       cmn_err(CE_WARN, "XFS quotacheck %s: "
-                               "Failed to reset quota flags.", mp->m_fsname);
+                       xfs_warn(mp,
+                               "Quotacheck: Failed to reset quota flags.");
                }
-       } else {
-               cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
-       }
+       } else
+               xfs_notice(mp, "Quotacheck: Done.");
        return (error);
 }
 
@@ -1937,8 +1926,8 @@ again:
                         */
                        error = xfs_qm_dqflush(dqp, 0);
                        if (error) {
-                               xfs_fs_cmn_err(CE_WARN, mp,
-                       "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
+                               xfs_warn(mp, "%s: dquot %p flush failed",
+                                       __func__, dqp);
                        }
                        goto dqunlock;
                }
@@ -2115,7 +2104,7 @@ xfs_qm_write_sb_changes(
        int             error;
 
 #ifdef QUOTADEBUG
-       cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname);
+       xfs_notice(mp, "Writing superblock quota changes");
 #endif
        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
        if ((error = xfs_trans_reserve(tp, 0,
index 45b5cb1788abb953d43f845cf462332cfe5863ac..774d7ec6df8e800e43c484916fbcec7d920de1e1 100644 (file)
@@ -119,8 +119,7 @@ xfs_qm_newmount(
             (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
            (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
            xfs_dev_is_read_only(mp, "changing quota state")) {
-               cmn_err(CE_WARN,
-                       "XFS: please mount with%s%s%s%s.",
+               xfs_warn(mp, "please mount with%s%s%s%s.",
                        (!quotaondisk ? "out quota" : ""),
                        (uquotaondisk ? " usrquota" : ""),
                        (pquotaondisk ? " prjquota" : ""),
index bdebc183223e53c47ab6734976f1ba2bc1aa8901..c82f06778a27d4388f9bdf61ac6c1193c1b373eb 100644 (file)
 #include "xfs_qm.h"
 #include "xfs_trace.h"
 
-#ifdef DEBUG
-# define qdprintk(s, args...)  cmn_err(CE_DEBUG, s, ## args)
-#else
-# define qdprintk(s, args...)  do { } while (0)
-#endif
-
 STATIC int     xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 STATIC int     xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
                                        uint);
@@ -294,7 +288,8 @@ xfs_qm_scall_trunc_qfiles(
        int             error = 0, error2 = 0;
 
        if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
-               qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
+               xfs_debug(mp, "%s: flags=%x m_qflags=%x\n",
+                       __func__, flags, mp->m_qflags);
                return XFS_ERROR(EINVAL);
        }
 
@@ -331,7 +326,8 @@ xfs_qm_scall_quotaon(
        sbflags = 0;
 
        if (flags == 0) {
-               qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags);
+               xfs_debug(mp, "%s: zero flags, m_qflags=%x\n",
+                       __func__, mp->m_qflags);
                return XFS_ERROR(EINVAL);
        }
 
@@ -352,8 +348,9 @@ xfs_qm_scall_quotaon(
            (flags & XFS_GQUOTA_ACCT) == 0 &&
            (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
            (flags & XFS_OQUOTA_ENFD))) {
-               qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
-                       flags, mp->m_sb.sb_qflags);
+               xfs_debug(mp,
+                       "%s: Can't enforce without acct, flags=%x sbflags=%x\n",
+                       __func__, flags, mp->m_sb.sb_qflags);
                return XFS_ERROR(EINVAL);
        }
        /*
@@ -541,7 +538,7 @@ xfs_qm_scall_setqlim(
                        q->qi_bsoftlimit = soft;
                }
        } else {
-               qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
+               xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft);
        }
        hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
                (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
@@ -557,7 +554,7 @@ xfs_qm_scall_setqlim(
                        q->qi_rtbsoftlimit = soft;
                }
        } else {
-               qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
+               xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
        }
 
        hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
@@ -574,7 +571,7 @@ xfs_qm_scall_setqlim(
                        q->qi_isoftlimit = soft;
                }
        } else {
-               qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
+               xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft);
        }
 
        /*
@@ -939,10 +936,11 @@ struct mutex  qcheck_lock;
 #define DQTEST_LIST_PRINT(l, NXT, title) \
 { \
          xfs_dqtest_t  *dqp; int i = 0;\
-         cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
+         xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \
          for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
               dqp = (xfs_dqtest_t *)dqp->NXT) { \
-               cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
+               xfs_debug(dqp->q_mount,         \
+                       "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
                         ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),      \
                         dqp->d_bcount, dqp->d_icount); } \
 }
@@ -966,16 +964,17 @@ xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
 }
 STATIC void
 xfs_qm_dqtest_print(
-       xfs_dqtest_t    *d)
+       struct xfs_mount        *mp,
+       struct dqtest           *d)
 {
-       cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
-       cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
-       cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);
-       cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",
+       xfs_debug(mp, "-----------DQTEST DQUOT----------------");
+       xfs_debug(mp, "---- dquot ID = %d", d->d_id);
+       xfs_debug(mp, "---- fs       = 0x%p", d->q_mount);
+       xfs_debug(mp, "---- bcount   = %Lu (0x%x)",
                d->d_bcount, (int)d->d_bcount);
-       cmn_err(CE_DEBUG, "---- icount   = %Lu (0x%x)",
+       xfs_debug(mp, "---- icount   = %Lu (0x%x)",
                d->d_icount, (int)d->d_icount);
-       cmn_err(CE_DEBUG, "---------------------------");
+       xfs_debug(mp, "---------------------------");
 }
 
 STATIC void
@@ -989,12 +988,14 @@ xfs_qm_dqtest_failed(
 {
        qmtest_nfails++;
        if (error)
-               cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",
-                      d->d_id, error, reason);
+               xfs_debug(dqp->q_mount,
+                       "quotacheck failed id=%d, err=%d\nreason: %s",
+                       d->d_id, error, reason);
        else
-               cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",
-                      d->d_id, reason, (int)a, (int)b);
-       xfs_qm_dqtest_print(d);
+               xfs_debug(dqp->q_mount,
+                       "quotacheck failed id=%d (%s) [%d != %d]",
+                       d->d_id, reason, (int)a, (int)b);
+       xfs_qm_dqtest_print(dqp->q_mount, d);
        if (dqp)
                xfs_qm_dqprint(dqp);
 }
@@ -1021,9 +1022,9 @@ xfs_dqtest_cmp2(
            be64_to_cpu(dqp->q_core.d_bcount) >=
            be64_to_cpu(dqp->q_core.d_blk_softlimit)) {
                if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {
-                       cmn_err(CE_DEBUG,
-                               "%d [%s] [0x%p] BLK TIMER NOT STARTED",
-                               d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+                       xfs_debug(dqp->q_mount,
+                               "%d [%s] BLK TIMER NOT STARTED",
+                               d->d_id, DQFLAGTO_TYPESTR(d));
                        err++;
                }
        }
@@ -1031,16 +1032,16 @@ xfs_dqtest_cmp2(
            be64_to_cpu(dqp->q_core.d_icount) >=
            be64_to_cpu(dqp->q_core.d_ino_softlimit)) {
                if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {
-                       cmn_err(CE_DEBUG,
-                               "%d [%s] [0x%p] INO TIMER NOT STARTED",
-                               d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+                       xfs_debug(dqp->q_mount,
+                               "%d [%s] INO TIMER NOT STARTED",
+                               d->d_id, DQFLAGTO_TYPESTR(d));
                        err++;
                }
        }
 #ifdef QUOTADEBUG
        if (!err) {
-               cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
-                       d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+               xfs_debug(dqp->q_mount, "%d [%s] qchecked",
+                       d->d_id, DQFLAGTO_TYPESTR(d));
        }
 #endif
        return (err);
@@ -1137,8 +1138,8 @@ xfs_qm_internalqcheck_adjust(
 
        if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
                *res = BULKSTAT_RV_NOTHING;
-               qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n",
-                       (unsigned long long) ino,
+               xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n",
+                       __func__, (unsigned long long) ino,
                        (unsigned long long) mp->m_sb.sb_uquotino,
                        (unsigned long long) mp->m_sb.sb_gquotino);
                return XFS_ERROR(EINVAL);
@@ -1223,12 +1224,12 @@ xfs_qm_internalqcheck(
                                 xfs_qm_internalqcheck_adjust,
                                 0, NULL, &done);
                if (error) {
-                       cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
+                       xfs_debug(mp, "Bulkstat returned error 0x%x", error);
                        break;
                }
        } while (!done);
 
-       cmn_err(CE_DEBUG, "Checking results against system dquots");
+       xfs_debug(mp, "Checking results against system dquots");
        for (i = 0; i < qmtest_hashmask; i++) {
                xfs_dqtest_t    *d, *n;
                xfs_dqhash_t    *h;
@@ -1246,10 +1247,10 @@ xfs_qm_internalqcheck(
        }
 
        if (qmtest_nfails) {
-               cmn_err(CE_DEBUG, "******** quotacheck failed  ********");
-               cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);
+               xfs_debug(mp, "******** quotacheck failed  ********");
+               xfs_debug(mp, "failures = %d", qmtest_nfails);
        } else {
-               cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
+               xfs_debug(mp, "******** quotacheck successful! ********");
        }
        kmem_free(qmtest_udqtab);
        kmem_free(qmtest_gdqtab);
index 7de91d1b75c06c91daea768da891ab49a4152818..2a36487313319f45b45b5dbc39bc4fc1c69c8d64 100644 (file)
@@ -643,8 +643,9 @@ xfs_trans_dqresv(
             (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
              (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
 #ifdef QUOTADEBUG
-               cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
-                         " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);
+               xfs_debug(mp,
+                       "BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?",
+                       nblks, *resbcountp, hardlimit);
 #endif
                if (nblks > 0) {
                        /*
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
deleted file mode 100644 (file)
index 0df8889..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <xfs.h>
-#include "debug.h"
-
-/* xfs_mount.h drags a lot of crap in, sorry.. */
-#include "xfs_sb.h"
-#include "xfs_inum.h"
-#include "xfs_ag.h"
-#include "xfs_mount.h"
-#include "xfs_error.h"
-
-void
-cmn_err(
-       const char      *lvl,
-       const char      *fmt,
-       ...)
-{
-       struct va_format vaf;
-       va_list         args;
-
-       va_start(args, fmt);
-       vaf.fmt = fmt;
-       vaf.va = &args;
-
-       printk("%s%pV", lvl, &vaf);
-       va_end(args);
-
-       BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0);
-}
-
-void
-xfs_fs_cmn_err(
-       const char              *lvl,
-       struct xfs_mount        *mp,
-       const char              *fmt,
-       ...)
-{
-       struct va_format        vaf;
-       va_list                 args;
-
-       va_start(args, fmt);
-       vaf.fmt = fmt;
-       vaf.va = &args;
-
-       printk("%sFilesystem %s: %pV", lvl, mp->m_fsname, &vaf);
-       va_end(args);
-
-       BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0);
-}
-
-/* All callers to xfs_cmn_err use CE_ALERT, so don't bother testing lvl */
-void
-xfs_cmn_err(
-       int                     panic_tag,
-       const char              *lvl,
-       struct xfs_mount        *mp,
-       const char              *fmt,
-       ...)
-{
-       struct va_format        vaf;
-       va_list                 args;
-       int                     do_panic = 0;
-
-       if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) {
-               printk(KERN_ALERT "XFS: Transforming an alert into a BUG.");
-               do_panic = 1;
-       }
-
-       va_start(args, fmt);
-       vaf.fmt = fmt;
-       vaf.va = &args;
-
-       printk(KERN_ALERT "Filesystem %s: %pV", mp->m_fsname, &vaf);
-       va_end(args);
-
-       BUG_ON(do_panic);
-}
-
-void
-assfail(char *expr, char *file, int line)
-{
-       printk(KERN_CRIT "Assertion failed: %s, file: %s, line: %d\n", expr,
-              file, line);
-       BUG();
-}
-
-void
-xfs_hex_dump(void *p, int length)
-{
-       print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1);
-}
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
deleted file mode 100644 (file)
index 05699f6..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef        __XFS_SUPPORT_DEBUG_H__
-#define        __XFS_SUPPORT_DEBUG_H__
-
-#include <stdarg.h>
-
-struct xfs_mount;
-
-#define CE_DEBUG        KERN_DEBUG
-#define CE_CONT         KERN_INFO
-#define CE_NOTE         KERN_NOTICE
-#define CE_WARN         KERN_WARNING
-#define CE_ALERT        KERN_ALERT
-#define CE_PANIC        KERN_EMERG
-
-void cmn_err(const char *lvl, const char *fmt, ...)
-               __attribute__ ((format (printf, 2, 3)));
-void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp,
-               const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
-void xfs_cmn_err( int panic_tag, const char *lvl, struct xfs_mount *mp,
-               const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
-
-extern void assfail(char *expr, char *f, int l);
-
-#define ASSERT_ALWAYS(expr)    \
-       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
-
-#ifndef DEBUG
-#define ASSERT(expr)   ((void)0)
-
-#ifndef STATIC
-# define STATIC static noinline
-#endif
-
-#else /* DEBUG */
-
-#define ASSERT(expr)   \
-       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
-
-#ifndef STATIC
-# define STATIC noinline
-#endif
-
-#endif /* DEBUG */
-#endif  /* __XFS_SUPPORT_DEBUG_H__ */
index f3227984a9bf815d554034ec4661bdcc37d6db36..4bc3c649aee4bb35a6c7ebaa790ef8b73d264073 100644 (file)
@@ -147,10 +147,9 @@ xfs_alloc_get_rec(
  */
 STATIC void
 xfs_alloc_compute_aligned(
+       xfs_alloc_arg_t *args,          /* allocation argument structure */
        xfs_agblock_t   foundbno,       /* starting block in found extent */
        xfs_extlen_t    foundlen,       /* length in found extent */
-       xfs_extlen_t    alignment,      /* alignment for allocation */
-       xfs_extlen_t    minlen,         /* minimum length for allocation */
        xfs_agblock_t   *resbno,        /* result block number */
        xfs_extlen_t    *reslen)        /* result length */
 {
@@ -158,8 +157,8 @@ xfs_alloc_compute_aligned(
        xfs_extlen_t    diff;
        xfs_extlen_t    len;
 
-       if (alignment > 1 && foundlen >= minlen) {
-               bno = roundup(foundbno, alignment);
+       if (args->alignment > 1 && foundlen >= args->minlen) {
+               bno = roundup(foundbno, args->alignment);
                diff = bno - foundbno;
                len = diff >= foundlen ? 0 : foundlen - diff;
        } else {
@@ -464,6 +463,27 @@ xfs_alloc_read_agfl(
        return 0;
 }
 
+STATIC int
+xfs_alloc_update_counters(
+       struct xfs_trans        *tp,
+       struct xfs_perag        *pag,
+       struct xfs_buf          *agbp,
+       long                    len)
+{
+       struct xfs_agf          *agf = XFS_BUF_TO_AGF(agbp);
+
+       pag->pagf_freeblks += len;
+       be32_add_cpu(&agf->agf_freeblks, len);
+
+       xfs_trans_agblocks_delta(tp, len);
+       if (unlikely(be32_to_cpu(agf->agf_freeblks) >
+                    be32_to_cpu(agf->agf_length)))
+               return EFSCORRUPTED;
+
+       xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
+       return 0;
+}
+
 /*
  * Allocation group level functions.
  */
@@ -505,49 +525,44 @@ xfs_alloc_ag_vextent(
                ASSERT(0);
                /* NOTREACHED */
        }
-       if (error)
+
+       if (error || args->agbno == NULLAGBLOCK)
                return error;
-       /*
-        * If the allocation worked, need to change the agf structure
-        * (and log it), and the superblock.
-        */
-       if (args->agbno != NULLAGBLOCK) {
-               xfs_agf_t       *agf;   /* allocation group freelist header */
-               long            slen = (long)args->len;
 
-               ASSERT(args->len >= args->minlen && args->len <= args->maxlen);
-               ASSERT(!(args->wasfromfl) || !args->isfl);
-               ASSERT(args->agbno % args->alignment == 0);
-               if (!(args->wasfromfl)) {
-
-                       agf = XFS_BUF_TO_AGF(args->agbp);
-                       be32_add_cpu(&agf->agf_freeblks, -(args->len));
-                       xfs_trans_agblocks_delta(args->tp,
-                                                -((long)(args->len)));
-                       args->pag->pagf_freeblks -= args->len;
-                       ASSERT(be32_to_cpu(agf->agf_freeblks) <=
-                               be32_to_cpu(agf->agf_length));
-                       xfs_alloc_log_agf(args->tp, args->agbp,
-                                               XFS_AGF_FREEBLKS);
-                       /*
-                        * Search the busylist for these blocks and mark the
-                        * transaction as synchronous if blocks are found. This
-                        * avoids the need to block due to a synchronous log
-                        * force to ensure correct ordering as the synchronous
-                        * transaction will guarantee that for us.
-                        */
-                       if (xfs_alloc_busy_search(args->mp, args->agno,
-                                               args->agbno, args->len))
-                               xfs_trans_set_sync(args->tp);
-               }
-               if (!args->isfl)
-                       xfs_trans_mod_sb(args->tp,
-                               args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
-                                       XFS_TRANS_SB_FDBLOCKS, -slen);
-               XFS_STATS_INC(xs_allocx);
-               XFS_STATS_ADD(xs_allocb, args->len);
+       ASSERT(args->len >= args->minlen);
+       ASSERT(args->len <= args->maxlen);
+       ASSERT(!args->wasfromfl || !args->isfl);
+       ASSERT(args->agbno % args->alignment == 0);
+
+       if (!args->wasfromfl) {
+               error = xfs_alloc_update_counters(args->tp, args->pag,
+                                                 args->agbp,
+                                                 -((long)(args->len)));
+               if (error)
+                       return error;
+
+               /*
+                * Search the busylist for these blocks and mark the
+                * transaction as synchronous if blocks are found. This
+                * avoids the need to block due to a synchronous log
+                * force to ensure correct ordering as the synchronous
+                * transaction will guarantee that for us.
+                */
+               if (xfs_alloc_busy_search(args->mp, args->agno,
+                                       args->agbno, args->len))
+                       xfs_trans_set_sync(args->tp);
        }
-       return 0;
+
+       if (!args->isfl) {
+               xfs_trans_mod_sb(args->tp, args->wasdel ?
+                                XFS_TRANS_SB_RES_FDBLOCKS :
+                                XFS_TRANS_SB_FDBLOCKS,
+                                -((long)(args->len)));
+       }
+
+       XFS_STATS_INC(xs_allocx);
+       XFS_STATS_ADD(xs_allocb, args->len);
+       return error;
 }
 
 /*
@@ -693,8 +708,7 @@ xfs_alloc_find_best_extent(
                if (error)
                        goto error0;
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-               xfs_alloc_compute_aligned(*sbno, *slen, args->alignment,
-                                         args->minlen, &bno, slena);
+               xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena);
 
                /*
                 * The good extent is closer than this one.
@@ -866,8 +880,8 @@ xfs_alloc_ag_vextent_near(
                        if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno, &ltlen, &i)))
                                goto error0;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-                       xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
-                                       args->minlen, &ltbnoa, &ltlena);
+                       xfs_alloc_compute_aligned(args, ltbno, ltlen,
+                                                 &ltbnoa, &ltlena);
                        if (ltlena < args->minlen)
                                continue;
                        args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
@@ -987,8 +1001,8 @@ xfs_alloc_ag_vextent_near(
                        if ((error = xfs_alloc_get_rec(bno_cur_lt, &ltbno, &ltlen, &i)))
                                goto error0;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-                       xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
-                                       args->minlen, &ltbnoa, &ltlena);
+                       xfs_alloc_compute_aligned(args, ltbno, ltlen,
+                                                 &ltbnoa, &ltlena);
                        if (ltlena >= args->minlen)
                                break;
                        if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i)))
@@ -1003,8 +1017,8 @@ xfs_alloc_ag_vextent_near(
                        if ((error = xfs_alloc_get_rec(bno_cur_gt, &gtbno, &gtlen, &i)))
                                goto error0;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-                       xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment,
-                                       args->minlen, &gtbnoa, &gtlena);
+                       xfs_alloc_compute_aligned(args, gtbno, gtlen,
+                                                 &gtbnoa, &gtlena);
                        if (gtlena >= args->minlen)
                                break;
                        if ((error = xfs_btree_increment(bno_cur_gt, 0, &i)))
@@ -1183,8 +1197,7 @@ xfs_alloc_ag_vextent_size(
         * once aligned; if not, we search left for something better.
         * This can't happen in the second case above.
         */
-       xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen,
-               &rbno, &rlen);
+       xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen);
        rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
        XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
                        (rlen <= flen && rbno + rlen <= fbno + flen), error0);
@@ -1209,8 +1222,8 @@ xfs_alloc_ag_vextent_size(
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
                        if (flen < bestrlen)
                                break;
-                       xfs_alloc_compute_aligned(fbno, flen, args->alignment,
-                               args->minlen, &rbno, &rlen);
+                       xfs_alloc_compute_aligned(args, fbno, flen,
+                                                 &rbno, &rlen);
                        rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
                        XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
                                (rlen <= flen && rbno + rlen <= fbno + flen),
@@ -1388,6 +1401,7 @@ xfs_free_ag_extent(
        xfs_mount_t     *mp;            /* mount point struct for filesystem */
        xfs_agblock_t   nbno;           /* new starting block of freespace */
        xfs_extlen_t    nlen;           /* new length of freespace */
+       xfs_perag_t     *pag;           /* per allocation group data */
 
        mp = tp->t_mountp;
        /*
@@ -1586,30 +1600,20 @@ xfs_free_ag_extent(
        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
        xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
        cnt_cur = NULL;
+
        /*
         * Update the freespace totals in the ag and superblock.
         */
-       {
-               xfs_agf_t       *agf;
-               xfs_perag_t     *pag;           /* per allocation group data */
-
-               pag = xfs_perag_get(mp, agno);
-               pag->pagf_freeblks += len;
-               xfs_perag_put(pag);
-
-               agf = XFS_BUF_TO_AGF(agbp);
-               be32_add_cpu(&agf->agf_freeblks, len);
-               xfs_trans_agblocks_delta(tp, len);
-               XFS_WANT_CORRUPTED_GOTO(
-                       be32_to_cpu(agf->agf_freeblks) <=
-                       be32_to_cpu(agf->agf_length),
-                       error0);
-               xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
-               if (!isfl)
-                       xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
-               XFS_STATS_INC(xs_freex);
-               XFS_STATS_ADD(xs_freeb, len);
-       }
+       pag = xfs_perag_get(mp, agno);
+       error = xfs_alloc_update_counters(tp, pag, agbp, len);
+       xfs_perag_put(pag);
+       if (error)
+               goto error0;
+
+       if (!isfl)
+               xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
+       XFS_STATS_INC(xs_freex);
+       XFS_STATS_ADD(xs_freeb, len);
 
        trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright);
 
index dc3afd7739ff40754d1e04eda13178acc78ef3c2..fa00788de2f549acf0d51bdb913e64350f703b16 100644 (file)
@@ -2365,6 +2365,13 @@ xfs_bmap_rtalloc(
         */
        if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
                ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
+
+       /*
+        * Lock out other modifications to the RT bitmap inode.
+        */
+       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
        /*
         * If it's an allocation to an empty file at offset 0,
         * pick an extent that will space things out in the rt area.
@@ -3519,7 +3526,7 @@ xfs_bmap_search_extents(
 
        if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
                     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
-               xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+               xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
                                "Access to block zero in inode %llu "
                                "start_block: %llx start_off: %llx "
                                "blkcnt: %llx extent-state: %x lastx: %x\n",
@@ -4193,12 +4200,11 @@ xfs_bmap_read_extents(
                num_recs = xfs_btree_get_numrecs(block);
                if (unlikely(i + num_recs > room)) {
                        ASSERT(i + num_recs <= room);
-                       xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+                       xfs_warn(ip->i_mount,
                                "corrupt dinode %Lu, (btree extents).",
                                (unsigned long long) ip->i_ino);
-                       XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
-                                        XFS_ERRLEVEL_LOW,
-                                       ip->i_mount);
+                       XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)",
+                               XFS_ERRLEVEL_LOW, ip->i_mount, block);
                        goto error0;
                }
                XFS_WANT_CORRUPTED_GOTO(
@@ -5772,7 +5778,7 @@ xfs_check_block(
                        else
                                thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
                        if (*thispa == *pp) {
-                               cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
+                               xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld",
                                        __func__, j, i,
                                        (unsigned long long)be64_to_cpu(*thispa));
                                panic("%s: ptrs are equal in node\n",
@@ -5937,11 +5943,11 @@ xfs_bmap_check_leaf_extents(
        return;
 
 error0:
-       cmn_err(CE_WARN, "%s: at error0", __func__);
+       xfs_warn(mp, "%s: at error0", __func__);
        if (bp_release)
                xfs_trans_brelse(NULL, bp);
 error_norelse:
-       cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
+       xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
                __func__, i);
        panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
        return;
@@ -6144,7 +6150,7 @@ xfs_bmap_punch_delalloc_range(
                if (error) {
                        /* something screwed, just bail */
                        if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                               xfs_alert(ip->i_mount,
                        "Failed delalloc mapping lookup ino %lld fsb %lld.",
                                                ip->i_ino, start_fsb);
                        }
index 6f8c21ce0d6d95fd8c45a5d3eea4ef0240fad1fd..e5413d96f1af90a67831dc2498e8d5fbdd8e42ed 100644 (file)
@@ -130,10 +130,12 @@ xfs_buf_item_log_check(
        orig = bip->bli_orig;
        buffer = XFS_BUF_PTR(bp);
        for (x = 0; x < XFS_BUF_COUNT(bp); x++) {
-               if (orig[x] != buffer[x] && !btst(bip->bli_logged, x))
-                       cmn_err(CE_PANIC,
-       "xfs_buf_item_log_check bip %x buffer %x orig %x index %d",
-                               bip, bp, orig, x);
+               if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) {
+                       xfs_emerg(bp->b_mount,
+                               "%s: bip %x buffer %x orig %x index %d",
+                               __func__, bip, bp, orig, x);
+                       ASSERT(0);
+               }
        }
 }
 #else
@@ -983,10 +985,9 @@ xfs_buf_iodone_callbacks(
        if (XFS_BUF_TARGET(bp) != lasttarg ||
            time_after(jiffies, (lasttime + 5*HZ))) {
                lasttime = jiffies;
-               cmn_err(CE_ALERT, "Device %s, XFS metadata write error"
-                               " block 0x%llx in %s",
+               xfs_alert(mp, "Device %s: metadata write error block 0x%llx",
                        XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
-                     (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname);
+                     (__uint64_t)XFS_BUF_ADDR(bp));
        }
        lasttarg = XFS_BUF_TARGET(bp);
 
index 1c00bedb3175c1f5e58d006b0cdf0c8089bc0df5..6102ac6d1dffb99adf41f7ad9171b618e0ab3ae7 100644 (file)
@@ -1995,13 +1995,12 @@ xfs_da_do_buf(
                error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);
                if (unlikely(error == EFSCORRUPTED)) {
                        if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
-                               cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n",
-                                       (long long)bno);
-                               cmn_err(CE_ALERT, "dir: inode %lld\n",
+                               xfs_alert(mp, "%s: bno %lld dir: inode %lld",
+                                       __func__, (long long)bno,
                                        (long long)dp->i_ino);
                                for (i = 0; i < nmap; i++) {
-                                       cmn_err(CE_ALERT,
-                                               "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
+                                       xfs_alert(mp,
+"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d",
                                                i,
                                                (long long)mapp[i].br_startoff,
                                                (long long)mapp[i].br_startblock,
index e60490bc00a61b6c8bc1bfbe04df4e56e536596c..be628677c2884723c58cce77f6f98af4ff3d1926 100644 (file)
@@ -270,9 +270,9 @@ xfs_swap_extents(
        /* check inode formats now that data is flushed */
        error = xfs_swap_extents_check_format(ip, tip);
        if (error) {
-               xfs_fs_cmn_err(CE_NOTE, mp,
+               xfs_notice(mp,
                    "%s: inode 0x%llx format is incompatible for exchanging.",
-                               __FILE__, ip->i_ino);
+                               __func__, ip->i_ino);
                goto out_unlock;
        }
 
index a1321bc7f19210a3b4bd1d87ec7c9d5eae410b28..dba7a71cedf3e6f903368416554730d9885142ad 100644 (file)
@@ -159,7 +159,7 @@ xfs_dir_ino_validate(
                XFS_AGINO_TO_INO(mp, agno, agino) == ino;
        if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
                        XFS_RANDOM_DIR_INO_VALIDATE))) {
-               xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
+               xfs_warn(mp, "Invalid inode number 0x%Lx",
                                (unsigned long long) ino);
                XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
                return XFS_ERROR(EFSCORRUPTED);
index f9a0864b696afea29fec8567a906ac793c882455..a0aab7d3294fd4874df67f70014f4f5a7df7dcb0 100644 (file)
@@ -899,10 +899,9 @@ xfs_dir2_leafn_rebalance(
        if(blk2->index < 0) {
                state->inleaf = 1;
                blk2->index = 0;
-               cmn_err(CE_ALERT,
-                       "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
-                       "blk1->index %d\n",
-                       blk1->index);
+               xfs_alert(args->dp->i_mount,
+       "%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n",
+                       __func__, blk1->index);
        }
 }
 
@@ -1641,26 +1640,22 @@ xfs_dir2_node_addname_int(
                        }
 
                        if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
-                               cmn_err(CE_ALERT,
-                                       "xfs_dir2_node_addname_int: dir ino "
-                                       "%llu needed freesp block %lld for\n"
-                                       "  data block %lld, got %lld\n"
-                                       "  ifbno %llu lastfbno %d\n",
-                                       (unsigned long long)dp->i_ino,
+                               xfs_alert(mp,
+                       "%s: dir ino " "%llu needed freesp block %lld for\n"
+                       "  data block %lld, got %lld ifbno %llu lastfbno %d",
+                                       __func__, (unsigned long long)dp->i_ino,
                                        (long long)xfs_dir2_db_to_fdb(mp, dbno),
                                        (long long)dbno, (long long)fbno,
                                        (unsigned long long)ifbno, lastfbno);
                                if (fblk) {
-                                       cmn_err(CE_ALERT,
-                                               " fblk 0x%p blkno %llu "
-                                               "index %d magic 0x%x\n",
+                                       xfs_alert(mp,
+                               " fblk 0x%p blkno %llu index %d magic 0x%x",
                                                fblk,
                                                (unsigned long long)fblk->blkno,
                                                fblk->index,
                                                fblk->magic);
                                } else {
-                                       cmn_err(CE_ALERT,
-                                               " ... fblk is NULL\n");
+                                       xfs_alert(mp, " ... fblk is NULL");
                                }
                                XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
                                                 XFS_ERRLEVEL_LOW, mp);
index 4c7db74a05f70ba5359c81ad6480c1d34c86ca01..39f06336b99dd7ae13d86bf216fa146437a9af36 100644 (file)
@@ -48,7 +48,7 @@ xfs_error_trap(int e)
                        break;
                if (e != xfs_etrap[i])
                        continue;
-               cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
+               xfs_notice(NULL, "%s: error %d", __func__, e);
                BUG();
                break;
        }
@@ -74,7 +74,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression,
 
        for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
                if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
-                       cmn_err(CE_WARN,
+                       xfs_warn(NULL,
        "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
                                expression, file, line, xfs_etest_fsname[i]);
                        return 1;
@@ -95,14 +95,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
 
        for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
                if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
-                       cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
+                       xfs_warn(mp, "error tag #%d on", error_tag);
                        return 0;
                }
        }
 
        for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
                if (xfs_etest[i] == 0) {
-                       cmn_err(CE_WARN, "Turned on XFS error tag #%d",
+                       xfs_warn(mp, "Turned on XFS error tag #%d",
                                error_tag);
                        xfs_etest[i] = error_tag;
                        xfs_etest_fsid[i] = fsid;
@@ -114,7 +114,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
                }
        }
 
-       cmn_err(CE_WARN, "error tag overflow, too many turned on");
+       xfs_warn(mp, "error tag overflow, too many turned on");
 
        return 1;
 }
@@ -133,7 +133,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
                if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
                     xfs_etest[i] != 0) {
                        cleared = 1;
-                       cmn_err(CE_WARN, "Clearing XFS error tag #%d",
+                       xfs_warn(mp, "Clearing XFS error tag #%d",
                                xfs_etest[i]);
                        xfs_etest[i] = 0;
                        xfs_etest_fsid[i] = 0LL;
@@ -144,9 +144,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
        }
 
        if (loud || cleared)
-               cmn_err(CE_WARN,
-                       "Cleared all XFS error tags for filesystem \"%s\"",
-                       mp->m_fsname);
+               xfs_warn(mp, "Cleared all XFS error tags for filesystem");
 
        return 0;
 }
@@ -162,9 +160,8 @@ xfs_error_report(
        inst_t                  *ra)
 {
        if (level <= xfs_error_level) {
-               xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
-                           CE_ALERT, mp,
-               "XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
+               xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
+               "Internal error %s at line %d of file %s.  Caller 0x%p\n",
                            tag, linenum, filename, ra);
 
                xfs_stack_trace();
@@ -184,4 +181,5 @@ xfs_corruption_error(
        if (level <= xfs_error_level)
                xfs_hex_dump(p, 16);
        xfs_error_report(tag, level, mp, filename, linenum, ra);
+       xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
 }
index 10dce5475f022061ac95e863b98a07b6c715c21d..079a367f44eeb6f67c16666c695a5fd3a246637d 100644 (file)
@@ -145,10 +145,8 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);
 #endif /* DEBUG */
 
 /*
- * XFS panic tags -- allow a call to xfs_cmn_err() be turned into
- *                     a panic by setting xfs_panic_mask in a
- *                     sysctl.  update xfs_max[XFS_PARAM] if
- *                     more are added.
+ * XFS panic tags -- allow a call to xfs_alert_tag() be turned into
+ *                     a panic by setting xfs_panic_mask in a sysctl.
  */
 #define                XFS_NO_PTAG                     0
 #define                XFS_PTAG_IFLUSH                 0x00000001
@@ -160,17 +158,4 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);
 #define                XFS_PTAG_SHUTDOWN_LOGERROR      0x00000040
 #define                XFS_PTAG_FSBLOCK_ZERO           0x00000080
 
-struct xfs_mount;
-
-extern void xfs_hex_dump(void *p, int length);
-
-#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
-       xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
-
-#define xfs_fs_mount_cmn_err(f, fmt, args...) \
-       do { \
-               if (!(f & XFS_MFSI_QUIET))      \
-                       cmn_err(CE_WARN, "XFS: " fmt, ## args); \
-       } while (0)
-
 #endif /* __XFS_ERROR_H__ */
index 85668efb3e3e03221b5e6dd3f517ad2e38b16f94..9153d2c77caf2856ea636bb76d317f2ef1a8676e 100644 (file)
@@ -385,8 +385,8 @@ xfs_growfs_data_private(
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
                                  XFS_FSS_TO_BB(mp, 1), 0, &bp);
                if (error) {
-                       xfs_fs_cmn_err(CE_WARN, mp,
-                       "error %d reading secondary superblock for ag %d",
+                       xfs_warn(mp,
+               "error %d reading secondary superblock for ag %d",
                                error, agno);
                        break;
                }
@@ -399,7 +399,7 @@ xfs_growfs_data_private(
                if (!(error = xfs_bwrite(mp, bp))) {
                        continue;
                } else {
-                       xfs_fs_cmn_err(CE_WARN, mp,
+                       xfs_warn(mp,
                "write error %d updating secondary superblock for ag %d",
                                error, agno);
                        break; /* no point in continuing */
index 0626a32c3447a4e8ab4a3676ba5aad9e35cd1f0a..84ebeec16642155d3bf5faf48b3443585504389a 100644 (file)
@@ -1055,28 +1055,23 @@ xfs_difree(
         */
        agno = XFS_INO_TO_AGNO(mp, inode);
        if (agno >= mp->m_sb.sb_agcount)  {
-               cmn_err(CE_WARN,
-                       "xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s.  Returning EINVAL.",
-                       agno, mp->m_sb.sb_agcount, mp->m_fsname);
+               xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
+                       __func__, agno, mp->m_sb.sb_agcount);
                ASSERT(0);
                return XFS_ERROR(EINVAL);
        }
        agino = XFS_INO_TO_AGINO(mp, inode);
        if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
-               cmn_err(CE_WARN,
-                       "xfs_difree: inode != XFS_AGINO_TO_INO() "
-                       "(%llu != %llu) on %s.  Returning EINVAL.",
-                       (unsigned long long)inode,
-                       (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino),
-                       mp->m_fsname);
+               xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
+                       __func__, (unsigned long long)inode,
+                       (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));
                ASSERT(0);
                return XFS_ERROR(EINVAL);
        }
        agbno = XFS_AGINO_TO_AGBNO(mp, agino);
        if (agbno >= mp->m_sb.sb_agblocks)  {
-               cmn_err(CE_WARN,
-                       "xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s.  Returning EINVAL.",
-                       agbno, mp->m_sb.sb_agblocks, mp->m_fsname);
+               xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
+                       __func__, agbno, mp->m_sb.sb_agblocks);
                ASSERT(0);
                return XFS_ERROR(EINVAL);
        }
@@ -1085,9 +1080,8 @@ xfs_difree(
         */
        error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
        if (error) {
-               cmn_err(CE_WARN,
-                       "xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s.  Returning error.",
-                       error, mp->m_fsname);
+               xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
+                       __func__, error);
                return error;
        }
        agi = XFS_BUF_TO_AGI(agbp);
@@ -1106,17 +1100,15 @@ xfs_difree(
         * Look for the entry describing this inode.
         */
        if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) {
-               cmn_err(CE_WARN,
-                       "xfs_difree: xfs_inobt_lookup returned()  an error %d on %s.  Returning error.",
-                       error, mp->m_fsname);
+               xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.",
+                       __func__, error);
                goto error0;
        }
        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
        error = xfs_inobt_get_rec(cur, &rec, &i);
        if (error) {
-               cmn_err(CE_WARN,
-                       "xfs_difree: xfs_inobt_get_rec()  returned an error %d on %s.  Returning error.",
-                       error, mp->m_fsname);
+               xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.",
+                       __func__, error);
                goto error0;
        }
        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
@@ -1157,8 +1149,8 @@ xfs_difree(
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
 
                if ((error = xfs_btree_delete(cur, &i))) {
-                       cmn_err(CE_WARN, "xfs_difree: xfs_btree_delete returned an error %d on %s.\n",
-                               error, mp->m_fsname);
+                       xfs_warn(mp, "%s: xfs_btree_delete returned error %d.",
+                               __func__, error);
                        goto error0;
                }
 
@@ -1170,9 +1162,8 @@ xfs_difree(
 
                error = xfs_inobt_update(cur, &rec);
                if (error) {
-                       cmn_err(CE_WARN,
-       "xfs_difree: xfs_inobt_update returned an error %d on %s.",
-                               error, mp->m_fsname);
+                       xfs_warn(mp, "%s: xfs_inobt_update returned error %d.",
+                               __func__, error);
                        goto error0;
                }
 
@@ -1218,10 +1209,9 @@ xfs_imap_lookup(
 
        error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
        if (error) {
-               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                               "xfs_ialloc_read_agi() returned "
-                               "error %d, agno %d",
-                               error, agno);
+               xfs_alert(mp,
+                       "%s: xfs_ialloc_read_agi() returned error %d, agno %d",
+                       __func__, error, agno);
                return error;
        }
 
@@ -1299,24 +1289,21 @@ xfs_imap(
                if (flags & XFS_IGET_UNTRUSTED)
                        return XFS_ERROR(EINVAL);
                if (agno >= mp->m_sb.sb_agcount) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                                       "xfs_imap: agno (%d) >= "
-                                       "mp->m_sb.sb_agcount (%d)",
-                                       agno,  mp->m_sb.sb_agcount);
+                       xfs_alert(mp,
+                               "%s: agno (%d) >= mp->m_sb.sb_agcount (%d)",
+                               __func__, agno, mp->m_sb.sb_agcount);
                }
                if (agbno >= mp->m_sb.sb_agblocks) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                                       "xfs_imap: agbno (0x%llx) >= "
-                                       "mp->m_sb.sb_agblocks (0x%lx)",
-                                       (unsigned long long) agbno,
-                                       (unsigned long) mp->m_sb.sb_agblocks);
+                       xfs_alert(mp,
+               "%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
+                               __func__, (unsigned long long)agbno,
+                               (unsigned long)mp->m_sb.sb_agblocks);
                }
                if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                                       "xfs_imap: ino (0x%llx) != "
-                                       "XFS_AGINO_TO_INO(mp, agno, agino) "
-                                       "(0x%llx)",
-                                       ino, XFS_AGINO_TO_INO(mp, agno, agino));
+                       xfs_alert(mp,
+               "%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)",
+                               __func__, ino,
+                               XFS_AGINO_TO_INO(mp, agno, agino));
                }
                xfs_stack_trace();
 #endif /* DEBUG */
@@ -1388,10 +1375,9 @@ out_map:
         */
        if ((imap->im_blkno + imap->im_len) >
            XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
-               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                       "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
-                       " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
-                       (unsigned long long) imap->im_blkno,
+               xfs_alert(mp,
+       "%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)",
+                       __func__, (unsigned long long) imap->im_blkno,
                        (unsigned long long) imap->im_len,
                        XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
                return XFS_ERROR(EINVAL);
index be7cf625421f15a50a739af9dfc1166981a3fd06..da871f5322368dffac20f1514a5966a45f26061e 100644 (file)
@@ -110,8 +110,8 @@ xfs_inobp_check(
                dip = (xfs_dinode_t *)xfs_buf_offset(bp,
                                        i * mp->m_sb.sb_inodesize);
                if (!dip->di_next_unlinked)  {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "Detected a bogus zero next_unlinked field in incore inode buffer 0x%p.  About to pop an ASSERT.",
+                       xfs_alert(mp,
+       "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.",
                                bp);
                        ASSERT(dip->di_next_unlinked);
                }
@@ -142,10 +142,9 @@ xfs_imap_to_bp(
                                   (int)imap->im_len, buf_flags, &bp);
        if (error) {
                if (error != EAGAIN) {
-                       cmn_err(CE_WARN,
-                               "xfs_imap_to_bp: xfs_trans_read_buf()returned "
-                               "an error %d on %s.  Returning error.",
-                               error, mp->m_fsname);
+                       xfs_warn(mp,
+                               "%s: xfs_trans_read_buf() returned error %d.",
+                               __func__, error);
                } else {
                        ASSERT(buf_flags & XBF_TRYLOCK);
                }
@@ -180,12 +179,11 @@ xfs_imap_to_bp(
                        XFS_CORRUPTION_ERROR("xfs_imap_to_bp",
                                                XFS_ERRLEVEL_HIGH, mp, dip);
 #ifdef DEBUG
-                       cmn_err(CE_PANIC,
-                                       "Device %s - bad inode magic/vsn "
-                                       "daddr %lld #%d (magic=%x)",
-                               XFS_BUFTARG_NAME(mp->m_ddev_targp),
+                       xfs_emerg(mp,
+                               "bad inode magic/vsn daddr %lld #%d (magic=%x)",
                                (unsigned long long)imap->im_blkno, i,
                                be16_to_cpu(dip->di_magic));
+                       ASSERT(0);
 #endif
                        xfs_trans_brelse(tp, bp);
                        return XFS_ERROR(EFSCORRUPTED);
@@ -317,7 +315,7 @@ xfs_iformat(
        if (unlikely(be32_to_cpu(dip->di_nextents) +
                     be16_to_cpu(dip->di_anextents) >
                     be64_to_cpu(dip->di_nblocks))) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+               xfs_warn(ip->i_mount,
                        "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
                        (unsigned long long)ip->i_ino,
                        (int)(be32_to_cpu(dip->di_nextents) +
@@ -330,8 +328,7 @@ xfs_iformat(
        }
 
        if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                       "corrupt dinode %Lu, forkoff = 0x%x.",
+               xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.",
                        (unsigned long long)ip->i_ino,
                        dip->di_forkoff);
                XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
@@ -341,7 +338,7 @@ xfs_iformat(
 
        if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) &&
                     !ip->i_mount->m_rtdev_targp)) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+               xfs_warn(ip->i_mount,
                        "corrupt dinode %Lu, has realtime flag set.",
                        ip->i_ino);
                XFS_CORRUPTION_ERROR("xfs_iformat(realtime)",
@@ -373,9 +370,8 @@ xfs_iformat(
                         * no local regular files yet
                         */
                        if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) {
-                               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                                       "corrupt inode %Lu "
-                                       "(local format for regular file).",
+                               xfs_warn(ip->i_mount,
+                       "corrupt inode %Lu (local format for regular file).",
                                        (unsigned long long) ip->i_ino);
                                XFS_CORRUPTION_ERROR("xfs_iformat(4)",
                                                     XFS_ERRLEVEL_LOW,
@@ -385,9 +381,8 @@ xfs_iformat(
 
                        di_size = be64_to_cpu(dip->di_size);
                        if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
-                               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                                       "corrupt inode %Lu "
-                                       "(bad size %Ld for local inode).",
+                               xfs_warn(ip->i_mount,
+                       "corrupt inode %Lu (bad size %Ld for local inode).",
                                        (unsigned long long) ip->i_ino,
                                        (long long) di_size);
                                XFS_CORRUPTION_ERROR("xfs_iformat(5)",
@@ -431,9 +426,8 @@ xfs_iformat(
                size = be16_to_cpu(atp->hdr.totsize);
 
                if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) {
-                       xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                               "corrupt inode %Lu "
-                               "(bad attr fork size %Ld).",
+                       xfs_warn(ip->i_mount,
+                               "corrupt inode %Lu (bad attr fork size %Ld).",
                                (unsigned long long) ip->i_ino,
                                (long long) size);
                        XFS_CORRUPTION_ERROR("xfs_iformat(8)",
@@ -488,9 +482,8 @@ xfs_iformat_local(
         * kmem_alloc() or memcpy() below.
         */
        if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                       "corrupt inode %Lu "
-                       "(bad size %d for local fork, size = %d).",
+               xfs_warn(ip->i_mount,
+       "corrupt inode %Lu (bad size %d for local fork, size = %d).",
                        (unsigned long long) ip->i_ino, size,
                        XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
                XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
@@ -547,8 +540,7 @@ xfs_iformat_extents(
         * kmem_alloc() or memcpy() below.
         */
        if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                       "corrupt inode %Lu ((a)extents = %d).",
+               xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
                        (unsigned long long) ip->i_ino, nex);
                XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
                                     ip->i_mount, dip);
@@ -623,11 +615,10 @@ xfs_iformat_btree(
            || XFS_BMDR_SPACE_CALC(nrecs) >
                        XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
            || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
-               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-                       "corrupt inode %Lu (btree).",
+               xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).",
                        (unsigned long long) ip->i_ino);
-               XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
-                                ip->i_mount);
+               XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
+                                ip->i_mount, dip);
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -813,11 +804,9 @@ xfs_iread(
         */
        if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) {
 #ifdef DEBUG
-               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-                               "dip->di_magic (0x%x) != "
-                               "XFS_DINODE_MAGIC (0x%x)",
-                               be16_to_cpu(dip->di_magic),
-                               XFS_DINODE_MAGIC);
+               xfs_alert(mp,
+                       "%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)",
+                       __func__, be16_to_cpu(dip->di_magic), XFS_DINODE_MAGIC);
 #endif /* DEBUG */
                error = XFS_ERROR(EINVAL);
                goto out_brelse;
@@ -835,9 +824,8 @@ xfs_iread(
                error = xfs_iformat(ip, dip);
                if (error)  {
 #ifdef DEBUG
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-                                       "xfs_iformat() returned error %d",
-                                       error);
+                       xfs_alert(mp, "%s: xfs_iformat() returned error %d",
+                               __func__, error);
 #endif /* DEBUG */
                        goto out_brelse;
                }
@@ -1016,8 +1004,8 @@ xfs_ialloc(
         * This is because we're setting fields here we need
         * to prevent others from looking at until we're done.
         */
-       error = xfs_trans_iget(tp->t_mountp, tp, ino,
-                               XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip);
+       error = xfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE,
+                        XFS_ILOCK_EXCL, &ip);
        if (error)
                return error;
        ASSERT(ip != NULL);
@@ -1166,6 +1154,7 @@ xfs_ialloc(
        /*
         * Log the new values stuffed into the inode.
         */
+       xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_log_inode(tp, ip, flags);
 
        /* now that we have an i_mode we can setup inode ops and unlock */
@@ -1820,9 +1809,8 @@ xfs_iunlink_remove(
                 */
                error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
                if (error) {
-                       cmn_err(CE_WARN,
-                               "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
-                               error, mp->m_fsname);
+                       xfs_warn(mp, "%s: xfs_itobp() returned error %d.",
+                               __func__, error);
                        return error;
                }
                next_agino = be32_to_cpu(dip->di_next_unlinked);
@@ -1867,9 +1855,9 @@ xfs_iunlink_remove(
                        error = xfs_inotobp(mp, tp, next_ino, &last_dip,
                                            &last_ibp, &last_offset, 0);
                        if (error) {
-                               cmn_err(CE_WARN,
-                       "xfs_iunlink_remove: xfs_inotobp()  returned an error %d on %s.  Returning error.",
-                                       error, mp->m_fsname);
+                               xfs_warn(mp,
+                                       "%s: xfs_inotobp() returned error %d.",
+                                       __func__, error);
                                return error;
                        }
                        next_agino = be32_to_cpu(last_dip->di_next_unlinked);
@@ -1882,9 +1870,8 @@ xfs_iunlink_remove(
                 */
                error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
                if (error) {
-                       cmn_err(CE_WARN,
-                               "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
-                               error, mp->m_fsname);
+                       xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.",
+                               __func__, error);
                        return error;
                }
                next_agino = be32_to_cpu(dip->di_next_unlinked);
@@ -2939,16 +2926,16 @@ xfs_iflush_int(
 
        if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
                               mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
-               xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                   "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p",
-                       ip->i_ino, be16_to_cpu(dip->di_magic), dip);
+               xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                       "%s: Bad inode %Lu magic number 0x%x, ptr 0x%p",
+                       __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);
                goto corrupt_out;
        }
        if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,
                                mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) {
-               xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                       "xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
-                       ip->i_ino, ip, ip->i_d.di_magic);
+               xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                       "%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
+                       __func__, ip->i_ino, ip, ip->i_d.di_magic);
                goto corrupt_out;
        }
        if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
@@ -2956,9 +2943,9 @@ xfs_iflush_int(
                    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
                    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
                    mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) {
-                       xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                               "xfs_iflush: Bad regular inode %Lu, ptr 0x%p",
-                               ip->i_ino, ip);
+                       xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                               "%s: Bad regular inode %Lu, ptr 0x%p",
+                               __func__, ip->i_ino, ip);
                        goto corrupt_out;
                }
        } else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
@@ -2967,28 +2954,28 @@ xfs_iflush_int(
                    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
                    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
                    mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) {
-                       xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                               "xfs_iflush: Bad directory inode %Lu, ptr 0x%p",
-                               ip->i_ino, ip);
+                       xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                               "%s: Bad directory inode %Lu, ptr 0x%p",
+                               __func__, ip->i_ino, ip);
                        goto corrupt_out;
                }
        }
        if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
                                ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5,
                                XFS_RANDOM_IFLUSH_5)) {
-               xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                       "xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p",
-                       ip->i_ino,
+               xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                       "%s: detected corrupt incore inode %Lu, "
+                       "total extents = %d, nblocks = %Ld, ptr 0x%p",
+                       __func__, ip->i_ino,
                        ip->i_d.di_nextents + ip->i_d.di_anextents,
-                       ip->i_d.di_nblocks,
-                       ip);
+                       ip->i_d.di_nblocks, ip);
                goto corrupt_out;
        }
        if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize,
                                mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) {
-               xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-                       "xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p",
-                       ip->i_ino, ip->i_d.di_forkoff, ip);
+               xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+                       "%s: bad inode %Lu, forkoff 0x%x, ptr 0x%p",
+                       __func__, ip->i_ino, ip->i_d.di_forkoff, ip);
                goto corrupt_out;
        }
        /*
index 5c95fa8ec11da9c703f756b4dbe42e81a569a6ac..f753200cef8d365593e9a0c1c1b155e968f3f8f8 100644 (file)
@@ -409,28 +409,35 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
 /*
  * Flags for lockdep annotations.
  *
- * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes
- * (ie directory operations that require locking a directory inode and
- * an entry inode).  The first inode gets locked with this flag so it
- * gets a lockdep subclass of 1 and the second lock will have a lockdep
- * subclass of 0.
+ * XFS_LOCK_PARENT - for directory operations that require locking a
+ * parent directory inode and a child entry inode.  The parent gets locked
+ * with this flag so it gets a lockdep subclass of 1 and the child entry
+ * lock will have a lockdep subclass of 0.
+ *
+ * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary
+ * inodes do not participate in the normal lock order, and thus have their
+ * own subclasses.
  *
  * XFS_LOCK_INUMORDER - for locking several inodes at the some time
  * with xfs_lock_inodes().  This flag is used as the starting subclass
  * and each subsequent lock acquired will increment the subclass by one.
- * So the first lock acquired will have a lockdep subclass of 2, the
- * second lock will have a lockdep subclass of 3, and so on. It is
+ * So the first lock acquired will have a lockdep subclass of 4, the
+ * second lock will have a lockdep subclass of 5, and so on. It is
  * the responsibility of the class builder to shift this to the correct
  * portion of the lock_mode lockdep mask.
  */
 #define XFS_LOCK_PARENT                1
-#define XFS_LOCK_INUMORDER     2
+#define XFS_LOCK_RTBITMAP      2
+#define XFS_LOCK_RTSUM         3
+#define XFS_LOCK_INUMORDER     4
 
 #define XFS_IOLOCK_SHIFT       16
 #define        XFS_IOLOCK_PARENT       (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
 
 #define XFS_ILOCK_SHIFT                24
 #define        XFS_ILOCK_PARENT        (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
+#define        XFS_ILOCK_RTBITMAP      (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT)
+#define        XFS_ILOCK_RTSUM         (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT)
 
 #define XFS_IOLOCK_DEP_MASK    0x00ff0000
 #define XFS_ILOCK_DEP_MASK     0xff000000
index 8a0f044750c3207eff174c4137bcd77580465894..091d82b94c4de518208d8eebc37abe4a7f3d4f1d 100644 (file)
@@ -101,11 +101,11 @@ xfs_iomap_eof_align_last_fsb(
 }
 
 STATIC int
-xfs_cmn_err_fsblock_zero(
+xfs_alert_fsblock_zero(
        xfs_inode_t     *ip,
        xfs_bmbt_irec_t *imap)
 {
-       xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+       xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
                        "Access to block zero in inode %llu "
                        "start_block: %llx start_off: %llx "
                        "blkcnt: %llx extent-state: %x\n",
@@ -246,7 +246,7 @@ xfs_iomap_write_direct(
        }
 
        if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) {
-               error = xfs_cmn_err_fsblock_zero(ip, imap);
+               error = xfs_alert_fsblock_zero(ip, imap);
                goto error_out;
        }
 
@@ -464,7 +464,7 @@ retry:
        }
 
        if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
-               return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
+               return xfs_alert_fsblock_zero(ip, &imap[0]);
 
        *ret_imap = imap[0];
        return 0;
@@ -614,7 +614,7 @@ xfs_iomap_write_allocate(
                 * covers at least part of the callers request
                 */
                if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
-                       return xfs_cmn_err_fsblock_zero(ip, imap);
+                       return xfs_alert_fsblock_zero(ip, imap);
 
                if ((offset_fsb >= imap->br_startoff) &&
                    (offset_fsb < (imap->br_startoff +
@@ -724,7 +724,7 @@ xfs_iomap_write_unwritten(
                        return XFS_ERROR(error);
 
                if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
-                       return xfs_cmn_err_fsblock_zero(ip, &imap);
+                       return xfs_alert_fsblock_zero(ip, &imap);
 
                if ((numblks_fsb = imap.br_blockcount) == 0) {
                        /*
index ae6fef1ff563e19ceb6b97393ed3ec8804c110b5..25efa9b8a6029ac35df73942459132abd71dc228 100644 (file)
@@ -374,11 +374,10 @@ xfs_log_mount(
        int             error;
 
        if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
-               cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
+               xfs_notice(mp, "Mounting Filesystem");
        else {
-               cmn_err(CE_NOTE,
-                       "Mounting filesystem \"%s\" in no-recovery mode.  Filesystem will be inconsistent.",
-                       mp->m_fsname);
+               xfs_notice(mp,
+"Mounting filesystem in no-recovery mode.  Filesystem will be inconsistent.");
                ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
        }
 
@@ -393,7 +392,7 @@ xfs_log_mount(
         */
        error = xfs_trans_ail_init(mp);
        if (error) {
-               cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
+               xfs_warn(mp, "AIL initialisation failed: error %d", error);
                goto out_free_log;
        }
        mp->m_log->l_ailp = mp->m_ail;
@@ -413,7 +412,8 @@ xfs_log_mount(
                if (readonly)
                        mp->m_flags |= XFS_MOUNT_RDONLY;
                if (error) {
-                       cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
+                       xfs_warn(mp, "log mount/recovery failed: error %d",
+                               error);
                        goto out_destroy_ail;
                }
        }
@@ -542,10 +542,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                         */
                }
 
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "xfs_log_unmount: unmount record failed");
-               }
+               if (error)
+                       xfs_alert(mp, "%s: unmount record failed", __func__);
 
 
                spin_lock(&log->l_icloglock);
@@ -852,7 +850,7 @@ xlog_space_left(
                 * In this case we just want to return the size of the
                 * log as the amount of space left.
                 */
-               xfs_fs_cmn_err(CE_ALERT, log->l_mp,
+               xfs_alert(log->l_mp,
                        "xlog_space_left: head behind tail\n"
                        "  tail_cycle = %d, tail_bytes = %d\n"
                        "  GH   cycle = %d, GH   bytes = %d",
@@ -1001,7 +999,7 @@ xlog_alloc_log(xfs_mount_t *mp,
 
        log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
        if (!log) {
-               xlog_warn("XFS: Log allocation failed: No memory!");
+               xfs_warn(mp, "Log allocation failed: No memory!");
                goto out;
        }
 
@@ -1029,24 +1027,24 @@ xlog_alloc_log(xfs_mount_t      *mp,
        if (xfs_sb_version_hassector(&mp->m_sb)) {
                log2_size = mp->m_sb.sb_logsectlog;
                if (log2_size < BBSHIFT) {
-                       xlog_warn("XFS: Log sector size too small "
-                               "(0x%x < 0x%x)", log2_size, BBSHIFT);
+                       xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)",
+                               log2_size, BBSHIFT);
                        goto out_free_log;
                }
 
                log2_size -= BBSHIFT;
                if (log2_size > mp->m_sectbb_log) {
-                       xlog_warn("XFS: Log sector size too large "
-                               "(0x%x > 0x%x)", log2_size, mp->m_sectbb_log);
+                       xfs_warn(mp, "Log sector size too large (0x%x > 0x%x)",
+                               log2_size, mp->m_sectbb_log);
                        goto out_free_log;
                }
 
                /* for larger sector sizes, must have v2 or external log */
                if (log2_size && log->l_logBBstart > 0 &&
                            !xfs_sb_version_haslogv2(&mp->m_sb)) {
-
-                       xlog_warn("XFS: log sector size (0x%x) invalid "
-                                 "for configuration.", log2_size);
+                       xfs_warn(mp,
+               "log sector size (0x%x) invalid for configuration.",
+                               log2_size);
                        goto out_free_log;
                }
        }
@@ -1563,38 +1561,36 @@ xlog_print_tic_res(
            "SWAPEXT"
        };
 
-       xfs_fs_cmn_err(CE_WARN, mp,
-                       "xfs_log_write: reservation summary:\n"
-                       "  trans type  = %s (%u)\n"
-                       "  unit res    = %d bytes\n"
-                       "  current res = %d bytes\n"
-                       "  total reg   = %u bytes (o/flow = %u bytes)\n"
-                       "  ophdrs      = %u (ophdr space = %u bytes)\n"
-                       "  ophdr + reg = %u bytes\n"
-                       "  num regions = %u\n",
-                       ((ticket->t_trans_type <= 0 ||
-                         ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
-                         "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
-                       ticket->t_trans_type,
-                       ticket->t_unit_res,
-                       ticket->t_curr_res,
-                       ticket->t_res_arr_sum, ticket->t_res_o_flow,
-                       ticket->t_res_num_ophdrs, ophdr_spc,
-                       ticket->t_res_arr_sum + 
-                       ticket->t_res_o_flow + ophdr_spc,
-                       ticket->t_res_num);
+       xfs_warn(mp,
+               "xfs_log_write: reservation summary:\n"
+               "  trans type  = %s (%u)\n"
+               "  unit res    = %d bytes\n"
+               "  current res = %d bytes\n"
+               "  total reg   = %u bytes (o/flow = %u bytes)\n"
+               "  ophdrs      = %u (ophdr space = %u bytes)\n"
+               "  ophdr + reg = %u bytes\n"
+               "  num regions = %u\n",
+               ((ticket->t_trans_type <= 0 ||
+                 ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
+                 "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
+               ticket->t_trans_type,
+               ticket->t_unit_res,
+               ticket->t_curr_res,
+               ticket->t_res_arr_sum, ticket->t_res_o_flow,
+               ticket->t_res_num_ophdrs, ophdr_spc,
+               ticket->t_res_arr_sum +
+               ticket->t_res_o_flow + ophdr_spc,
+               ticket->t_res_num);
 
        for (i = 0; i < ticket->t_res_num; i++) {
-               uint r_type = ticket->t_res_arr[i].r_type; 
-               cmn_err(CE_WARN,
-                           "region[%u]: %s - %u bytes\n",
-                           i, 
+               uint r_type = ticket->t_res_arr[i].r_type;
+               xfs_warn(mp, "region[%u]: %s - %u bytes\n", i,
                            ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
                            "bad-rtype" : res_type_str[r_type-1]),
                            ticket->t_res_arr[i].r_len);
        }
 
-       xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
+       xfs_alert_tag(mp, XFS_PTAG_LOGRES,
                "xfs_log_write: reservation ran out. Need to up reservation");
        xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 }
@@ -1682,7 +1678,7 @@ xlog_write_setup_ophdr(
        case XFS_LOG:
                break;
        default:
-               xfs_fs_cmn_err(CE_WARN, log->l_mp,
+               xfs_warn(log->l_mp,
                        "Bad XFS transaction clientid 0x%x in ticket 0x%p",
                        ophdr->oh_clientid, ticket);
                return NULL;
@@ -2264,7 +2260,7 @@ xlog_state_do_callback(
                if (repeats > 5000) {
                        flushcnt += repeats;
                        repeats = 0;
-                       xfs_fs_cmn_err(CE_WARN, log->l_mp,
+                       xfs_warn(log->l_mp,
                                "%s: possible infinite loop (%d iterations)",
                                __func__, flushcnt);
                }
@@ -3052,10 +3048,8 @@ xfs_log_force(
        int     error;
 
        error = _xfs_log_force(mp, flags, NULL);
-       if (error) {
-               xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
-                       "error %d returned.", error);
-       }
+       if (error)
+               xfs_warn(mp, "%s: error %d returned.", __func__, error);
 }
 
 /*
@@ -3204,10 +3198,8 @@ xfs_log_force_lsn(
        int     error;
 
        error = _xfs_log_force_lsn(mp, lsn, flags, NULL);
-       if (error) {
-               xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
-                       "error %d returned.", error);
-       }
+       if (error)
+               xfs_warn(mp, "%s: error %d returned.", __func__, error);
 }
 
 /*
@@ -3412,7 +3404,7 @@ xlog_verify_dest_ptr(
        }
 
        if (!good_ptr)
-               xlog_panic("xlog_verify_dest_ptr: invalid ptr");
+               xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);
 }
 
 STATIC void
@@ -3448,16 +3440,16 @@ xlog_verify_tail_lsn(xlog_t         *log,
        blocks =
            log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));
        if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize))
-           xlog_panic("xlog_verify_tail_lsn: ran out of log space");
+               xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);
     } else {
        ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);
 
        if (BLOCK_LSN(tail_lsn) == log->l_prev_block)
-           xlog_panic("xlog_verify_tail_lsn: tail wrapped");
+               xfs_emerg(log->l_mp, "%s: tail wrapped", __func__);
 
        blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;
        if (blocks < BTOBB(iclog->ic_offset) + 1)
-           xlog_panic("xlog_verify_tail_lsn: ran out of log space");
+               xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);
     }
 }      /* xlog_verify_tail_lsn */
 
@@ -3497,22 +3489,23 @@ xlog_verify_iclog(xlog_t         *log,
        icptr = log->l_iclog;
        for (i=0; i < log->l_iclog_bufs; i++) {
                if (icptr == NULL)
-                       xlog_panic("xlog_verify_iclog: invalid ptr");
+                       xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);
                icptr = icptr->ic_next;
        }
        if (icptr != log->l_iclog)
-               xlog_panic("xlog_verify_iclog: corrupt iclog ring");
+               xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__);
        spin_unlock(&log->l_icloglock);
 
        /* check log magic numbers */
        if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM)
-               xlog_panic("xlog_verify_iclog: invalid magic num");
+               xfs_emerg(log->l_mp, "%s: invalid magic num", __func__);
 
        ptr = (xfs_caddr_t) &iclog->ic_header;
        for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;
             ptr += BBSIZE) {
                if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
-                       xlog_panic("xlog_verify_iclog: unexpected magic num");
+                       xfs_emerg(log->l_mp, "%s: unexpected magic num",
+                               __func__);
        }
 
        /* check fields */
@@ -3542,9 +3535,10 @@ xlog_verify_iclog(xlog_t  *log,
                        }
                }
                if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
-                       cmn_err(CE_WARN, "xlog_verify_iclog: "
-                               "invalid clientid %d op 0x%p offset 0x%lx",
-                               clientid, ophead, (unsigned long)field_offset);
+                       xfs_warn(log->l_mp,
+                               "%s: invalid clientid %d op 0x%p offset 0x%lx",
+                               __func__, clientid, ophead,
+                               (unsigned long)field_offset);
 
                /* check length */
                field_offset = (__psint_t)
index d5f8be8f4bf603cac8c3f0394759e5fefdd8d42e..15dbf1f9c2be6c962655a84f6a254cc191723cee 100644 (file)
@@ -87,10 +87,6 @@ static inline uint xlog_get_client_id(__be32 i)
        return be32_to_cpu(i) >> 24;
 }
 
-#define xlog_panic(args...)    cmn_err(CE_PANIC, ## args)
-#define xlog_exit(args...)     cmn_err(CE_PANIC, ## args)
-#define xlog_warn(args...)     cmn_err(CE_WARN, ## args)
-
 /*
  * In core log state
  */
index aa0ebb776903317a8d29916396eb547c3ce296c9..0c4a5618e7af769c051da1337f4f338457b14866 100644 (file)
@@ -92,7 +92,7 @@ xlog_get_bp(
        int             nbblks)
 {
        if (!xlog_buf_bbcount_valid(log, nbblks)) {
-               xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+               xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
                        nbblks);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
                return NULL;
@@ -160,7 +160,7 @@ xlog_bread_noalign(
        int             error;
 
        if (!xlog_buf_bbcount_valid(log, nbblks)) {
-               xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+               xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
                        nbblks);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
                return EFSCORRUPTED;
@@ -219,7 +219,7 @@ xlog_bwrite(
        int             error;
 
        if (!xlog_buf_bbcount_valid(log, nbblks)) {
-               xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+               xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
                        nbblks);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
                return EFSCORRUPTED;
@@ -254,9 +254,9 @@ xlog_header_check_dump(
        xfs_mount_t             *mp,
        xlog_rec_header_t       *head)
 {
-       cmn_err(CE_DEBUG, "%s:  SB : uuid = %pU, fmt = %d\n",
+       xfs_debug(mp, "%s:  SB : uuid = %pU, fmt = %d\n",
                __func__, &mp->m_sb.sb_uuid, XLOG_FMT);
-       cmn_err(CE_DEBUG, "    log : uuid = %pU, fmt = %d\n",
+       xfs_debug(mp, "    log : uuid = %pU, fmt = %d\n",
                &head->h_fs_uuid, be32_to_cpu(head->h_fmt));
 }
 #else
@@ -279,15 +279,15 @@ xlog_header_check_recover(
         * a dirty log created in IRIX.
         */
        if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) {
-               xlog_warn(
-       "XFS: dirty log written in incompatible format - can't recover");
+               xfs_warn(mp,
+       "dirty log written in incompatible format - can't recover");
                xlog_header_check_dump(mp, head);
                XFS_ERROR_REPORT("xlog_header_check_recover(1)",
                                 XFS_ERRLEVEL_HIGH, mp);
                return XFS_ERROR(EFSCORRUPTED);
        } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
-               xlog_warn(
-       "XFS: dirty log entry has mismatched uuid - can't recover");
+               xfs_warn(mp,
+       "dirty log entry has mismatched uuid - can't recover");
                xlog_header_check_dump(mp, head);
                XFS_ERROR_REPORT("xlog_header_check_recover(2)",
                                 XFS_ERRLEVEL_HIGH, mp);
@@ -312,9 +312,9 @@ xlog_header_check_mount(
                 * h_fs_uuid is nil, we assume this log was last mounted
                 * by IRIX and continue.
                 */
-               xlog_warn("XFS: nil uuid in log - IRIX style log");
+               xfs_warn(mp, "nil uuid in log - IRIX style log");
        } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
-               xlog_warn("XFS: log has mismatched uuid - can't recover");
+               xfs_warn(mp, "log has mismatched uuid - can't recover");
                xlog_header_check_dump(mp, head);
                XFS_ERROR_REPORT("xlog_header_check_mount",
                                 XFS_ERRLEVEL_HIGH, mp);
@@ -490,8 +490,8 @@ xlog_find_verify_log_record(
        for (i = (*last_blk) - 1; i >= 0; i--) {
                if (i < start_blk) {
                        /* valid log record not found */
-                       xlog_warn(
-               "XFS: Log inconsistent (didn't find previous header)");
+                       xfs_warn(log->l_mp,
+               "Log inconsistent (didn't find previous header)");
                        ASSERT(0);
                        error = XFS_ERROR(EIO);
                        goto out;
@@ -591,12 +591,12 @@ xlog_find_head(
                         * mkfs etc write a dummy unmount record to a fresh
                         * log so we can store the uuid in there
                         */
-                       xlog_warn("XFS: totally zeroed log");
+                       xfs_warn(log->l_mp, "totally zeroed log");
                }
 
                return 0;
        } else if (error) {
-               xlog_warn("XFS: empty log check failed");
+               xfs_warn(log->l_mp, "empty log check failed");
                return error;
        }
 
@@ -819,7 +819,7 @@ validate_head:
        xlog_put_bp(bp);
 
        if (error)
-           xlog_warn("XFS: failed to find log head");
+               xfs_warn(log->l_mp, "failed to find log head");
        return error;
 }
 
@@ -912,7 +912,7 @@ xlog_find_tail(
                }
        }
        if (!found) {
-               xlog_warn("XFS: xlog_find_tail: couldn't find sync record");
+               xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
                ASSERT(0);
                return XFS_ERROR(EIO);
        }
@@ -1028,7 +1028,7 @@ done:
        xlog_put_bp(bp);
 
        if (error)
-               xlog_warn("XFS: failed to locate log tail");
+               xfs_warn(log->l_mp, "failed to locate log tail");
        return error;
 }
 
@@ -1092,7 +1092,8 @@ xlog_find_zeroed(
                 * the first block must be 1. If it's not, maybe we're
                 * not looking at a log... Bail out.
                 */
-               xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)");
+               xfs_warn(log->l_mp,
+                       "Log inconsistent or not a log (last==0, first!=1)");
                return XFS_ERROR(EINVAL);
        }
 
@@ -1506,8 +1507,8 @@ xlog_recover_add_to_trans(
        if (list_empty(&trans->r_itemq)) {
                /* we need to catch log corruptions here */
                if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) {
-                       xlog_warn("XFS: xlog_recover_add_to_trans: "
-                                 "bad header magic number");
+                       xfs_warn(log->l_mp, "%s: bad header magic number",
+                               __func__);
                        ASSERT(0);
                        return XFS_ERROR(EIO);
                }
@@ -1534,8 +1535,8 @@ xlog_recover_add_to_trans(
        if (item->ri_total == 0) {              /* first region to be added */
                if (in_f->ilf_size == 0 ||
                    in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) {
-                       xlog_warn(
-       "XFS: bad number of regions (%d) in inode log format",
+                       xfs_warn(log->l_mp,
+               "bad number of regions (%d) in inode log format",
                                  in_f->ilf_size);
                        ASSERT(0);
                        return XFS_ERROR(EIO);
@@ -1592,8 +1593,9 @@ xlog_recover_reorder_trans(
                        list_move_tail(&item->ri_list, &trans->r_itemq);
                        break;
                default:
-                       xlog_warn(
-       "XFS: xlog_recover_reorder_trans: unrecognized type of log operation");
+                       xfs_warn(log->l_mp,
+                               "%s: unrecognized type of log operation",
+                               __func__);
                        ASSERT(0);
                        return XFS_ERROR(EIO);
                }
@@ -1803,8 +1805,9 @@ xlog_recover_do_inode_buffer(
                logged_nextp = item->ri_buf[item_index].i_addr +
                                next_unlinked_offset - reg_buf_offset;
                if (unlikely(*logged_nextp == 0)) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "bad inode buffer log record (ptr = 0x%p, bp = 0x%p).  XFS trying to replay bad (0) inode di_next_unlinked field",
+                       xfs_alert(mp,
+               "Bad inode buffer log record (ptr = 0x%p, bp = 0x%p). "
+               "Trying to replay bad (0) inode di_next_unlinked field.",
                                item, bp);
                        XFS_ERROR_REPORT("xlog_recover_do_inode_buf",
                                         XFS_ERRLEVEL_LOW, mp);
@@ -1863,17 +1866,17 @@ xlog_recover_do_reg_buffer(
                if (buf_f->blf_flags &
                   (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
                        if (item->ri_buf[i].i_addr == NULL) {
-                               cmn_err(CE_ALERT,
+                               xfs_alert(mp,
                                        "XFS: NULL dquot in %s.", __func__);
                                goto next;
                        }
                        if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
-                               cmn_err(CE_ALERT,
+                               xfs_alert(mp,
                                        "XFS: dquot too small (%d) in %s.",
                                        item->ri_buf[i].i_len, __func__);
                                goto next;
                        }
-                       error = xfs_qm_dqcheck(item->ri_buf[i].i_addr,
+                       error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
                                               -1, 0, XFS_QMOPT_DOWARN,
                                               "dquot_buf_recover");
                        if (error)
@@ -1898,6 +1901,7 @@ xlog_recover_do_reg_buffer(
  */
 int
 xfs_qm_dqcheck(
+       struct xfs_mount *mp,
        xfs_disk_dquot_t *ddq,
        xfs_dqid_t       id,
        uint             type,    /* used only when IO_dorepair is true */
@@ -1924,14 +1928,14 @@ xfs_qm_dqcheck(
         */
        if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) {
                if (flags & XFS_QMOPT_DOWARN)
-                       cmn_err(CE_ALERT,
+                       xfs_alert(mp,
                        "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
                        str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
                errs++;
        }
        if (ddq->d_version != XFS_DQUOT_VERSION) {
                if (flags & XFS_QMOPT_DOWARN)
-                       cmn_err(CE_ALERT,
+                       xfs_alert(mp,
                        "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
                        str, id, ddq->d_version, XFS_DQUOT_VERSION);
                errs++;
@@ -1941,7 +1945,7 @@ xfs_qm_dqcheck(
            ddq->d_flags != XFS_DQ_PROJ &&
            ddq->d_flags != XFS_DQ_GROUP) {
                if (flags & XFS_QMOPT_DOWARN)
-                       cmn_err(CE_ALERT,
+                       xfs_alert(mp,
                        "%s : XFS dquot ID 0x%x, unknown flags 0x%x",
                        str, id, ddq->d_flags);
                errs++;
@@ -1949,7 +1953,7 @@ xfs_qm_dqcheck(
 
        if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
                if (flags & XFS_QMOPT_DOWARN)
-                       cmn_err(CE_ALERT,
+                       xfs_alert(mp,
                        "%s : ondisk-dquot 0x%p, ID mismatch: "
                        "0x%x expected, found id 0x%x",
                        str, ddq, id, be32_to_cpu(ddq->d_id));
@@ -1962,9 +1966,8 @@ xfs_qm_dqcheck(
                                be64_to_cpu(ddq->d_blk_softlimit)) {
                        if (!ddq->d_btimer) {
                                if (flags & XFS_QMOPT_DOWARN)
-                                       cmn_err(CE_ALERT,
-                                       "%s : Dquot ID 0x%x (0x%p) "
-                                       "BLK TIMER NOT STARTED",
+                                       xfs_alert(mp,
+                       "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
                                        str, (int)be32_to_cpu(ddq->d_id), ddq);
                                errs++;
                        }
@@ -1974,9 +1977,8 @@ xfs_qm_dqcheck(
                                be64_to_cpu(ddq->d_ino_softlimit)) {
                        if (!ddq->d_itimer) {
                                if (flags & XFS_QMOPT_DOWARN)
-                                       cmn_err(CE_ALERT,
-                                       "%s : Dquot ID 0x%x (0x%p) "
-                                       "INODE TIMER NOT STARTED",
+                                       xfs_alert(mp,
+                       "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
                                        str, (int)be32_to_cpu(ddq->d_id), ddq);
                                errs++;
                        }
@@ -1986,9 +1988,8 @@ xfs_qm_dqcheck(
                                be64_to_cpu(ddq->d_rtb_softlimit)) {
                        if (!ddq->d_rtbtimer) {
                                if (flags & XFS_QMOPT_DOWARN)
-                                       cmn_err(CE_ALERT,
-                                       "%s : Dquot ID 0x%x (0x%p) "
-                                       "RTBLK TIMER NOT STARTED",
+                                       xfs_alert(mp,
+                       "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
                                        str, (int)be32_to_cpu(ddq->d_id), ddq);
                                errs++;
                        }
@@ -1999,7 +2000,7 @@ xfs_qm_dqcheck(
                return errs;
 
        if (flags & XFS_QMOPT_DOWARN)
-               cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id);
+               xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
 
        /*
         * Typically, a repair is only requested by quotacheck.
@@ -2218,9 +2219,9 @@ xlog_recover_inode_pass2(
         */
        if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {
                xfs_buf_relse(bp);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
-                       dip, bp, in_f->ilf_ino);
+               xfs_alert(mp,
+       "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld",
+                       __func__, dip, bp, in_f->ilf_ino);
                XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)",
                                 XFS_ERRLEVEL_LOW, mp);
                error = EFSCORRUPTED;
@@ -2229,9 +2230,9 @@ xlog_recover_inode_pass2(
        dicp = item->ri_buf[1].i_addr;
        if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
                xfs_buf_relse(bp);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld",
-                       item, in_f->ilf_ino);
+               xfs_alert(mp,
+                       "%s: Bad inode log record, rec ptr 0x%p, ino %Ld",
+                       __func__, item, in_f->ilf_ino);
                XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)",
                                 XFS_ERRLEVEL_LOW, mp);
                error = EFSCORRUPTED;
@@ -2263,9 +2264,10 @@ xlog_recover_inode_pass2(
                        XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
                                         XFS_ERRLEVEL_LOW, mp, dicp);
                        xfs_buf_relse(bp);
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
-                               item, dip, bp, in_f->ilf_ino);
+                       xfs_alert(mp,
+               "%s: Bad regular inode log record, rec ptr 0x%p, "
+               "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
+                               __func__, item, dip, bp, in_f->ilf_ino);
                        error = EFSCORRUPTED;
                        goto error;
                }
@@ -2276,9 +2278,10 @@ xlog_recover_inode_pass2(
                        XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
                                             XFS_ERRLEVEL_LOW, mp, dicp);
                        xfs_buf_relse(bp);
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                               "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
-                               item, dip, bp, in_f->ilf_ino);
+                       xfs_alert(mp,
+               "%s: Bad dir inode log record, rec ptr 0x%p, "
+               "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
+                               __func__, item, dip, bp, in_f->ilf_ino);
                        error = EFSCORRUPTED;
                        goto error;
                }
@@ -2287,9 +2290,10 @@ xlog_recover_inode_pass2(
                XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
                                     XFS_ERRLEVEL_LOW, mp, dicp);
                xfs_buf_relse(bp);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
-                       item, dip, bp, in_f->ilf_ino,
+               xfs_alert(mp,
+       "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
+       "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
+                       __func__, item, dip, bp, in_f->ilf_ino,
                        dicp->di_nextents + dicp->di_anextents,
                        dicp->di_nblocks);
                error = EFSCORRUPTED;
@@ -2299,8 +2303,9 @@ xlog_recover_inode_pass2(
                XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
                                     XFS_ERRLEVEL_LOW, mp, dicp);
                xfs_buf_relse(bp);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
+               xfs_alert(mp,
+       "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
+       "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,
                        item, dip, bp, in_f->ilf_ino, dicp->di_forkoff);
                error = EFSCORRUPTED;
                goto error;
@@ -2309,9 +2314,9 @@ xlog_recover_inode_pass2(
                XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
                                     XFS_ERRLEVEL_LOW, mp, dicp);
                xfs_buf_relse(bp);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
-                       item->ri_buf[1].i_len, item);
+               xfs_alert(mp,
+                       "%s: Bad inode log record length %d, rec ptr 0x%p",
+                       __func__, item->ri_buf[1].i_len, item);
                error = EFSCORRUPTED;
                goto error;
        }
@@ -2398,7 +2403,7 @@ xlog_recover_inode_pass2(
                        break;
 
                default:
-                       xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag");
+                       xfs_warn(log->l_mp, "%s: Invalid flag", __func__);
                        ASSERT(0);
                        xfs_buf_relse(bp);
                        error = EIO;
@@ -2467,13 +2472,11 @@ xlog_recover_dquot_pass2(
 
        recddq = item->ri_buf[1].i_addr;
        if (recddq == NULL) {
-               cmn_err(CE_ALERT,
-                       "XFS: NULL dquot in %s.", __func__);
+               xfs_alert(log->l_mp, "NULL dquot in %s.", __func__);
                return XFS_ERROR(EIO);
        }
        if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) {
-               cmn_err(CE_ALERT,
-                       "XFS: dquot too small (%d) in %s.",
+               xfs_alert(log->l_mp, "dquot too small (%d) in %s.",
                        item->ri_buf[1].i_len, __func__);
                return XFS_ERROR(EIO);
        }
@@ -2498,12 +2501,10 @@ xlog_recover_dquot_pass2(
         */
        dq_f = item->ri_buf[0].i_addr;
        ASSERT(dq_f);
-       if ((error = xfs_qm_dqcheck(recddq,
-                          dq_f->qlf_id,
-                          0, XFS_QMOPT_DOWARN,
-                          "xlog_recover_dquot_pass2 (log copy)"))) {
+       error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
+                          "xlog_recover_dquot_pass2 (log copy)");
+       if (error)
                return XFS_ERROR(EIO);
-       }
        ASSERT(dq_f->qlf_len == 1);
 
        error = xfs_read_buf(mp, mp->m_ddev_targp,
@@ -2523,8 +2524,9 @@ xlog_recover_dquot_pass2(
         * was among a chunk of dquots created earlier, and we did some
         * minimal initialization then.
         */
-       if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
-                          "xlog_recover_dquot_pass2")) {
+       error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
+                          "xlog_recover_dquot_pass2");
+       if (error) {
                xfs_buf_relse(bp);
                return XFS_ERROR(EIO);
        }
@@ -2676,9 +2678,8 @@ xlog_recover_commit_pass1(
                /* nothing to do in pass 1 */
                return 0;
        default:
-               xlog_warn(
-       "XFS: invalid item type (%d) xlog_recover_commit_pass1",
-                       ITEM_TYPE(item));
+               xfs_warn(log->l_mp, "%s: invalid item type (%d)",
+                       __func__, ITEM_TYPE(item));
                ASSERT(0);
                return XFS_ERROR(EIO);
        }
@@ -2707,9 +2708,8 @@ xlog_recover_commit_pass2(
                /* nothing to do in pass2 */
                return 0;
        default:
-               xlog_warn(
-       "XFS: invalid item type (%d) xlog_recover_commit_pass2",
-                       ITEM_TYPE(item));
+               xfs_warn(log->l_mp, "%s: invalid item type (%d)",
+                       __func__, ITEM_TYPE(item));
                ASSERT(0);
                return XFS_ERROR(EIO);
        }
@@ -2751,10 +2751,11 @@ xlog_recover_commit_trans(
 
 STATIC int
 xlog_recover_unmount_trans(
+       struct log              *log,
        xlog_recover_t          *trans)
 {
        /* Do nothing now */
-       xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR");
+       xfs_warn(log->l_mp, "%s: Unmount LR", __func__);
        return 0;
 }
 
@@ -2797,8 +2798,8 @@ xlog_recover_process_data(
                dp += sizeof(xlog_op_header_t);
                if (ohead->oh_clientid != XFS_TRANSACTION &&
                    ohead->oh_clientid != XFS_LOG) {
-                       xlog_warn(
-               "XFS: xlog_recover_process_data: bad clientid");
+                       xfs_warn(log->l_mp, "%s: bad clientid 0x%x",
+                                       __func__, ohead->oh_clientid);
                        ASSERT(0);
                        return (XFS_ERROR(EIO));
                }
@@ -2811,8 +2812,8 @@ xlog_recover_process_data(
                                        be64_to_cpu(rhead->h_lsn));
                } else {
                        if (dp + be32_to_cpu(ohead->oh_len) > lp) {
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad length");
+                               xfs_warn(log->l_mp, "%s: bad length 0x%x",
+                                       __func__, be32_to_cpu(ohead->oh_len));
                                WARN_ON(1);
                                return (XFS_ERROR(EIO));
                        }
@@ -2825,7 +2826,7 @@ xlog_recover_process_data(
                                                                trans, pass);
                                break;
                        case XLOG_UNMOUNT_TRANS:
-                               error = xlog_recover_unmount_trans(trans);
+                               error = xlog_recover_unmount_trans(log, trans);
                                break;
                        case XLOG_WAS_CONT_TRANS:
                                error = xlog_recover_add_to_cont_trans(log,
@@ -2833,8 +2834,8 @@ xlog_recover_process_data(
                                                be32_to_cpu(ohead->oh_len));
                                break;
                        case XLOG_START_TRANS:
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad transaction");
+                               xfs_warn(log->l_mp, "%s: bad transaction",
+                                       __func__);
                                ASSERT(0);
                                error = XFS_ERROR(EIO);
                                break;
@@ -2844,8 +2845,8 @@ xlog_recover_process_data(
                                                dp, be32_to_cpu(ohead->oh_len));
                                break;
                        default:
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad flag");
+                               xfs_warn(log->l_mp, "%s: bad flag 0x%x",
+                                       __func__, flags);
                                ASSERT(0);
                                error = XFS_ERROR(EIO);
                                break;
@@ -3030,8 +3031,7 @@ xlog_recover_clear_agi_bucket(
 out_abort:
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);
 out_error:
-       xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
-                       "failed to clear agi %d. Continuing.", agno);
+       xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno);
        return;
 }
 
@@ -3282,7 +3282,7 @@ xlog_valid_rec_header(
        if (unlikely(
            (!rhead->h_version ||
            (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
-               xlog_warn("XFS: %s: unrecognised log version (%d).",
+               xfs_warn(log->l_mp, "%s: unrecognised log version (%d).",
                        __func__, be32_to_cpu(rhead->h_version));
                return XFS_ERROR(EIO);
        }
@@ -3740,10 +3740,9 @@ xlog_recover(
                        return error;
                }
 
-               cmn_err(CE_NOTE,
-                       "Starting XFS recovery on filesystem: %s (logdev: %s)",
-                       log->l_mp->m_fsname, log->l_mp->m_logname ?
-                       log->l_mp->m_logname : "internal");
+               xfs_notice(log->l_mp, "Starting recovery (logdev: %s)",
+                               log->l_mp->m_logname ? log->l_mp->m_logname
+                                                    : "internal");
 
                error = xlog_do_recover(log, head_blk, tail_blk);
                log->l_flags |= XLOG_RECOVERY_NEEDED;
@@ -3776,9 +3775,7 @@ xlog_recover_finish(
                int     error;
                error = xlog_recover_process_efis(log);
                if (error) {
-                       cmn_err(CE_ALERT,
-                               "Failed to recover EFIs on filesystem: %s",
-                               log->l_mp->m_fsname);
+                       xfs_alert(log->l_mp, "Failed to recover EFIs");
                        return error;
                }
                /*
@@ -3793,15 +3790,12 @@ xlog_recover_finish(
 
                xlog_recover_check_summary(log);
 
-               cmn_err(CE_NOTE,
-                       "Ending XFS recovery on filesystem: %s (logdev: %s)",
-                       log->l_mp->m_fsname, log->l_mp->m_logname ?
-                       log->l_mp->m_logname : "internal");
+               xfs_notice(log->l_mp, "Ending recovery (logdev: %s)",
+                               log->l_mp->m_logname ? log->l_mp->m_logname
+                                                    : "internal");
                log->l_flags &= ~XLOG_RECOVERY_NEEDED;
        } else {
-               cmn_err(CE_DEBUG,
-                       "Ending clean XFS mount for filesystem: %s\n",
-                       log->l_mp->m_fsname);
+               xfs_info(log->l_mp, "Ending clean mount");
        }
        return 0;
 }
@@ -3834,10 +3828,8 @@ xlog_recover_check_summary(
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
                error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
                if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp,
-                                       "xlog_recover_check_summary(agf)"
-                                       "agf read failed agno %d error %d",
-                                                       agno, error);
+                       xfs_alert(mp, "%s agf read failed agno %d error %d",
+                                               __func__, agno, error);
                } else {
                        agfp = XFS_BUF_TO_AGF(agfbp);
                        freeblks += be32_to_cpu(agfp->agf_freeblks) +
@@ -3846,7 +3838,10 @@ xlog_recover_check_summary(
                }
 
                error = xfs_read_agi(mp, NULL, agno, &agibp);
-               if (!error) {
+               if (error) {
+                       xfs_alert(mp, "%s agi read failed agno %d error %d",
+                                               __func__, agno, error);
+               } else {
                        struct xfs_agi  *agi = XFS_BUF_TO_AGI(agibp);
 
                        itotal += be32_to_cpu(agi->agi_count);
index d447aef84bc3a552fe44fdd1559bbf05d3f5f17f..bb3f9a7b24ed7b6d36ef5536ea9d0b4020d9725e 100644 (file)
@@ -133,9 +133,7 @@ xfs_uuid_mount(
                return 0;
 
        if (uuid_is_nil(uuid)) {
-               cmn_err(CE_WARN,
-                       "XFS: Filesystem %s has nil UUID - can't mount",
-                       mp->m_fsname);
+               xfs_warn(mp, "Filesystem has nil UUID - can't mount");
                return XFS_ERROR(EINVAL);
        }
 
@@ -163,8 +161,7 @@ xfs_uuid_mount(
 
  out_duplicate:
        mutex_unlock(&xfs_uuid_table_mutex);
-       cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount",
-                        mp->m_fsname);
+       xfs_warn(mp, "Filesystem has duplicate UUID - can't mount");
        return XFS_ERROR(EINVAL);
 }
 
@@ -311,6 +308,8 @@ xfs_mount_validate_sb(
        xfs_sb_t        *sbp,
        int             flags)
 {
+       int             loud = !(flags & XFS_MFSI_QUIET);
+
        /*
         * If the log device and data device have the
         * same device number, the log is internal.
@@ -319,28 +318,32 @@ xfs_mount_validate_sb(
         * a volume filesystem in a non-volume manner.
         */
        if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-               xfs_fs_mount_cmn_err(flags, "bad magic number");
+               if (loud)
+                       xfs_warn(mp, "bad magic number");
                return XFS_ERROR(EWRONGFS);
        }
 
        if (!xfs_sb_good_version(sbp)) {
-               xfs_fs_mount_cmn_err(flags, "bad version");
+               if (loud)
+                       xfs_warn(mp, "bad version");
                return XFS_ERROR(EWRONGFS);
        }
 
        if (unlikely(
            sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
-               xfs_fs_mount_cmn_err(flags,
-                       "filesystem is marked as having an external log; "
-                       "specify logdev on the\nmount command line.");
+               if (loud)
+                       xfs_warn(mp,
+               "filesystem is marked as having an external log; "
+               "specify logdev on the mount command line.");
                return XFS_ERROR(EINVAL);
        }
 
        if (unlikely(
            sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
-               xfs_fs_mount_cmn_err(flags,
-                       "filesystem is marked as having an internal log; "
-                       "do not specify logdev on\nthe mount command line.");
+               if (loud)
+                       xfs_warn(mp,
+               "filesystem is marked as having an internal log; "
+               "do not specify logdev on the mount command line.");
                return XFS_ERROR(EINVAL);
        }
 
@@ -369,7 +372,8 @@ xfs_mount_validate_sb(
            (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)  ||
            (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)  ||
            (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
-               xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
+               if (loud)
+                       xfs_warn(mp, "SB sanity check 1 failed");
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -382,7 +386,8 @@ xfs_mount_validate_sb(
             (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
            sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
                              sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
-               xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
+               if (loud)
+                       xfs_warn(mp, "SB sanity check 2 failed");
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -390,12 +395,12 @@ xfs_mount_validate_sb(
         * Until this is fixed only page-sized or smaller data blocks work.
         */
        if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
-               xfs_fs_mount_cmn_err(flags,
-                       "file system with blocksize %d bytes",
-                       sbp->sb_blocksize);
-               xfs_fs_mount_cmn_err(flags,
-                       "only pagesize (%ld) or less will currently work.",
-                       PAGE_SIZE);
+               if (loud) {
+                       xfs_warn(mp,
+               "File system with blocksize %d bytes. "
+               "Only pagesize (%ld) or less will currently work.",
+                               sbp->sb_blocksize, PAGE_SIZE);
+               }
                return XFS_ERROR(ENOSYS);
        }
 
@@ -409,21 +414,23 @@ xfs_mount_validate_sb(
        case 2048:
                break;
        default:
-               xfs_fs_mount_cmn_err(flags,
-                       "inode size of %d bytes not supported",
-                       sbp->sb_inodesize);
+               if (loud)
+                       xfs_warn(mp, "inode size of %d bytes not supported",
+                               sbp->sb_inodesize);
                return XFS_ERROR(ENOSYS);
        }
 
        if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
            xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
-               xfs_fs_mount_cmn_err(flags,
-                       "file system too large to be mounted on this system.");
+               if (loud)
+                       xfs_warn(mp,
+               "file system too large to be mounted on this system.");
                return XFS_ERROR(EFBIG);
        }
 
        if (unlikely(sbp->sb_inprogress)) {
-               xfs_fs_mount_cmn_err(flags, "file system busy");
+               if (loud)
+                       xfs_warn(mp, "file system busy");
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -431,8 +438,9 @@ xfs_mount_validate_sb(
         * Version 1 directory format has never worked on Linux.
         */
        if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
-               xfs_fs_mount_cmn_err(flags,
-                       "file system using version 1 directory format");
+               if (loud)
+                       xfs_warn(mp,
+                               "file system using version 1 directory format");
                return XFS_ERROR(ENOSYS);
        }
 
@@ -673,6 +681,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
        unsigned int    sector_size;
        xfs_buf_t       *bp;
        int             error;
+       int             loud = !(flags & XFS_MFSI_QUIET);
 
        ASSERT(mp->m_sb_bp == NULL);
        ASSERT(mp->m_ddev_targp != NULL);
@@ -688,7 +697,8 @@ reread:
        bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
                                        XFS_SB_DADDR, sector_size, 0);
        if (!bp) {
-               xfs_fs_mount_cmn_err(flags, "SB buffer read failed");
+               if (loud)
+                       xfs_warn(mp, "SB buffer read failed");
                return EIO;
        }
 
@@ -699,7 +709,8 @@ reread:
        xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
        error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
        if (error) {
-               xfs_fs_mount_cmn_err(flags, "SB validate failed");
+               if (loud)
+                       xfs_warn(mp, "SB validate failed");
                goto release_buf;
        }
 
@@ -707,9 +718,9 @@ reread:
         * We must be able to do sector-sized and sector-aligned IO.
         */
        if (sector_size > mp->m_sb.sb_sectsize) {
-               xfs_fs_mount_cmn_err(flags,
-                       "device supports only %u byte sectors (not %u)",
-                       sector_size, mp->m_sb.sb_sectsize);
+               if (loud)
+                       xfs_warn(mp, "device supports %u byte sectors (not %u)",
+                               sector_size, mp->m_sb.sb_sectsize);
                error = ENOSYS;
                goto release_buf;
        }
@@ -853,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp)
                if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
                    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
                        if (mp->m_flags & XFS_MOUNT_RETERR) {
-                               cmn_err(CE_WARN,
-                                       "XFS: alignment check 1 failed");
+                               xfs_warn(mp, "alignment check 1 failed");
                                return XFS_ERROR(EINVAL);
                        }
                        mp->m_dalign = mp->m_swidth = 0;
@@ -867,8 +877,9 @@ xfs_update_alignment(xfs_mount_t *mp)
                                if (mp->m_flags & XFS_MOUNT_RETERR) {
                                        return XFS_ERROR(EINVAL);
                                }
-                               xfs_fs_cmn_err(CE_WARN, mp,
-"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
+                               xfs_warn(mp,
+               "stripe alignment turned off: sunit(%d)/swidth(%d) "
+               "incompatible with agsize(%d)",
                                        mp->m_dalign, mp->m_swidth,
                                        sbp->sb_agblocks);
 
@@ -878,9 +889,9 @@ xfs_update_alignment(xfs_mount_t *mp)
                                mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
                        } else {
                                if (mp->m_flags & XFS_MOUNT_RETERR) {
-                                       xfs_fs_cmn_err(CE_WARN, mp,
-"stripe alignment turned off: sunit(%d) less than bsize(%d)",
-                                               mp->m_dalign,
+                                       xfs_warn(mp,
+               "stripe alignment turned off: sunit(%d) less than bsize(%d)",
+                                               mp->m_dalign,
                                                mp->m_blockmask +1);
                                        return XFS_ERROR(EINVAL);
                                }
@@ -1026,14 +1037,14 @@ xfs_check_sizes(xfs_mount_t *mp)
 
        d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
        if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
-               cmn_err(CE_WARN, "XFS: filesystem size mismatch detected");
+               xfs_warn(mp, "filesystem size mismatch detected");
                return XFS_ERROR(EFBIG);
        }
        bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
                                        d - XFS_FSS_TO_BB(mp, 1),
                                        BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
        if (!bp) {
-               cmn_err(CE_WARN, "XFS: last sector read failed");
+               xfs_warn(mp, "last sector read failed");
                return EIO;
        }
        xfs_buf_relse(bp);
@@ -1041,14 +1052,14 @@ xfs_check_sizes(xfs_mount_t *mp)
        if (mp->m_logdev_targp != mp->m_ddev_targp) {
                d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
                if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
-                       cmn_err(CE_WARN, "XFS: log size mismatch detected");
+                       xfs_warn(mp, "log size mismatch detected");
                        return XFS_ERROR(EFBIG);
                }
                bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp,
                                        d - XFS_FSB_TO_BB(mp, 1),
                                        XFS_FSB_TO_B(mp, 1), 0);
                if (!bp) {
-                       cmn_err(CE_WARN, "XFS: log device read failed");
+                       xfs_warn(mp, "log device read failed");
                        return EIO;
                }
                xfs_buf_relse(bp);
@@ -1086,7 +1097,7 @@ xfs_mount_reset_sbqflags(
                return 0;
 
 #ifdef QUOTADEBUG
-       xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
+       xfs_notice(mp, "Writing superblock quota changes");
 #endif
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
@@ -1094,8 +1105,7 @@ xfs_mount_reset_sbqflags(
                                      XFS_DEFAULT_LOG_COUNT);
        if (error) {
                xfs_trans_cancel(tp, 0);
-               xfs_fs_cmn_err(CE_ALERT, mp,
-                       "xfs_mount_reset_sbqflags: Superblock update failed!");
+               xfs_alert(mp, "%s: Superblock update failed!", __func__);
                return error;
        }
 
@@ -1161,8 +1171,7 @@ xfs_mountfs(
         * transaction subsystem is online.
         */
        if (xfs_sb_has_mismatched_features2(sbp)) {
-               cmn_err(CE_WARN,
-                       "XFS: correcting sb_features alignment problem");
+               xfs_warn(mp, "correcting sb_features alignment problem");
                sbp->sb_features2 |= sbp->sb_bad_features2;
                sbp->sb_bad_features2 = sbp->sb_features2;
                mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
@@ -1241,7 +1250,7 @@ xfs_mountfs(
         */
        error = xfs_rtmount_init(mp);
        if (error) {
-               cmn_err(CE_WARN, "XFS: RT mount failed");
+               xfs_warn(mp, "RT mount failed");
                goto out_remove_uuid;
        }
 
@@ -1272,12 +1281,12 @@ xfs_mountfs(
        INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
        error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
        if (error) {
-               cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
+               xfs_warn(mp, "Failed per-ag init: %d", error);
                goto out_remove_uuid;
        }
 
        if (!sbp->sb_logblocks) {
-               cmn_err(CE_WARN, "XFS: no log defined");
+               xfs_warn(mp, "no log defined");
                XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
                error = XFS_ERROR(EFSCORRUPTED);
                goto out_free_perag;
@@ -1290,7 +1299,7 @@ xfs_mountfs(
                              XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
                              XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
        if (error) {
-               cmn_err(CE_WARN, "XFS: log mount failed");
+               xfs_warn(mp, "log mount failed");
                goto out_free_perag;
        }
 
@@ -1327,16 +1336,14 @@ xfs_mountfs(
         */
        error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
        if (error) {
-               cmn_err(CE_WARN, "XFS: failed to read root inode");
+               xfs_warn(mp, "failed to read root inode");
                goto out_log_dealloc;
        }
 
        ASSERT(rip != NULL);
 
        if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
-               cmn_err(CE_WARN, "XFS: corrupted root inode");
-               cmn_err(CE_WARN, "Device %s - root %llu is not a directory",
-                       XFS_BUFTARG_NAME(mp->m_ddev_targp),
+               xfs_warn(mp, "corrupted root inode %llu: not a directory",
                        (unsigned long long)rip->i_ino);
                xfs_iunlock(rip, XFS_ILOCK_EXCL);
                XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
@@ -1356,7 +1363,7 @@ xfs_mountfs(
                /*
                 * Free up the root inode.
                 */
-               cmn_err(CE_WARN, "XFS: failed to read RT inodes");
+               xfs_warn(mp, "failed to read RT inodes");
                goto out_rele_rip;
        }
 
@@ -1368,7 +1375,7 @@ xfs_mountfs(
        if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
                error = xfs_mount_log_sb(mp, mp->m_update_flags);
                if (error) {
-                       cmn_err(CE_WARN, "XFS: failed to write sb changes");
+                       xfs_warn(mp, "failed to write sb changes");
                        goto out_rtunmount;
                }
        }
@@ -1389,10 +1396,7 @@ xfs_mountfs(
                 * quotachecked license.
                 */
                if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
-                       cmn_err(CE_NOTE,
-                               "XFS: resetting qflags for filesystem %s",
-                               mp->m_fsname);
-
+                       xfs_notice(mp, "resetting quota flags");
                        error = xfs_mount_reset_sbqflags(mp);
                        if (error)
                                return error;
@@ -1406,7 +1410,7 @@ xfs_mountfs(
         */
        error = xfs_log_mount_finish(mp);
        if (error) {
-               cmn_err(CE_WARN, "XFS: log mount finish failed");
+               xfs_warn(mp, "log mount finish failed");
                goto out_rtunmount;
        }
 
@@ -1435,8 +1439,8 @@ xfs_mountfs(
                resblks = xfs_default_resblks(mp);
                error = xfs_reserve_blocks(mp, &resblks, NULL);
                if (error)
-                       cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
-                               "blocks. Continuing without a reserve pool.");
+                       xfs_warn(mp,
+       "Unable to allocate reserve blocks. Continuing without reserve pool.");
        }
 
        return 0;
@@ -1525,12 +1529,12 @@ xfs_unmountfs(
        resblks = 0;
        error = xfs_reserve_blocks(mp, &resblks, NULL);
        if (error)
-               cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
+               xfs_warn(mp, "Unable to free reserved block pool. "
                                "Freespace may not be correct on next mount.");
 
        error = xfs_log_sbcount(mp, 1);
        if (error)
-               cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
+               xfs_warn(mp, "Unable to update superblock counters. "
                                "Freespace may not be correct on next mount.");
        xfs_unmountfs_writesb(mp);
        xfs_unmountfs_wait(mp);                 /* wait for async bufs */
@@ -2013,10 +2017,8 @@ xfs_dev_is_read_only(
        if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
            xfs_readonly_buftarg(mp->m_logdev_targp) ||
            (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
-               cmn_err(CE_NOTE,
-                       "XFS: %s required on read-only device.", message);
-               cmn_err(CE_NOTE,
-                       "XFS: write access unavailable, cannot proceed.");
+               xfs_notice(mp, "%s required on read-only device.", message);
+               xfs_notice(mp, "write access unavailable, cannot proceed.");
                return EROFS;
        }
        return 0;
index 9bb6eda4cd215903077612233bf3b6c0d1577327..a595f29567fedda40964ae11eb1e885859acb238 100644 (file)
@@ -382,7 +382,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags)
        xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \
                                f | XFS_QMOPT_RES_REGBLKS)
 
-extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
+extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
+                               xfs_dqid_t, uint, uint, char *);
 extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
 
 #endif /* __KERNEL__ */
index 12a19138531048555651e28330ade938a1b2b36f..8f76fdff4f4688484fac811a23f97cf23f91d23a 100644 (file)
@@ -76,7 +76,7 @@ xfs_growfs_rt_alloc(
        xfs_mount_t     *mp,            /* file system mount point */
        xfs_extlen_t    oblocks,        /* old count of blocks */
        xfs_extlen_t    nblocks,        /* new count of blocks */
-       xfs_ino_t       ino)            /* inode number (bitmap/summary) */
+       xfs_inode_t     *ip)            /* inode (bitmap/summary) */
 {
        xfs_fileoff_t   bno;            /* block number in file */
        xfs_buf_t       *bp;            /* temporary buffer for zeroing */
@@ -86,7 +86,6 @@ xfs_growfs_rt_alloc(
        xfs_fsblock_t   firstblock;     /* first block allocated in xaction */
        xfs_bmap_free_t flist;          /* list of freed blocks */
        xfs_fsblock_t   fsbno;          /* filesystem block for bno */
-       xfs_inode_t     *ip;            /* pointer to incore inode */
        xfs_bmbt_irec_t map;            /* block map output */
        int             nmap;           /* number of block maps */
        int             resblks;        /* space reservation */
@@ -112,9 +111,9 @@ xfs_growfs_rt_alloc(
                /*
                 * Lock the inode.
                 */
-               if ((error = xfs_trans_iget(mp, tp, ino, 0,
-                                               XFS_ILOCK_EXCL, &ip)))
-                       goto error_cancel;
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
+
                xfs_bmap_init(&flist, &firstblock);
                /*
                 * Allocate blocks to the bitmap file.
@@ -155,9 +154,8 @@ xfs_growfs_rt_alloc(
                        /*
                         * Lock the bitmap inode.
                         */
-                       if ((error = xfs_trans_iget(mp, tp, ino, 0,
-                                                       XFS_ILOCK_EXCL, &ip)))
-                               goto error_cancel;
+                       xfs_ilock(ip, XFS_ILOCK_EXCL);
+                       xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
                        /*
                         * Get a buffer for the block.
                         */
@@ -1854,7 +1852,6 @@ xfs_growfs_rt(
        xfs_rtblock_t   bmbno;          /* bitmap block number */
        xfs_buf_t       *bp;            /* temporary buffer */
        int             error;          /* error return value */
-       xfs_inode_t     *ip;            /* bitmap inode, used as lock */
        xfs_mount_t     *nmp;           /* new (fake) mount structure */
        xfs_drfsbno_t   nrblocks;       /* new number of realtime blocks */
        xfs_extlen_t    nrbmblocks;     /* new number of rt bitmap blocks */
@@ -1918,11 +1915,11 @@ xfs_growfs_rt(
        /*
         * Allocate space to the bitmap and summary files, as necessary.
         */
-       if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks,
-                       mp->m_sb.sb_rbmino)))
+       error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
+       if (error)
                return error;
-       if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
-                       mp->m_sb.sb_rsumino)))
+       error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
+       if (error)
                return error;
        /*
         * Allocate a new (fake) mount/sb.
@@ -1972,10 +1969,8 @@ xfs_growfs_rt(
                /*
                 * Lock out other callers by grabbing the bitmap inode lock.
                 */
-               if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-                                               XFS_ILOCK_EXCL, &ip)))
-                       goto error_cancel;
-               ASSERT(ip == mp->m_rbmip);
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
                /*
                 * Update the bitmap inode's size.
                 */
@@ -1986,10 +1981,8 @@ xfs_growfs_rt(
                /*
                 * Get the summary inode into the transaction.
                 */
-               if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
-                                               XFS_ILOCK_EXCL, &ip)))
-                       goto error_cancel;
-               ASSERT(ip == mp->m_rsumip);
+               xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
                /*
                 * Update the summary inode's size.
                 */
@@ -2075,15 +2068,15 @@ xfs_rtallocate_extent(
        xfs_extlen_t    prod,           /* extent product factor */
        xfs_rtblock_t   *rtblock)       /* out: start block allocated */
 {
+       xfs_mount_t     *mp = tp->t_mountp;
        int             error;          /* error value */
-       xfs_inode_t     *ip;            /* inode for bitmap file */
-       xfs_mount_t     *mp;            /* file system mount structure */
        xfs_rtblock_t   r;              /* result allocated block */
        xfs_fsblock_t   sb;             /* summary file block number */
        xfs_buf_t       *sumbp;         /* summary file block buffer */
 
+       ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
        ASSERT(minlen > 0 && minlen <= maxlen);
-       mp = tp->t_mountp;
+
        /*
         * If prod is set then figure out what to do to minlen and maxlen.
         */
@@ -2099,12 +2092,7 @@ xfs_rtallocate_extent(
                        return 0;
                }
        }
-       /*
-        * Lock out other callers by grabbing the bitmap inode lock.
-        */
-       if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-                                       XFS_ILOCK_EXCL, &ip)))
-               return error;
+
        sumbp = NULL;
        /*
         * Allocate by size, or near another block, or exactly at some block.
@@ -2123,11 +2111,12 @@ xfs_rtallocate_extent(
                                len, &sumbp, &sb, prod, &r);
                break;
        default:
+               error = EIO;
                ASSERT(0);
        }
-       if (error) {
+       if (error)
                return error;
-       }
+
        /*
         * If it worked, update the superblock.
         */
@@ -2155,7 +2144,6 @@ xfs_rtfree_extent(
        xfs_extlen_t    len)            /* length of extent freed */
 {
        int             error;          /* error value */
-       xfs_inode_t     *ip;            /* bitmap file inode */
        xfs_mount_t     *mp;            /* file system mount structure */
        xfs_fsblock_t   sb;             /* summary file block number */
        xfs_buf_t       *sumbp;         /* summary file block buffer */
@@ -2164,9 +2152,9 @@ xfs_rtfree_extent(
        /*
         * Synchronize by locking the bitmap inode.
         */
-       if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-                                       XFS_ILOCK_EXCL, &ip)))
-               return error;
+       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
 #if defined(__KERNEL__) && defined(DEBUG)
        /*
         * Check to see that this whole range is currently allocated.
@@ -2199,10 +2187,10 @@ xfs_rtfree_extent(
         */
        if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
            mp->m_sb.sb_rextents) {
-               if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
-                       ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
-               *(__uint64_t *)&ip->i_d.di_atime = 0;
-               xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+               if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
+                       mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
+               *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
+               xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
        }
        return 0;
 }
@@ -2222,8 +2210,8 @@ xfs_rtmount_init(
        if (sbp->sb_rblocks == 0)
                return 0;
        if (mp->m_rtdev_targp == NULL) {
-               cmn_err(CE_WARN,
-       "XFS: This filesystem has a realtime volume, use rtdev=device option");
+               xfs_warn(mp,
+       "Filesystem has a realtime volume, use rtdev=device option");
                return XFS_ERROR(ENODEV);
        }
        mp->m_rsumlevels = sbp->sb_rextslog + 1;
@@ -2237,7 +2225,7 @@ xfs_rtmount_init(
         */
        d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
        if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
-               cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
+               xfs_warn(mp, "realtime mount -- %llu != %llu",
                        (unsigned long long) XFS_BB_TO_FSB(mp, d),
                        (unsigned long long) mp->m_sb.sb_rblocks);
                return XFS_ERROR(EFBIG);
@@ -2246,7 +2234,7 @@ xfs_rtmount_init(
                                        d - XFS_FSB_TO_BB(mp, 1),
                                        XFS_FSB_TO_B(mp, 1), 0);
        if (!bp) {
-               cmn_err(CE_WARN, "XFS: realtime device size check failed");
+               xfs_warn(mp, "realtime device size check failed");
                return EIO;
        }
        xfs_buf_relse(bp);
@@ -2306,20 +2294,16 @@ xfs_rtpick_extent(
        xfs_rtblock_t   *pick)          /* result rt extent */
 {
        xfs_rtblock_t   b;              /* result block */
-       int             error;          /* error return value */
-       xfs_inode_t     *ip;            /* bitmap incore inode */
        int             log2;           /* log of sequence number */
        __uint64_t      resid;          /* residual after log removed */
        __uint64_t      seq;            /* sequence number of file creation */
        __uint64_t      *seqp;          /* pointer to seqno in inode */
 
-       if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-                                       XFS_ILOCK_EXCL, &ip)))
-               return error;
-       ASSERT(ip == mp->m_rbmip);
-       seqp = (__uint64_t *)&ip->i_d.di_atime;
-       if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
-               ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
+       ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
+
+       seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime;
+       if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
+               mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
                *seqp = 0;
        }
        seq = *seqp;
@@ -2335,7 +2319,7 @@ xfs_rtpick_extent(
                        b = mp->m_sb.sb_rextents - len;
        }
        *seqp = seq + 1;
-       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+       xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
        *pick = b;
        return 0;
 }
index ff614c29b44142da429bb33db904afdf843469ad..09e1f4f35e971c0e1edf326cfeca9d21f67a6953 100644 (file)
@@ -154,7 +154,7 @@ xfs_rtmount_init(
        if (mp->m_sb.sb_rblocks == 0)
                return 0;
 
-       cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT");
+       xfs_warn(mp, "Not built with CONFIG_XFS_RT");
        return ENOSYS;
 }
 # define xfs_rtmount_inodes(m)  (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
index 56861d5daaef54432a94a640a7b1e65812030ef7..d6d6fdfe9422b47545de1bbeb9e6713c67be160b 100644 (file)
@@ -49,9 +49,9 @@ xfs_do_force_shutdown(
        logerror = flags & SHUTDOWN_LOG_IO_ERROR;
 
        if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
-               cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
-                                "line %d of file %s.  Return address = 0x%p",
-                       mp->m_fsname, flags, lnnum, fname, __return_address);
+               xfs_notice(mp,
+       "%s(0x%x) called from line %d of file %s.  Return address = 0x%p",
+                       __func__, flags, lnnum, fname, __return_address);
        }
        /*
         * No need to duplicate efforts.
@@ -69,30 +69,25 @@ xfs_do_force_shutdown(
                return;
 
        if (flags & SHUTDOWN_CORRUPT_INCORE) {
-               xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
-    "Corruption of in-memory data detected.  Shutting down filesystem: %s",
-                       mp->m_fsname);
-               if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
+               xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT,
+    "Corruption of in-memory data detected.  Shutting down filesystem");
+               if (XFS_ERRLEVEL_HIGH <= xfs_error_level)
                        xfs_stack_trace();
-               }
        } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
                if (logerror) {
-                       xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
-               "Log I/O Error Detected.  Shutting down filesystem: %s",
-                               mp->m_fsname);
+                       xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR,
+               "Log I/O Error Detected.  Shutting down filesystem");
                } else if (flags & SHUTDOWN_DEVICE_REQ) {
-                       xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
-               "All device paths lost.  Shutting down filesystem: %s",
-                               mp->m_fsname);
+                       xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
+               "All device paths lost.  Shutting down filesystem");
                } else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
-                       xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
-               "I/O Error Detected.  Shutting down filesystem: %s",
-                               mp->m_fsname);
+                       xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
+               "I/O Error Detected. Shutting down filesystem");
                }
        }
        if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
-               cmn_err(CE_ALERT, "Please umount the filesystem, "
-                                 "and rectify the problem(s)");
+               xfs_alert(mp,
+       "Please umount the filesystem and rectify the problem(s)");
        }
 }
 
@@ -106,10 +101,9 @@ xfs_ioerror_alert(
        xfs_buf_t               *bp,
        xfs_daddr_t             blkno)
 {
-       cmn_err(CE_ALERT,
- "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
- "       (\"%s\") error %d buf count %zd",
-               (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
+       xfs_alert(mp,
+                "I/O error occurred: meta-data dev %s block 0x%llx"
+                "       (\"%s\") error %d buf count %zd",
                XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
                (__uint64_t)blkno, func,
                XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
@@ -173,17 +167,9 @@ xfs_extlen_t
 xfs_get_extsz_hint(
        struct xfs_inode        *ip)
 {
-       xfs_extlen_t            extsz;
-
-       if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
-               extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
-                               ? ip->i_d.di_extsize
-                               : ip->i_mount->m_sb.sb_rextsize;
-               ASSERT(extsz);
-       } else {
-               extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
-                               ? ip->i_d.di_extsize : 0;
-       }
-
-       return extsz;
+       if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize)
+               return ip->i_d.di_extsize;
+       if (XFS_IS_REALTIME_INODE(ip))
+               return ip->i_mount->m_sb.sb_rextsize;
+       return 0;
 }
index c2042b736b81131a780703d8a5907c848793eebb..06a9759b6352aa497d64396d9ce3fa0900506d3f 100644 (file)
@@ -469,8 +469,6 @@ void                xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);
 void           xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
 void           xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
 void           xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
-int            xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
-                              xfs_ino_t , uint, uint, struct xfs_inode **);
 void           xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
 void           xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint);
 void           xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *);
index c5bbbc45db91ed97429a043ba8144cc53509a993..12aff9584e299a2d026a84f1871c669f0fdb9a4c 100644 (file)
@@ -563,7 +563,7 @@ xfs_trans_ail_delete_bulk(
 
                        spin_unlock(&ailp->xa_lock);
                        if (!XFS_FORCED_SHUTDOWN(mp)) {
-                               xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
+                               xfs_alert_tag(mp, XFS_PTAG_AILDELETE,
                "%s: attempting to delete a log item that is not in the AIL",
                                                __func__);
                                xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
index c47918c302a50593341de2add8e5072078d9804e..3bea66132334c91e83278a5c581fae7d399e1490 100644 (file)
@@ -305,7 +305,7 @@ xfs_trans_read_buf(
                        if (xfs_error_target == target) {
                                if (((xfs_req_num++) % xfs_error_mod) == 0) {
                                        xfs_buf_relse(bp);
-                                       cmn_err(CE_DEBUG, "Returning error!\n");
+                                       xfs_debug(mp, "Returning error!");
                                        return XFS_ERROR(EIO);
                                }
                        }
@@ -403,7 +403,7 @@ xfs_trans_read_buf(
                                xfs_force_shutdown(tp->t_mountp,
                                                   SHUTDOWN_META_IO_ERROR);
                                xfs_buf_relse(bp);
-                               cmn_err(CE_DEBUG, "Returning trans error!\n");
+                               xfs_debug(mp, "Returning trans error!");
                                return XFS_ERROR(EIO);
                        }
                }
@@ -427,7 +427,7 @@ shutdown_abort:
         */
 #if defined(DEBUG)
        if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp))
-               cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp);
+               xfs_notice(mp, "about to pop assert, bp == 0x%p", bp);
 #endif
        ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) !=
                                     (XBF_STALE|XBF_DELWRI));
index ccb34532768bd65a1c5baa14a4a0a143df1ea2cb..16084d8ea231a0434823ef3c9007333fdbd675f7 100644 (file)
@@ -43,28 +43,6 @@ xfs_trans_inode_broot_debug(
 #define        xfs_trans_inode_broot_debug(ip)
 #endif
 
-/*
- * Get an inode and join it to the transaction.
- */
-int
-xfs_trans_iget(
-       xfs_mount_t     *mp,
-       xfs_trans_t     *tp,
-       xfs_ino_t       ino,
-       uint            flags,
-       uint            lock_flags,
-       xfs_inode_t     **ipp)
-{
-       int                     error;
-
-       error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp);
-       if (!error && tp) {
-               xfs_trans_ijoin(tp, *ipp);
-               (*ipp)->i_itemp->ili_lock_flags = lock_flags;
-       }
-       return error;
-}
-
 /*
  * Add a locked inode to the transaction.
  *
index d8e6f8cd6f0c89782dd0d5df7a2e7a0329688235..37d8146ee15b2022edecce33ffc896ed84c55e59 100644 (file)
@@ -1189,9 +1189,8 @@ xfs_inactive(
                 * inode might be lost for a long time or forever.
                 */
                if (!XFS_FORCED_SHUTDOWN(mp)) {
-                       cmn_err(CE_NOTE,
-               "xfs_inactive:  xfs_ifree() returned an error = %d on %s",
-                               error, mp->m_fsname);
+                       xfs_notice(mp, "%s: xfs_ifree returned error %d",
+                               __func__, error);
                        xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
                }
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
@@ -1208,12 +1207,12 @@ xfs_inactive(
                 */
                error = xfs_bmap_finish(&tp,  &free_list, &committed);
                if (error)
-                       xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
-                               "xfs_bmap_finish() returned error %d", error);
+                       xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
+                               __func__, error);
                error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
                if (error)
-                       xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
-                               "xfs_trans_commit() returned error %d", error);
+                       xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
+                               __func__, error);
        }
 
        /*
@@ -1310,7 +1309,7 @@ xfs_create(
        error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
-               goto std_return;
+               return error;
 
        if (is_dir) {
                rdev = 0;
@@ -1389,12 +1388,6 @@ xfs_create(
                goto out_trans_abort;
        }
 
-       /*
-        * At this point, we've gotten a newly allocated inode.
-        * It is locked (and joined to the transaction).
-        */
-       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
        /*
         * Now we join the directory inode to the transaction.  We do not do it
         * earlier because xfs_dir_ialloc might commit the previous transaction
@@ -1440,22 +1433,13 @@ xfs_create(
         */
        xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
 
-       /*
-        * xfs_trans_commit normally decrements the vnode ref count
-        * when it unlocks the inode. Since we want to return the
-        * vnode to the caller, we bump the vnode ref count now.
-        */
-       IHOLD(ip);
-
        error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error)
-               goto out_abort_rele;
+               goto out_bmap_cancel;
 
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-       if (error) {
-               IRELE(ip);
-               goto out_dqrele;
-       }
+       if (error)
+               goto out_release_inode;
 
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
@@ -1469,27 +1453,21 @@ xfs_create(
        cancel_flags |= XFS_TRANS_ABORT;
  out_trans_cancel:
        xfs_trans_cancel(tp, cancel_flags);
- out_dqrele:
+ out_release_inode:
+       /*
+        * Wait until after the current transaction is aborted to
+        * release the inode.  This prevents recursive transactions
+        * and deadlocks from xfs_inactive.
+        */
+       if (ip)
+               IRELE(ip);
+
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
 
        if (unlock_dp_on_error)
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
- std_return:
        return error;
-
- out_abort_rele:
-       /*
-        * Wait until after the current transaction is aborted to
-        * release the inode.  This prevents recursive transactions
-        * and deadlocks from xfs_inactive.
-        */
-       xfs_bmap_cancel(&free_list);
-       cancel_flags |= XFS_TRANS_ABORT;
-       xfs_trans_cancel(tp, cancel_flags);
-       IRELE(ip);
-       unlock_dp_on_error = B_FALSE;
-       goto out_dqrele;
 }
 
 #ifdef DEBUG
@@ -2114,9 +2092,8 @@ xfs_symlink(
                                  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
                                  &first_block, resblks, mval, &nmaps,
                                  &free_list);
-               if (error) {
-                       goto error1;
-               }
+               if (error)
+                       goto error2;
 
                if (resblks)
                        resblks -= fs_blocks;
@@ -2148,7 +2125,7 @@ xfs_symlink(
        error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
                                        &first_block, &free_list, resblks);
        if (error)
-               goto error1;
+               goto error2;
        xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
@@ -2161,13 +2138,6 @@ xfs_symlink(
                xfs_trans_set_sync(tp);
        }
 
-       /*
-        * xfs_trans_commit normally decrements the vnode ref count
-        * when it unlocks the inode. Since we want to return the
-        * vnode to the caller, we bump the vnode ref count now.
-        */
-       IHOLD(ip);
-
        error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                goto error2;
index 57af0338d2709972d7dfee827f67da05e2efdb7d..176b825add52691cb5abb2b52780dd75923d3377 100644 (file)
@@ -650,9 +650,13 @@ __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
 __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
 #define __NR_open_by_handle_at         265
 __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
+#define __NR_clock_adjtime 266
+__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs 264
+__SYSCALL(__NR_syncfs, sys_syncfs)
 
 #undef __NR_syscalls
-#define __NR_syscalls 266
+#define __NR_syscalls 268
 
 /*
  * All syscalls below here should go away really,
index 1a87760d65322b2d0528886b3232d2707f725532..f2afed4fa9454776c79611d52755121dff749342 100644 (file)
@@ -416,7 +416,6 @@ static inline bool d_mountpoint(struct dentry *dentry)
        return dentry->d_flags & DCACHE_MOUNTED;
 }
 
-extern struct vfsmount *lookup_mnt(struct path *);
 extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
 
 extern int sysctl_vfs_cache_pressure;
index fc023d67676f6e18be83551c8543806bc05e08b8..c64f3680d4f154b2bc2959380e0b04ecd5477d52 100644 (file)
@@ -93,7 +93,7 @@ struct fw_card {
        int current_tlabel;
        u64 tlabel_mask;
        struct list_head transaction_list;
-       unsigned long reset_jiffies;
+       u64 reset_jiffies;
 
        u32 split_timeout_hi;
        u32 split_timeout_lo;
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
deleted file mode 100644 (file)
index 4bef5c5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*                                                                          */
-/* i2c-id.h - identifier values for i2c drivers and adapters                */
-/*                                                                          */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-1999 Simon G. Vogl
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
-/* ------------------------------------------------------------------------- */
-
-#ifndef LINUX_I2C_ID_H
-#define LINUX_I2C_ID_H
-
-/* Please note that I2C driver IDs are optional. They are only needed if a
-   legacy chip driver needs to identify a bus or a bus driver needs to
-   identify a legacy client. If you don't need them, just don't set them. */
-
-/*
- * ---- Adapter types ----------------------------------------------------
- */
-
-/* --- Bit algorithm adapters                                          */
-#define I2C_HW_B_CX2388x       0x01001b /* connexant 2388x based tv cards */
-
-#endif /* LINUX_I2C_ID_H */
index 06a8d9c7de98765c3b73e1093c346de452c0fbd5..f1e3ff5880a9f1d6d505f2e1102aeceef10fdb47 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #ifdef __KERNEL__
 #include <linux/module.h>
-#include <linux/i2c-id.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>      /* for struct device */
 #include <linux/sched.h>       /* for completion */
@@ -105,8 +104,8 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
 /**
  * struct i2c_driver - represent an I2C device driver
  * @class: What kind of i2c device we instantiate (for detect)
- * @attach_adapter: Callback for bus addition (for legacy drivers)
- * @detach_adapter: Callback for bus removal (for legacy drivers)
+ * @attach_adapter: Callback for bus addition (deprecated)
+ * @detach_adapter: Callback for bus removal (deprecated)
  * @probe: Callback for device binding
  * @remove: Callback for device unbinding
  * @shutdown: Callback for device shutdown
@@ -144,11 +143,11 @@ struct i2c_driver {
        unsigned int class;
 
        /* Notifies the driver that a new bus has appeared or is about to be
-        * removed. You should avoid using this if you can, it will probably
-        * be removed in a near future.
+        * removed. You should avoid using this, it will be removed in a
+        * near future.
         */
-       int (*attach_adapter)(struct i2c_adapter *);
-       int (*detach_adapter)(struct i2c_adapter *);
+       int (*attach_adapter)(struct i2c_adapter *) __deprecated;
+       int (*detach_adapter)(struct i2c_adapter *) __deprecated;
 
        /* Standard driver model interfaces */
        int (*probe)(struct i2c_client *, const struct i2c_device_id *);
@@ -354,7 +353,6 @@ struct i2c_algorithm {
  */
 struct i2c_adapter {
        struct module *owner;
-       unsigned int id __deprecated;
        unsigned int class;               /* classes to allow probing for */
        const struct i2c_algorithm *algo; /* the algorithm to access the bus */
        void *algo_data;
@@ -396,6 +394,8 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
                return NULL;
 }
 
+int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *));
+
 /* Adapter locking functions, exported for shared pin cases */
 void i2c_lock_adapter(struct i2c_adapter *);
 void i2c_unlock_adapter(struct i2c_adapter *);
@@ -447,7 +447,7 @@ extern void i2c_release_client(struct i2c_client *client);
 extern void i2c_clients_command(struct i2c_adapter *adap,
                                unsigned int cmd, void *arg);
 
-extern struct i2c_adapter *i2c_get_adapter(int id);
+extern struct i2c_adapter *i2c_get_adapter(int nr);
 extern void i2c_put_adapter(struct i2c_adapter *adap);
 
 
diff --git a/include/linux/i2c/ads1015.h b/include/linux/i2c/ads1015.h
new file mode 100644 (file)
index 0000000..d5aa2a0
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Platform Data for ADS1015 12-bit 4-input ADC
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LINUX_ADS1015_H
+#define LINUX_ADS1015_H
+
+#define ADS1015_CHANNELS 8
+
+struct ads1015_channel_data {
+       bool enabled;
+       unsigned int pga;
+       unsigned int data_rate;
+};
+
+struct ads1015_platform_data {
+       struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+};
+
+#endif /* LINUX_ADS1015_H */
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
new file mode 100644 (file)
index 0000000..f027f7a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __LINUX_ATMEL_MXT_TS_H
+#define __LINUX_ATMEL_MXT_TS_H
+
+#include <linux/types.h>
+
+/* Orient */
+#define MXT_NORMAL             0x0
+#define MXT_DIAGONAL           0x1
+#define MXT_HORIZONTAL_FLIP    0x2
+#define MXT_ROTATED_90_COUNTER 0x3
+#define MXT_VERTICAL_FLIP      0x4
+#define MXT_ROTATED_90         0x5
+#define MXT_ROTATED_180                0x6
+#define MXT_DIAGONAL_COUNTER   0x7
+
+/* The platform data for the Atmel maXTouch touchscreen driver */
+struct mxt_platform_data {
+       const u8 *config;
+       size_t config_length;
+
+       unsigned int x_line;
+       unsigned int y_line;
+       unsigned int x_size;
+       unsigned int y_size;
+       unsigned int blen;
+       unsigned int threshold;
+       unsigned int voltage;
+       unsigned char orient;
+       unsigned long irqflags;
+};
+
+#endif /* __LINUX_ATMEL_MXT_TS_H */
index 725ae7c313ff3914ecd077df1e33b2c2a8e8b7d2..61bb18a4fd3c9946a19d90ea293f1d966042c0a4 100644 (file)
@@ -18,6 +18,7 @@
 #define MCS_KEY_CODE(v)                ((v) & 0xffff)
 
 struct mcs_platform_data {
+       void (*poweron)(bool);
        void (*cfg_pin)(void);
 
        /* touchscreen */
diff --git a/include/linux/i2c/qt602240_ts.h b/include/linux/i2c/qt602240_ts.h
deleted file mode 100644 (file)
index c5033e1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * AT42QT602240/ATMXT224 Touchscreen driver
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __LINUX_QT602240_TS_H
-#define __LINUX_QT602240_TS_H
-
-/* Orient */
-#define QT602240_NORMAL                        0x0
-#define QT602240_DIAGONAL              0x1
-#define QT602240_HORIZONTAL_FLIP       0x2
-#define QT602240_ROTATED_90_COUNTER    0x3
-#define QT602240_VERTICAL_FLIP         0x4
-#define QT602240_ROTATED_90            0x5
-#define QT602240_ROTATED_180           0x6
-#define QT602240_DIAGONAL_COUNTER      0x7
-
-/* The platform data for the AT42QT602240/ATMXT224 touchscreen driver */
-struct qt602240_platform_data {
-       unsigned int x_line;
-       unsigned int y_line;
-       unsigned int x_size;
-       unsigned int y_size;
-       unsigned int blen;
-       unsigned int threshold;
-       unsigned int voltage;
-       unsigned char orient;
-};
-
-#endif /* __LINUX_QT602240_TS_H */
index 5e3dddf8f562651f488dd4b3061fbfefabb98f7a..ce0b72464eb814bf5902e3daf423522934963b8c 100644 (file)
  * @poll: driver-supplied method that polls the device and posts
  *     input events (mandatory).
  * @poll_interval: specifies how often the poll() method should be called.
- *     Defaults to 500 msec unless overriden when registering the device.
+ *     Defaults to 500 msec unless overridden when registering the device.
  * @poll_interval_max: specifies upper bound for the poll interval.
  *     Defaults to the initial value of @poll_interval.
  * @poll_interval_min: specifies lower bound for the poll interval.
  *     Defaults to 0.
- * @input: input device structire associated with the polled device.
+ * @input: input device structure associated with the polled device.
  *     Must be properly initialized by the driver (id, name, phys, bits).
  *
  * Polled input device provides a skeleton for supporting simple input
index e428382ca28a59aac1a16f1f5926f28a3c7fb24b..056ae8a5bd9b8bb3424c431ff60bcc22c155b4da 100644 (file)
@@ -1154,8 +1154,6 @@ struct ff_effect {
  *     sparse keymaps. If not supplied default mechanism will be used.
  *     The method is being called while holding event_lock and thus must
  *     not sleep
- * @getkeycode_new: transition method
- * @setkeycode_new: transition method
  * @ff: force feedback structure associated with the device if device
  *     supports force feedback effects
  * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1234,14 +1232,10 @@ struct input_dev {
        void *keycode;
 
        int (*setkeycode)(struct input_dev *dev,
-                         unsigned int scancode, unsigned int keycode);
+                         const struct input_keymap_entry *ke,
+                         unsigned int *old_keycode);
        int (*getkeycode)(struct input_dev *dev,
-                         unsigned int scancode, unsigned int *keycode);
-       int (*setkeycode_new)(struct input_dev *dev,
-                             const struct input_keymap_entry *ke,
-                             unsigned int *old_keycode);
-       int (*getkeycode_new)(struct input_dev *dev,
-                             struct input_keymap_entry *ke);
+                         struct input_keymap_entry *ke);
 
        struct ff_device *ff;
 
index 6cfe344f9559604d4037b005860dfc279833ac99..1e5df2af8d845c6a2ff63115245c88cba4a95cdc 100644 (file)
@@ -23,6 +23,7 @@
 #define XENFS_SUPER_MAGIC      0xabba1974
 #define EXT4_SUPER_MAGIC       0xEF53
 #define BTRFS_SUPER_MAGIC      0x9123683E
+#define NILFS_SUPER_MAGIC      0x3434
 #define HPFS_SUPER_MAGIC       0xf995e849
 #define ISOFS_SUPER_MAGIC      0x9660
 #define JFFS2_SUPER_MAGIC      0x72b6
index fd322aca33ba89a9cec62eb7f3909f813b2267a5..173086d42af4dc2634fea9d62804e7a5c0312f8f 100644 (file)
@@ -80,7 +80,8 @@ struct wm831x_touch_pdata {
        int isel;              /** Current for pen down (uA) */
        int rpu;               /** Pen down sensitivity resistor divider */
        int pressure;          /** Report pressure (boolean) */
-       int data_irq;          /** Touch data ready IRQ */
+       unsigned int data_irq; /** Touch data ready IRQ */
+       unsigned int pd_irq;   /** Touch pendown detect IRQ */
 };
 
 enum wm831x_watchdog_action {
index 8ce082781ccb403385ec57b5989be5f5f6692a55..adb4888248be9a06219f71f39dceb06c60edd15d 100644 (file)
@@ -54,6 +54,9 @@ struct mmc_ext_csd {
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
        unsigned int            sec_erase_mult; /* Secure erase multiplier */
        unsigned int            trim_timeout;           /* In milliseconds */
+       bool                    enhanced_area_en;       /* enable bit */
+       unsigned long long      enhanced_area_offset;   /* Units: Byte */
+       unsigned int            enhanced_area_size;     /* Units: KB */
 };
 
 struct sd_scr {
@@ -121,6 +124,7 @@ struct mmc_card {
                                                /* for byte mode */
 #define MMC_QUIRK_NONSTD_SDIO  (1<<2)          /* non-standard SDIO card attached */
                                                /* (missing CIA registers) */
+#define MMC_QUIRK_BROKEN_CLK_GATING (1<<3)     /* clock gating the sdio bus will make card fail */
 
        unsigned int            erase_size;     /* erase size in sectors */
        unsigned int            erase_shift;    /* if erase unit is power 2 */
@@ -148,6 +152,8 @@ struct mmc_card {
        struct dentry           *debugfs_root;
 };
 
+void mmc_fixup_device(struct mmc_card *dev);
+
 #define mmc_card_mmc(c)                ((c)->type == MMC_TYPE_MMC)
 #define mmc_card_sd(c)         ((c)->type == MMC_TYPE_SD)
 #define mmc_card_sdio(c)       ((c)->type == MMC_TYPE_SDIO)
index 64e013f1cfb82a883a93982ec2cea3b42a0729fb..07f27af4dba5221b1139206cc2bd33858a3b38ef 100644 (file)
@@ -160,6 +160,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
 
 extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
 extern void mmc_release_host(struct mmc_host *host);
+extern void mmc_do_release_host(struct mmc_host *host);
 extern int mmc_try_claim_host(struct mmc_host *host);
 
 /**
index 16b0261763ed5189306c6e23e24383e96522211d..c0207a770476fbaa5c25db5f1045293c7409c4c2 100644 (file)
@@ -140,6 +140,7 @@ struct dw_mci {
        u32                     bus_hz;
        u32                     current_speed;
        u32                     num_slots;
+       u32                     fifoth_val;
        struct platform_device  *pdev;
        struct dw_mci_board     *pdata;
        struct dw_mci_slot      *slot[MAX_MCI_SLOTS];
@@ -151,6 +152,8 @@ struct dw_mci {
 
        /* Workaround flags */
        u32                     quirks;
+
+       struct regulator        *vmmc;  /* Power regulator */
 };
 
 /* DMA ops for Internal/External DMAC interface */
@@ -165,14 +168,14 @@ struct dw_mci_dma_ops {
 };
 
 /* IP Quirks/flags. */
-/* No special quirks or flags to cater for */
-#define DW_MCI_QUIRK_NONE              0
 /* DTO fix for command transmission with IDMAC configured */
-#define DW_MCI_QUIRK_IDMAC_DTO         1
+#define DW_MCI_QUIRK_IDMAC_DTO                 BIT(0)
 /* delay needed between retries on some 2.11a implementations */
-#define DW_MCI_QUIRK_RETRY_DELAY       2
+#define DW_MCI_QUIRK_RETRY_DELAY               BIT(1)
 /* High Speed Capable - Supports HS cards (upto 50MHz) */
-#define DW_MCI_QUIRK_HIGHSPEED         4
+#define DW_MCI_QUIRK_HIGHSPEED                 BIT(2)
+/* Unreliable card detection */
+#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION     BIT(3)
 
 
 struct dma_pdata;
@@ -192,6 +195,8 @@ struct dw_mci_board {
        u32 quirks; /* Workaround / Quirk flags */
        unsigned int bus_hz; /* Bus speed */
 
+       unsigned int caps;      /* Capabilities */
+
        /* delay in mS before detecting cards after interrupt */
        u32 detect_delay_ms;
 
index 612301f85d144608066f1131bc330a3007a7c1e0..264ba5451e3b98449832d94693d167792cec1f7b 100644 (file)
@@ -253,6 +253,8 @@ struct _mmc_csd {
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PARTITION_ATTRIBUTE    156     /* R/W */
+#define EXT_CSD_PARTITION_SUPPORT      160     /* RO */
 #define EXT_CSD_ERASE_GROUP_DEF                175     /* R/W */
 #define EXT_CSD_ERASED_MEM_CONT                181     /* RO */
 #define EXT_CSD_BUS_WIDTH              183     /* R/W */
@@ -262,6 +264,7 @@ struct _mmc_csd {
 #define EXT_CSD_CARD_TYPE              196     /* RO */
 #define EXT_CSD_SEC_CNT                        212     /* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT            217     /* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE         221     /* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT     223     /* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE      224     /* RO */
 #define EXT_CSD_SEC_TRIM_MULT          229     /* RO */
index 227e49dd5720f5743661aedfc43fa6cb1e461f94..8768c469e93e611f1636748cf5cabf8250896ec7 100644 (file)
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
-
-/*
- * Inode flags stored in nilfs_inode and on-memory nilfs inode
- *
- * We define these flags based on ext2-fs because of the
- * compatibility reason; to avoid problems in chattr(1)
- */
-#define NILFS_SECRM_FL         0x00000001 /* Secure deletion */
-#define NILFS_UNRM_FL          0x00000002 /* Undelete */
-#define NILFS_SYNC_FL          0x00000008 /* Synchronous updates */
-#define NILFS_IMMUTABLE_FL     0x00000010 /* Immutable file */
-#define NILFS_APPEND_FL                0x00000020 /* writes to file may only append */
-#define NILFS_NODUMP_FL                0x00000040 /* do not dump file */
-#define NILFS_NOATIME_FL       0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define NILFS_NOTAIL_FL                0x00008000 /* file tail should not be merged */
-#define NILFS_DIRSYNC_FL       0x00010000 /* dirsync behaviour */
-
-#define NILFS_FL_USER_VISIBLE  0x0003DFFF /* User visible flags */
-#define NILFS_FL_USER_MODIFIABLE       0x000380FF /* User modifiable flags */
+#include <linux/magic.h>
 
 
 #define NILFS_INODE_BMAP_SIZE  7
@@ -236,8 +217,10 @@ struct nilfs_super_block {
  * If there is a bit set in the incompatible feature set that the kernel
  * doesn't know about, it should refuse to mount the filesystem.
  */
+#define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT    0x00000001ULL
+
 #define NILFS_FEATURE_COMPAT_SUPP      0ULL
-#define NILFS_FEATURE_COMPAT_RO_SUPP   0ULL
+#define NILFS_FEATURE_COMPAT_RO_SUPP   NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT
 #define NILFS_FEATURE_INCOMPAT_SUPP    0ULL
 
 /*
@@ -260,7 +243,6 @@ struct nilfs_super_block {
 #define NILFS_USER_INO         11      /* Fisrt user's file inode number */
 
 #define NILFS_SB_OFFSET_BYTES  1024    /* byte offset of nilfs superblock */
-#define NILFS_SUPER_MAGIC      0x3434  /* NILFS filesystem  magic number */
 
 #define NILFS_SEG_MIN_BLOCKS   16      /* Minimum number of blocks in
                                           a full segment */
@@ -346,17 +328,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen)
 {
        unsigned len = le16_to_cpu(dlen);
 
+#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
        if (len == NILFS_MAX_REC_LEN)
                return 1 << 16;
+#endif
        return len;
 }
 
 static inline __le16 nilfs_rec_len_to_disk(unsigned len)
 {
+#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
        if (len == (1 << 16))
                return cpu_to_le16(NILFS_MAX_REC_LEN);
        else if (len > (1 << 16))
                BUG();
+#endif
        return cpu_to_le16(len);
 }
 
@@ -525,7 +511,7 @@ struct nilfs_checkpoint {
        __le64 cp_create;
        __le64 cp_nblk_inc;
        __le64 cp_inodes_count;
-       __le64 cp_blocks_count;         /* Reserved (might be deleted) */
+       __le64 cp_blocks_count;
 
        /* Do not change the byte offset of ifile inode.
           To keep the compatibility of the disk format,
diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h
new file mode 100644 (file)
index 0000000..d9b0c84
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file is part of TSC2005 touchscreen driver
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Contact: Aaro Koskinen <aaro.koskinen@nokia.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
+ *
+ */
+
+#ifndef _LINUX_SPI_TSC2005_H
+#define _LINUX_SPI_TSC2005_H
+
+#include <linux/types.h>
+
+struct tsc2005_platform_data {
+       int             ts_pressure_max;
+       int             ts_pressure_fudge;
+       int             ts_x_max;
+       int             ts_x_fudge;
+       int             ts_y_max;
+       int             ts_y_fudge;
+       int             ts_x_plate_ohm;
+       unsigned int    esd_timeout_ms;
+       void            (*set_reset)(bool enable);
+};
+
+#endif
index 1f5c18e6f4f17bedfbd38e64da3cc112d1cb90bb..83ecc1749ef6153581d295706d6c4768c11931e0 100644 (file)
@@ -825,6 +825,7 @@ asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags
 asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
                                  u64 mask, int fd,
                                  const char  __user *pathname);
+asmlinkage long sys_syncfs(int fd);
 
 int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
 
index 3f761001d517e2e3ae3b92f24cd85bcd6cd32262..e97ca59e2520dce3a3c0d7b2460d444e1b7591c0 100644 (file)
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
+ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
 obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
index c350e18b53e3f4d5f7683680634de3f2bf1bf3a3..c5ebc6a9064390583ed4f9cb6c11cf857fd0c318 100644 (file)
@@ -1,4 +1,5 @@
-ccflags-$(CONFIG_PM_DEBUG)     :=      -DDEBUG
+
+ccflags-$(CONFIG_PM_DEBUG)     := -DDEBUG
 
 obj-$(CONFIG_PM)               += main.o
 obj-$(CONFIG_PM_SLEEP)         += console.o
index 4e3cff10fdceda165e8e9f22c0e9b861dba918d8..31751868de8856cbe4ee909ef09915e6a9a9c679 100644 (file)
@@ -2421,9 +2421,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
                return -EFAULT;
 
        /* Not even root can pretend to send signals from the kernel.
-          Nor can they impersonate a kill(), which adds source info.  */
-       if (info.si_code >= 0)
+        * Nor can they impersonate a kill()/tgkill(), which adds source info.
+        */
+       if (info.si_code != SI_QUEUE) {
+               /* We used to allow any < 0 si_code */
+               WARN_ON_ONCE(info.si_code < 0);
                return -EPERM;
+       }
        info.si_signo = sig;
 
        /* POSIX.1b doesn't mention process groups.  */
@@ -2437,9 +2441,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
                return -EINVAL;
 
        /* Not even root can pretend to send signals from the kernel.
-          Nor can they impersonate a kill(), which adds source info.  */
-       if (info->si_code >= 0)
+        * Nor can they impersonate a kill()/tgkill(), which adds source info.
+        */
+       if (info->si_code != SI_QUEUE) {
+               /* We used to allow any < 0 si_code */
+               WARN_ON_ONCE(info->si_code < 0);
                return -EPERM;
+       }
        info->si_signo = sig;
 
        return do_send_specific(tgid, pid, sig, info);
index 6f440d82b58db05e63d3a2ff9e32918e74974ebc..191c5c4c89fcf92fc18e3728cd382f4f39f8e1ce 100644 (file)
@@ -102,11 +102,6 @@ config HEADERS_CHECK
 
 config DEBUG_SECTION_MISMATCH
        bool "Enable full Section mismatch analysis"
-       depends on UNDEFINED || (BLACKFIN)
-       default y
-       # This option is on purpose disabled for now.
-       # It will be enabled when we are down to a reasonable number
-       # of section mismatch warnings (< 10 for an allyesconfig build)
        help
          The section mismatch analysis checks if there are illegal
          references from one section to another section.
index 2e088109fbd5238f3e4f6d293848606d0ac95a58..fcea26168bca718afb07cf4a2a71081b309e906e 100644 (file)
@@ -18,6 +18,11 @@ always               := $(hostprogs-y) $(hostprogs-m)
 # The following hostprogs-y programs are only build on demand
 hostprogs-y += unifdef
 
+# This target is used internally to avoid "is up to date" messages
+PHONY += build_unifdef
+build_unifdef: scripts/unifdef FORCE
+       @:
+
 subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
index 4eb99ab34053769f5b2b644594427b2bdc108c82..d5f925abe4d29710ab0b314bf28d29752b35dc8d 100644 (file)
@@ -49,6 +49,40 @@ ifeq ($(KBUILD_NOPEDANTIC),)
                 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS)
         endif
 endif
+
+#
+# make W=1 settings
+#
+# $(call cc-option... ) handles gcc -W.. options which
+# are not supported by all versions of the compiler
+ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
+KBUILD_EXTRA_WARNINGS := -Wextra
+KBUILD_EXTRA_WARNINGS += -Wunused -Wno-unused-parameter
+KBUILD_EXTRA_WARNINGS += -Waggregate-return
+KBUILD_EXTRA_WARNINGS += -Wbad-function-cast
+KBUILD_EXTRA_WARNINGS += -Wcast-qual
+KBUILD_EXTRA_WARNINGS += -Wcast-align
+KBUILD_EXTRA_WARNINGS += -Wconversion
+KBUILD_EXTRA_WARNINGS += -Wdisabled-optimization
+KBUILD_EXTRA_WARNINGS += -Wlogical-op
+KBUILD_EXTRA_WARNINGS += -Wmissing-declarations
+KBUILD_EXTRA_WARNINGS += -Wmissing-format-attribute
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wmissing-include-dirs,)
+KBUILD_EXTRA_WARNINGS += -Wmissing-prototypes
+KBUILD_EXTRA_WARNINGS += -Wnested-externs
+KBUILD_EXTRA_WARNINGS += -Wold-style-definition
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Woverlength-strings,)
+KBUILD_EXTRA_WARNINGS += -Wpacked
+KBUILD_EXTRA_WARNINGS += -Wpacked-bitfield-compat
+KBUILD_EXTRA_WARNINGS += -Wpadded
+KBUILD_EXTRA_WARNINGS += -Wpointer-arith
+KBUILD_EXTRA_WARNINGS += -Wredundant-decls
+KBUILD_EXTRA_WARNINGS += -Wshadow
+KBUILD_EXTRA_WARNINGS += -Wswitch-default
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wvla,)
+KBUILD_CFLAGS += $(KBUILD_EXTRA_WARNINGS)
+endif
+
 include scripts/Makefile.lib
 
 ifdef host-progs
@@ -403,7 +437,6 @@ ifneq ($(cmd_files),)
   include $(cmd_files)
 endif
 
-
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable se we can use it in if_changed and friends.
 
index 1512c0a755acea37da3d190c88ae47c04023f883..e1862429ccda55ea41f760acd299ea6747319f0c 100755 (executable)
@@ -56,10 +56,11 @@ trap "rm -f $tmp1 $tmp2" 0
 dump_config "$img"
 
 # That didn't work, so retry after decompression.
-try_decompress '\037\213\010' xy  gunzip
-try_decompress 'BZh'          xy  bunzip2
-try_decompress '\135\0\0\0'   xxx unlzma
-try_decompress '\211\114\132' xy  'lzop -d'
+try_decompress '\037\213\010' xy    gunzip
+try_decompress '\3757zXZ\000' abcde unxz
+try_decompress 'BZh'          xy    bunzip2
+try_decompress '\135\0\0\0'   xxx   unlzma
+try_decompress '\211\114\132' xy    'lzop -d'
 
 # Bail out:
 echo "$me: Cannot find kernel config." >&2
index e420fe440019fd7c1ea8c0a80319f68bd6f4983b..13d03cf05d95115571839e2c791fc87fa1c9612a 100644 (file)
@@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE
 # flex
 
 quiet_cmd_lex.c = FLEX    $@
-      cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h
+      cmd_lex.c = flex -o$@ -d $<
 
-$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE
+$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE
        $(call if_changed,lex.c)
        cp $@ $@_shipped
 
index f99115ebe9254a4ef630eabe127bc7cf25e2195c..f9e75531ea0390836bfdc0fa5c8ad5b42ca12924 100644 (file)
@@ -53,12 +53,22 @@ static int nsyms;
 static struct symbol *expansion_trail;
 static struct symbol *visited_symbols;
 
-static const char *const symbol_type_name[] = {
-       "normal", "typedef", "enum", "struct", "union"
+static const struct {
+       int n;
+       const char *name;
+} symbol_types[] = {
+       [SYM_NORMAL]     = { 0, NULL},
+       [SYM_TYPEDEF]    = {'t', "typedef"},
+       [SYM_ENUM]       = {'e', "enum"},
+       [SYM_STRUCT]     = {'s', "struct"},
+       [SYM_UNION]      = {'u', "union"},
+       [SYM_ENUM_CONST] = {'E', "enum constant"},
 };
 
 static int equal_list(struct string_list *a, struct string_list *b);
 static void print_list(FILE * f, struct string_list *list);
+static struct string_list *concat_list(struct string_list *start, ...);
+static struct string_list *mk_node(const char *string);
 static void print_location(void);
 static void print_type_name(enum symbol_type type, const char *name);
 
@@ -140,14 +150,20 @@ static unsigned long crc32(const char *s)
 
 static enum symbol_type map_to_ns(enum symbol_type t)
 {
-       if (t == SYM_TYPEDEF)
-               t = SYM_NORMAL;
-       else if (t == SYM_UNION)
-               t = SYM_STRUCT;
+       switch (t) {
+       case SYM_ENUM_CONST:
+       case SYM_NORMAL:
+       case SYM_TYPEDEF:
+               return SYM_NORMAL;
+       case SYM_ENUM:
+       case SYM_STRUCT:
+       case SYM_UNION:
+               return SYM_STRUCT;
+       }
        return t;
 }
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns)
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
 {
        unsigned long h = crc32(name) % HASH_BUCKETS;
        struct symbol *sym;
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
                    sym->is_declared)
                        break;
 
+       if (exact && sym && sym->type != ns)
+               return NULL;
        return sym;
 }
 
@@ -180,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
                            struct string_list *defn, int is_extern,
                            int is_reference)
 {
-       unsigned long h = crc32(name) % HASH_BUCKETS;
+       unsigned long h;
        struct symbol *sym;
        enum symbol_status status = STATUS_UNCHANGED;
+       /* The parser adds symbols in the order their declaration completes,
+        * so it is safe to store the value of the previous enum constant in
+        * a static variable.
+        */
+       static int enum_counter;
+       static struct string_list *last_enum_expr;
+
+       if (type == SYM_ENUM_CONST) {
+               if (defn) {
+                       free_list(last_enum_expr, NULL);
+                       last_enum_expr = copy_list_range(defn, NULL);
+                       enum_counter = 1;
+               } else {
+                       struct string_list *expr;
+                       char buf[20];
+
+                       snprintf(buf, sizeof(buf), "%d", enum_counter++);
+                       if (last_enum_expr) {
+                               expr = copy_list_range(last_enum_expr, NULL);
+                               defn = concat_list(mk_node("("),
+                                                  expr,
+                                                  mk_node(")"),
+                                                  mk_node("+"),
+                                                  mk_node(buf), NULL);
+                       } else {
+                               defn = mk_node(buf);
+                       }
+               }
+       } else if (type == SYM_ENUM) {
+               free_list(last_enum_expr, NULL);
+               last_enum_expr = NULL;
+               enum_counter = 0;
+               if (!name)
+                       /* Anonymous enum definition, nothing more to do */
+                       return NULL;
+       }
 
+       h = crc32(name) % HASH_BUCKETS;
        for (sym = symtab[h]; sym; sym = sym->hash_next) {
                if (map_to_ns(sym->type) == map_to_ns(type) &&
                    strcmp(name, sym->name) == 0) {
@@ -247,8 +302,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
        sym->is_override = 0;
 
        if (flag_debug) {
-               fprintf(debugfile, "Defn for %s %s == <",
-                       symbol_type_name[type], name);
+               if (symbol_types[type].name)
+                       fprintf(debugfile, "Defn for %s %s == <",
+                               symbol_types[type].name, name);
+               else
+                       fprintf(debugfile, "Defn for type%d %s == <",
+                               type, name);
                if (is_extern)
                        fputs("extern ", debugfile);
                print_list(debugfile, defn);
@@ -288,6 +347,35 @@ void free_list(struct string_list *s, struct string_list *e)
        }
 }
 
+static struct string_list *mk_node(const char *string)
+{
+       struct string_list *newnode;
+
+       newnode = xmalloc(sizeof(*newnode));
+       newnode->string = xstrdup(string);
+       newnode->tag = SYM_NORMAL;
+       newnode->next = NULL;
+
+       return newnode;
+}
+
+static struct string_list *concat_list(struct string_list *start, ...)
+{
+       va_list ap;
+       struct string_list *n, *n2;
+
+       if (!start)
+               return NULL;
+       for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
+               for (n2 = n; n2->next; n2 = n2->next)
+                       ;
+               n2->next = start;
+               start = n;
+       }
+       va_end(ap);
+       return start;
+}
+
 struct string_list *copy_node(struct string_list *node)
 {
        struct string_list *newnode;
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node)
        return newnode;
 }
 
+struct string_list *copy_list_range(struct string_list *start,
+                                   struct string_list *end)
+{
+       struct string_list *res, *n;
+
+       if (start == end)
+               return NULL;
+       n = res = copy_node(start);
+       for (start = start->next; start != end; start = start->next) {
+               n->next = copy_node(start);
+               n = n->next;
+       }
+       n->next = NULL;
+       return res;
+}
+
 static int equal_list(struct string_list *a, struct string_list *b)
 {
        while (a && b) {
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f)
        if (node.string[1] == '#') {
                int n;
 
-               for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
-                       if (node.string[0] == symbol_type_name[n][0]) {
+               for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
+                       if (node.string[0] == symbol_types[n].n) {
                                node.tag = n;
                                node.string += 2;
                                return copy_node(&node);
@@ -397,8 +501,8 @@ static void read_reference(FILE *f)
 
 static void print_node(FILE * f, struct string_list *list)
 {
-       if (list->tag != SYM_NORMAL) {
-               putc(symbol_type_name[list->tag][0], f);
+       if (symbol_types[list->tag].n) {
+               putc(symbol_types[list->tag].n, f);
                putc('#', f);
        }
        fputs(list->string, f);
@@ -468,8 +572,9 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
                        crc = partial_crc32_one(' ', crc);
                        break;
 
+               case SYM_ENUM_CONST:
                case SYM_TYPEDEF:
-                       subsym = find_symbol(cur->string, cur->tag);
+                       subsym = find_symbol(cur->string, cur->tag, 0);
                        /* FIXME: Bad reference files can segfault here. */
                        if (subsym->expansion_trail) {
                                if (flag_dump_defs)
@@ -486,55 +591,30 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
                case SYM_STRUCT:
                case SYM_UNION:
                case SYM_ENUM:
-                       subsym = find_symbol(cur->string, cur->tag);
+                       subsym = find_symbol(cur->string, cur->tag, 0);
                        if (!subsym) {
-                               struct string_list *n, *t = NULL;
+                               struct string_list *n;
 
                                error_with_pos("expand undefined %s %s",
-                                              symbol_type_name[cur->tag],
+                                              symbol_types[cur->tag].name,
                                               cur->string);
-
-                               n = xmalloc(sizeof(*n));
-                               n->string = xstrdup(symbol_type_name[cur->tag]);
-                               n->tag = SYM_NORMAL;
-                               n->next = t;
-                               t = n;
-
-                               n = xmalloc(sizeof(*n));
-                               n->string = xstrdup(cur->string);
-                               n->tag = SYM_NORMAL;
-                               n->next = t;
-                               t = n;
-
-                               n = xmalloc(sizeof(*n));
-                               n->string = xstrdup("{");
-                               n->tag = SYM_NORMAL;
-                               n->next = t;
-                               t = n;
-
-                               n = xmalloc(sizeof(*n));
-                               n->string = xstrdup("UNKNOWN");
-                               n->tag = SYM_NORMAL;
-                               n->next = t;
-                               t = n;
-
-                               n = xmalloc(sizeof(*n));
-                               n->string = xstrdup("}");
-                               n->tag = SYM_NORMAL;
-                               n->next = t;
-                               t = n;
-
+                               n = concat_list(mk_node
+                                               (symbol_types[cur->tag].name),
+                                               mk_node(cur->string),
+                                               mk_node("{"),
+                                               mk_node("UNKNOWN"),
+                                               mk_node("}"), NULL);
                                subsym =
                                    add_symbol(cur->string, cur->tag, n, 0);
                        }
                        if (subsym->expansion_trail) {
                                if (flag_dump_defs) {
                                        fprintf(debugfile, "%s %s ",
-                                               symbol_type_name[cur->tag],
+                                               symbol_types[cur->tag].name,
                                                cur->string);
                                }
 
-                               crc = partial_crc32(symbol_type_name[cur->tag],
+                               crc = partial_crc32(symbol_types[cur->tag].name,
                                                    crc);
                                crc = partial_crc32_one(' ', crc);
                                crc = partial_crc32(cur->string, crc);
@@ -565,7 +645,7 @@ void export_symbol(const char *name)
 {
        struct symbol *sym;
 
-       sym = find_symbol(name, SYM_NORMAL);
+       sym = find_symbol(name, SYM_NORMAL, 0);
        if (!sym)
                error_with_pos("export undefined symbol %s", name);
        else {
@@ -624,8 +704,8 @@ static void print_location(void)
 
 static void print_type_name(enum symbol_type type, const char *name)
 {
-       if (type != SYM_NORMAL)
-               fprintf(stderr, "%s %s", symbol_type_name[type], name);
+       if (symbol_types[type].name)
+               fprintf(stderr, "%s %s", symbol_types[type].name, name);
        else
                fprintf(stderr, "%s", name);
 }
@@ -771,8 +851,8 @@ int main(int argc, char **argv)
 
                        if (sym->is_override)
                                fputs("override ", dumpfile);
-                       if (sym->type != SYM_NORMAL) {
-                               putc(symbol_type_name[sym->type][0], dumpfile);
+                       if (symbol_types[sym->type].n) {
+                               putc(symbol_types[sym->type].n, dumpfile);
                                putc('#', dumpfile);
                        }
                        fputs(sym->name, dumpfile);
index 25c4d40cefc134f2609593ed60546daba55e1aab..7ec52ae3846aa3c2b70837fd652d7e20bbf9dcb0 100644 (file)
@@ -26,7 +26,8 @@
 #include <stdio.h>
 
 enum symbol_type {
-       SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
+       SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION,
+       SYM_ENUM_CONST
 };
 
 enum symbol_status {
@@ -58,7 +59,7 @@ typedef struct string_list **yystype;
 extern int cur_line;
 extern char *cur_filename;
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns);
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact);
 struct symbol *add_symbol(const char *name, enum symbol_type type,
                          struct string_list *defn, int is_extern);
 void export_symbol(const char *);
@@ -66,6 +67,8 @@ void export_symbol(const char *);
 void free_node(struct string_list *list);
 void free_list(struct string_list *s, struct string_list *e);
 struct string_list *copy_node(struct string_list *);
+struct string_list *copy_list_range(struct string_list *start,
+                                   struct string_list *end);
 
 int yylex(void);
 int yyparse(void);
index 2ac23bcca5b537fad4c8b06401404b20adb03e9e..af4939041e4b6f082a446fab07b5d79addf30ef0 100644 (file)
@@ -79,6 +79,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -109,8 +110,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 /* %endif */
@@ -456,16 +455,16 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[76] =
+static yyconst flex_int16_t yy_accept[73] =
     {   0,
-        0,    0,    0,    0,   14,   12,    4,    3,   12,    7,
-       12,   12,    7,   12,   12,   12,   12,   12,    9,    9,
-       12,   12,   12,    4,    0,    5,    0,    7,    0,    6,
-        0,    0,    0,    0,    0,    0,    2,    8,   10,   10,
-        9,    0,    0,    9,    9,    0,    9,    0,    0,   11,
-        0,    0,    0,   10,    0,   10,    9,    9,    0,    0,
-        0,    0,    0,    0,    0,   10,   10,    0,    0,    0,
-        0,    0,    0,    1,    0
+        0,    0,   14,   12,    4,    3,   12,    7,   12,   12,
+       12,   12,   12,    9,    9,   12,   12,    7,   12,   12,
+        4,    0,    5,    0,    7,    8,    0,    6,    0,    0,
+       10,   10,    9,    0,    0,    9,    9,    0,    9,    0,
+        0,    0,    0,    2,    0,    0,   11,    0,   10,    0,
+       10,    9,    9,    0,    0,    0,   10,   10,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        1,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -507,108 +506,104 @@ static yyconst flex_int32_t yy_meta[29] =
         8,    7,    3,    3,    3,    1,    3,    1
     } ;
 
-static yyconst flex_int16_t yy_base[88] =
+static yyconst flex_int16_t yy_base[85] =
     {   0,
-        0,  147,   21,  140,  145,  284,   39,  284,   26,    0,
-       32,  126,   40,   44,  115,   35,   36,   46,   50,   53,
-       39,   61,   54,   79,   65,  284,    0,    0,   66,  284,
-        0,  119,   79,   75,  123,  104,  284,  284,  107,    0,
-       79,   73,   76,   76,   66,    0,    0,   85,   86,  284,
-      133,   83,   91,  284,   99,  147,  284,  114,  122,   70,
-      107,  141,  172,  151,  135,  181,  284,  137,  114,  157,
-      149,   48,   45,  284,  284,  208,  214,  222,  230,  238,
-      246,  250,  255,  256,  261,  267,  275
+        0,  145,  150,  266,   27,  266,   25,    0,  131,   23,
+       23,   16,   23,   39,   31,   25,   39,   60,   22,   65,
+       57,   43,  266,    0,    0,  266,   61,  266,    0,  128,
+       74,    0,  113,   59,   62,  113,   52,    0,    0,   72,
+       66,  110,  100,  266,   73,   74,  266,   70,  266,   90,
+      103,  266,   84,  129,  108,  113,  143,  266,  107,   66,
+      118,  137,  168,  120,   80,   91,  145,  143,   83,   41,
+      266,  266,  190,  196,  204,  212,  220,  228,  232,  237,
+      238,  243,  249,  257
     } ;
 
-static yyconst flex_int16_t yy_def[88] =
+static yyconst flex_int16_t yy_def[85] =
     {   0,
-       75,    1,    1,    3,   75,   75,   75,   75,   76,   77,
-       78,   75,   77,   79,   75,   75,   75,   75,   75,   19,
-       75,   75,   75,   75,   76,   75,   80,   77,   78,   75,
-       81,   75,   76,   78,   79,   79,   75,   75,   75,   39,
-       19,   82,   83,   75,   75,   84,   20,   76,   78,   75,
-       79,   51,   85,   75,   75,   75,   75,   84,   79,   51,
-       79,   79,   79,   51,   75,   75,   75,   86,   79,   63,
-       86,   87,   87,   75,    0,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75
+       72,    1,   72,   72,   72,   72,   73,   74,   72,   72,
+       75,   72,   72,   72,   14,   72,   72,   74,   72,   76,
+       72,   73,   72,   77,   74,   72,   75,   72,   78,   72,
+       72,   31,   14,   79,   80,   72,   72,   81,   15,   73,
+       75,   76,   76,   72,   73,   75,   72,   82,   72,   72,
+       72,   72,   81,   76,   54,   72,   72,   72,   76,   54,
+       76,   76,   76,   54,   83,   76,   63,   83,   84,   84,
+       72,    0,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
     } ;
 
-static yyconst flex_int16_t yy_nxt[313] =
+static yyconst flex_int16_t yy_nxt[295] =
     {   0,
-        6,    7,    8,    7,    9,    6,   10,    6,    6,   11,
-        6,    6,   12,    6,    6,    6,    6,    6,    6,   10,
-       10,   10,   13,   10,   10,    6,   10,    6,   15,   16,
-       26,   15,   17,   18,   19,   20,   20,   21,   15,   22,
-       24,   30,   24,   38,   33,   36,   37,   74,   23,   34,
-       74,   27,   38,   38,   38,   38,   38,   31,   32,   39,
-       39,   39,   40,   41,   41,   42,   47,   47,   47,   26,
-       43,   38,   44,   45,   46,   30,   44,   75,   38,   38,
-       24,   38,   24,   26,   30,   40,   55,   55,   57,   26,
-       27,   31,   57,   43,   35,   30,   64,   64,   64,   57,
-
-       31,   65,   65,   75,   27,   36,   37,   35,   59,   37,
-       27,   31,   56,   56,   56,   59,   37,   51,   52,   52,
-       39,   39,   39,   59,   37,   37,   68,   53,   54,   54,
-       69,   50,   38,   54,   59,   37,   44,   45,   32,   37,
-       44,   35,   59,   37,   75,   14,   60,   60,   66,   66,
-       66,   37,   14,   72,   75,   61,   62,   63,   59,   61,
-       56,   56,   56,   69,   64,   64,   64,   69,   67,   67,
-       75,   75,   75,   67,   37,   35,   75,   75,   75,   61,
-       62,   75,   75,   61,   75,   70,   70,   70,   75,   75,
-       75,   70,   70,   70,   66,   66,   66,   75,   75,   75,
-
-       75,   75,   54,   54,   75,   75,   75,   54,   25,   25,
-       25,   25,   25,   25,   25,   25,   28,   75,   75,   28,
-       28,   28,   29,   29,   29,   29,   29,   29,   29,   29,
-       35,   35,   35,   35,   35,   35,   35,   35,   48,   75,
-       48,   48,   48,   48,   48,   48,   49,   75,   49,   49,
-       49,   49,   49,   49,   42,   42,   75,   42,   56,   75,
-       56,   58,   58,   58,   66,   75,   66,   71,   71,   71,
-       71,   71,   71,   71,   71,   73,   73,   73,   73,   73,
-       73,   73,   73,    5,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
+        9,   12,   13,   14,   15,   15,   16,    9,   17,    8,
+        8,    8,   18,    8,    8,    4,    8,   19,   21,   23,
+       21,   26,   28,   26,   26,   30,   31,   31,   31,   26,
+       26,   26,   26,   71,   39,   39,   39,   23,   29,   26,
+       24,   32,   33,   33,   34,   72,   26,   26,   21,   35,
+       21,   36,   37,   38,   40,   36,   43,   44,   24,   41,
+       28,   32,   50,   50,   52,   28,   23,   23,   52,   35,
+       56,   56,   44,   28,   42,   71,   29,   31,   31,   31,
+       42,   29,   59,   44,   48,   49,   49,   24,   24,   29,
+
+       49,   43,   44,   51,   51,   51,   36,   37,   59,   44,
+       36,   65,   44,   54,   55,   55,   51,   51,   51,   59,
+       44,   64,   64,   64,   58,   58,   57,   57,   57,   58,
+       59,   44,   42,   64,   64,   64,   52,   72,   59,   44,
+       47,   66,   60,   60,   42,   44,   59,   69,   26,   72,
+       20,   61,   62,   63,   72,   61,   57,   57,   57,   66,
+       72,   72,   72,   66,   49,   49,   72,   61,   62,   49,
+       44,   61,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   67,   67,   67,   72,   72,   72,   67,   67,   67,
+       22,   22,   22,   22,   22,   22,   22,   22,   25,   72,
+
+       72,   25,   25,   25,   27,   27,   27,   27,   27,   27,
+       27,   27,   42,   42,   42,   42,   42,   42,   42,   42,
+       45,   72,   45,   45,   45,   45,   45,   45,   46,   72,
+       46,   46,   46,   46,   46,   46,   34,   34,   72,   34,
+       51,   72,   51,   53,   53,   53,   57,   72,   57,   68,
+       68,   68,   68,   68,   68,   68,   68,   70,   70,   70,
+       70,   70,   70,   70,   70,    3,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
-static yyconst flex_int16_t yy_chk[313] =
+static yyconst flex_int16_t yy_chk[295] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
-        9,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        7,   11,    7,   16,   13,   14,   14,   73,    3,   13,
-       72,    9,   16,   17,   17,   21,   21,   11,   18,   18,
-       18,   18,   19,   19,   19,   19,   20,   20,   20,   25,
-       19,   23,   19,   19,   19,   29,   19,   20,   22,   22,
-       24,   23,   24,   33,   34,   42,   43,   43,   45,   48,
-       25,   29,   45,   42,   60,   49,   52,   52,   52,   44,
-
-       34,   53,   53,   41,   33,   36,   36,   52,   61,   61,
-       48,   49,   55,   55,   55,   69,   69,   36,   36,   36,
-       39,   39,   39,   59,   59,   35,   59,   39,   39,   39,
-       61,   32,   15,   39,   51,   51,   58,   58,   12,   68,
-       58,   68,   62,   62,    5,    4,   51,   51,   65,   65,
-       65,   71,    2,   71,    0,   51,   51,   51,   70,   51,
-       56,   56,   56,   62,   64,   64,   64,   62,   56,   56,
-        0,    0,    0,   56,   63,   64,    0,    0,    0,   70,
-       70,    0,    0,   70,    0,   63,   63,   63,    0,    0,
-        0,   63,   63,   63,   66,   66,   66,    0,    0,    0,
-
-        0,    0,   66,   66,    0,    0,    0,   66,   76,   76,
-       76,   76,   76,   76,   76,   76,   77,    0,    0,   77,
-       77,   77,   78,   78,   78,   78,   78,   78,   78,   78,
-       79,   79,   79,   79,   79,   79,   79,   79,   80,    0,
-       80,   80,   80,   80,   80,   80,   81,    0,   81,   81,
-       81,   81,   81,   81,   82,   82,    0,   82,   83,    0,
-       83,   84,   84,   84,   85,    0,   85,   86,   86,   86,
-       86,   86,   86,   86,   86,   87,   87,   87,   87,   87,
-       87,   87,   87,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        1,    1,    1,    1,    1,    1,    1,    1,    5,    7,
+        5,   10,   11,   12,   12,   13,   13,   13,   13,   19,
+       10,   16,   16,   70,   15,   15,   15,   22,   11,   19,
+        7,   14,   14,   14,   14,   15,   17,   17,   21,   14,
+       21,   14,   14,   14,   18,   14,   20,   20,   22,   18,
+       27,   34,   35,   35,   37,   41,   40,   45,   37,   34,
+       48,   48,   65,   46,   65,   69,   27,   31,   31,   31,
+       60,   41,   66,   66,   31,   31,   31,   40,   45,   46,
+
+       31,   43,   43,   50,   50,   50,   53,   53,   59,   59,
+       53,   59,   42,   43,   43,   43,   51,   51,   51,   61,
+       61,   55,   55,   55,   51,   51,   56,   56,   56,   51,
+       54,   54,   55,   64,   64,   64,   36,   33,   62,   62,
+       30,   61,   54,   54,   64,   68,   67,   68,    9,    3,
+        2,   54,   54,   54,    0,   54,   57,   57,   57,   62,
+        0,    0,    0,   62,   57,   57,    0,   67,   67,   57,
+       63,   67,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   63,   63,   63,    0,    0,    0,   63,   63,   63,
+       73,   73,   73,   73,   73,   73,   73,   73,   74,    0,
+
+        0,   74,   74,   74,   75,   75,   75,   75,   75,   75,
+       75,   75,   76,   76,   76,   76,   76,   76,   76,   76,
+       77,    0,   77,   77,   77,   77,   77,   77,   78,    0,
+       78,   78,   78,   78,   78,   78,   79,   79,    0,   79,
+       80,    0,   80,   81,   81,   81,   82,    0,   82,   83,
+       83,   83,   83,   83,   83,   83,   83,   84,   84,   84,
+       84,   84,   84,   84,   84,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -619,8 +614,8 @@ int yy_flex_debug = 1;
 
 static yyconst flex_int16_t yy_rule_linenum[13] =
     {   0,
-       71,   72,   73,   76,   79,   80,   81,   87,   88,   89,
-       91,   94
+       67,   68,   69,   72,   75,   76,   77,   83,   84,   85,
+       87,   90
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -667,15 +662,11 @@ char *yytext;
    and then we categorize those basic tokens in the second stage.  */
 #define YY_DECL                static int yylex1(void)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-
 /* We don't do multiple input files.  */
 #define YY_NO_INPUT 1
-#line 676 "scripts/genksyms/lex.c"
+#line 668 "scripts/genksyms/lex.c"
 
 #define INITIAL 0
-#define V2_TOKENS 1
 
 #ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -808,7 +799,7 @@ static int input (void );
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
                { \
                int c = '*'; \
-               size_t n; \
+               int n; \
                for ( n = 0; n < max_size && \
                             (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
                        buf[n] = (char) c; \
@@ -918,12 +909,12 @@ YY_DECL
        register int yy_act;
     
 /* %% [7.0] user's declarations go here */
-#line 67 "scripts/genksyms/lex.l"
+#line 63 "scripts/genksyms/lex.l"
 
 
 
  /* Keep track of our location in the original source files.  */
-#line 927 "scripts/genksyms/lex.c"
+#line 918 "scripts/genksyms/lex.c"
 
        if ( !(yy_init) )
                {
@@ -987,13 +978,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 76 )
+                               if ( yy_current_state >= 73 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 284 );
+               while ( yy_base[yy_current_state] != 266 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1041,42 +1032,42 @@ do_action:      /* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 71 "scripts/genksyms/lex.l"
+#line 67 "scripts/genksyms/lex.l"
 return FILENAME;
        YY_BREAK
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 72 "scripts/genksyms/lex.l"
+#line 68 "scripts/genksyms/lex.l"
 cur_line++;
        YY_BREAK
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 73 "scripts/genksyms/lex.l"
+#line 69 "scripts/genksyms/lex.l"
 cur_line++;
        YY_BREAK
 /* Ignore all other whitespace.  */
 case 4:
 YY_RULE_SETUP
-#line 76 "scripts/genksyms/lex.l"
+#line 72 "scripts/genksyms/lex.l"
 ;
        YY_BREAK
 case 5:
 /* rule 5 can match eol */
 YY_RULE_SETUP
-#line 79 "scripts/genksyms/lex.l"
+#line 75 "scripts/genksyms/lex.l"
 return STRING;
        YY_BREAK
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 80 "scripts/genksyms/lex.l"
+#line 76 "scripts/genksyms/lex.l"
 return CHAR;
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 81 "scripts/genksyms/lex.l"
+#line 77 "scripts/genksyms/lex.l"
 return IDENT;
        YY_BREAK
 /* The Pedant requires that the other C multi-character tokens be
@@ -1085,38 +1076,37 @@ return IDENT;
     around them properly.  */
 case 8:
 YY_RULE_SETUP
-#line 87 "scripts/genksyms/lex.l"
+#line 83 "scripts/genksyms/lex.l"
 return OTHER;
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 88 "scripts/genksyms/lex.l"
+#line 84 "scripts/genksyms/lex.l"
 return INT;
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 89 "scripts/genksyms/lex.l"
+#line 85 "scripts/genksyms/lex.l"
 return REAL;
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 91 "scripts/genksyms/lex.l"
+#line 87 "scripts/genksyms/lex.l"
 return DOTS;
        YY_BREAK
 /* All other tokens are single characters.  */
 case 12:
 YY_RULE_SETUP
-#line 94 "scripts/genksyms/lex.l"
+#line 90 "scripts/genksyms/lex.l"
 return yytext[0];
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 ECHO;
        YY_BREAK
-#line 1118 "scripts/genksyms/lex.c"
+#line 1109 "scripts/genksyms/lex.c"
 case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(V2_TOKENS):
        yyterminate();
 
        case YY_END_OF_BUFFER:
@@ -1429,7 +1419,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 76 )
+                       if ( yy_current_state >= 73 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1462,11 +1452,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 76 )
+               if ( yy_current_state >= 73 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 75);
+       yy_is_jam = (yy_current_state == 72);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2252,7 +2242,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 
 
 
@@ -2263,12 +2253,23 @@ void yyfree (void * ptr )
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)      do {                                               \
                          cur_node = next_node;                            \
                          next_node = xmalloc(sizeof(*next_node));         \
                          next_node->next = cur_node;                      \
                          cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-                         cur_node->tag = SYM_NORMAL;                      \
+                         cur_node->tag =                                  \
+                           find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+                           SYM_ENUM_CONST : SYM_NORMAL ;                  \
                        } while (0)
 
 #define APP            _APP(yytext, yyleng)
@@ -2294,7 +2295,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -2347,8 +2347,8 @@ repeat:
 
                  case STRUCT_KEYW:
                  case UNION_KEYW:
-                   dont_want_brace_phrase = 3;
                  case ENUM_KEYW:
+                   dont_want_brace_phrase = 3;
                    suppress_type_lookup = 2;
                    goto fini;
 
@@ -2358,8 +2358,7 @@ repeat:
              }
            if (!suppress_type_lookup)
              {
-               struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-               if (sym && sym->type == SYM_TYPEDEF)
+               if (find_symbol(yytext, SYM_TYPEDEF, 1))
                  token = TYPE;
              }
          }
@@ -2478,7 +2477,20 @@ repeat:
          ++count;
          APP;
          goto repeat;
-       case ')': case ']': case '}':
+       case '}':
+         /* is this the last line of an enum declaration? */
+         if (count == 0)
+           {
+             /* Put back the token we just read so's we can find it again
+                after registering the expression.  */
+             unput(token);
+
+             lexstate = ST_NORMAL;
+             token = EXPRESSION_PHRASE;
+             break;
+           }
+         /* FALLTHRU */
+       case ')': case ']':
          --count;
          APP;
          goto repeat;
@@ -2567,143 +2579,4 @@ fini:
 
   return token;
 }
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ASM_KEYW = 258,
-     ATTRIBUTE_KEYW = 259,
-     AUTO_KEYW = 260,
-     BOOL_KEYW = 261,
-     CHAR_KEYW = 262,
-     CONST_KEYW = 263,
-     DOUBLE_KEYW = 264,
-     ENUM_KEYW = 265,
-     EXTERN_KEYW = 266,
-     EXTENSION_KEYW = 267,
-     FLOAT_KEYW = 268,
-     INLINE_KEYW = 269,
-     INT_KEYW = 270,
-     LONG_KEYW = 271,
-     REGISTER_KEYW = 272,
-     RESTRICT_KEYW = 273,
-     SHORT_KEYW = 274,
-     SIGNED_KEYW = 275,
-     STATIC_KEYW = 276,
-     STRUCT_KEYW = 277,
-     TYPEDEF_KEYW = 278,
-     UNION_KEYW = 279,
-     UNSIGNED_KEYW = 280,
-     VOID_KEYW = 281,
-     VOLATILE_KEYW = 282,
-     TYPEOF_KEYW = 283,
-     EXPORT_SYMBOL_KEYW = 284,
-     ASM_PHRASE = 285,
-     ATTRIBUTE_PHRASE = 286,
-     BRACE_PHRASE = 287,
-     BRACKET_PHRASE = 288,
-     EXPRESSION_PHRASE = 289,
-     CHAR = 290,
-     DOTS = 291,
-     IDENT = 292,
-     INT = 293,
-     REAL = 294,
-     STRING = 295,
-     TYPE = 296,
-     OTHER = 297,
-     FILENAME = 298
-   };
-#endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
 
index fe50ff9dacd089d56760c79244c3d4cfacb4c32d..e4ddd493fec3eac20061b1d3701a47c0c36c6ab7 100644 (file)
@@ -55,10 +55,6 @@ CHAR                 L?\'([^\\\']*\\.)*[^\\\']*\'
 
 MC_TOKEN               ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-%s V2_TOKENS
-
 /* We don't do multiple input files.  */
 %option noyywrap
 
@@ -84,9 +80,9 @@ MC_TOKEN              ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
     recognized as tokens.  We don't actually use them since we don't
     parse expressions, but we do want whitespace to be arranged
     around them properly.  */
-<V2_TOKENS>{MC_TOKEN}                  return OTHER;
-<V2_TOKENS>{INT}                       return INT;
-<V2_TOKENS>{REAL}                      return REAL;
+{MC_TOKEN}                             return OTHER;
+{INT}                                  return INT;
+{REAL}                                 return REAL;
 
 "..."                                  return DOTS;
 
@@ -103,12 +99,23 @@ MC_TOKEN           ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)      do {                                               \
                          cur_node = next_node;                            \
                          next_node = xmalloc(sizeof(*next_node));         \
                          next_node->next = cur_node;                      \
                          cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-                         cur_node->tag = SYM_NORMAL;                      \
+                         cur_node->tag =                                  \
+                           find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+                           SYM_ENUM_CONST : SYM_NORMAL ;                  \
                        } while (0)
 
 #define APP            _APP(yytext, yyleng)
@@ -134,7 +141,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -187,8 +193,8 @@ repeat:
 
                  case STRUCT_KEYW:
                  case UNION_KEYW:
-                   dont_want_brace_phrase = 3;
                  case ENUM_KEYW:
+                   dont_want_brace_phrase = 3;
                    suppress_type_lookup = 2;
                    goto fini;
 
@@ -198,8 +204,7 @@ repeat:
              }
            if (!suppress_type_lookup)
              {
-               struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-               if (sym && sym->type == SYM_TYPEDEF)
+               if (find_symbol(yytext, SYM_TYPEDEF, 1))
                  token = TYPE;
              }
          }
@@ -318,7 +323,20 @@ repeat:
          ++count;
          APP;
          goto repeat;
-       case ')': case ']': case '}':
+       case '}':
+         /* is this the last line of an enum declaration? */
+         if (count == 0)
+           {
+             /* Put back the token we just read so's we can find it again
+                after registering the expression.  */
+             unput(token);
+
+             lexstate = ST_NORMAL;
+             token = EXPRESSION_PHRASE;
+             break;
+           }
+         /* FALLTHRU */
+       case ')': case ']':
          --count;
          APP;
          goto repeat;
index 809b949e495b58267a180c31688ffd926e0adb49..1a0b8607fb0e5ff7412626598443bbe6807404a7 100644 (file)
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+   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, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,7 +28,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -47,7 +46,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.1"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 /* Pure parsers.  */
 #define YYPURE 0
 
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 
 
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 24 "scripts/genksyms/parse.y"
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "genksyms.h"
+
+static int is_typedef;
+static int is_extern;
+static char *current_name;
+static struct string_list *decl_spec;
+
+static void yyerror(const char *);
+
+static inline void
+remove_node(struct string_list **p)
+{
+  struct string_list *node = *p;
+  *p = node->next;
+  free_node(node);
+}
+
+static inline void
+remove_list(struct string_list **pb, struct string_list **pe)
+{
+  struct string_list *b = *pb, *e = *pe;
+  *pb = e;
+  free_list(b, e);
+}
+
+
+
+/* Line 189 of yacc.c  */
+#line 106 "scripts/genksyms/parse.c"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
      FILENAME = 298
    };
 #endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 24 "scripts/genksyms/parse.y"
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include "genksyms.h"
-
-static int is_typedef;
-static int is_extern;
-static char *current_name;
-static struct string_list *decl_spec;
-
-static void yyerror(const char *);
-
-static inline void
-remove_node(struct string_list **p)
-{
-  struct string_list *node = *p;
-  *p = node->next;
-  free_node(node);
-}
-
-static inline void
-remove_list(struct string_list **pb, struct string_list **pe)
-{
-  struct string_list *b = *pb, *e = *pe;
-  *pb = e;
-  free_list(b, e);
-}
-
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
 
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
-
 /* Copy the second part of user declarations.  */
 
 
-/* Line 216 of yacc.c.  */
-#line 223 "scripts/genksyms/parse.c"
+/* Line 264 of yacc.c  */
+#line 191 "scripts/genksyms/parse.c"
 
 #ifdef short
 # undef short
@@ -294,14 +262,14 @@ typedef short int yytype_int16;
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int i)
+YYID (int yyi)
 #else
 static int
-YYID (i)
-    int i;
+YYID (yyi)
+    int yyi;
 #endif
 {
-  return i;
+  return yyi;
 }
 #endif
 
@@ -382,9 +350,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -418,12 +386,12 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
     do                                                                 \
       {                                                                        \
        YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
+       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+       Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*yyptr);                          \
       }                                                                        \
@@ -434,16 +402,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   523
+#define YYLAST   532
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  53
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  46
+#define YYNNTS  49
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  126
+#define YYNRULES  132
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  178
+#define YYNSTATES  188
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -504,7 +472,8 @@ static const yytype_uint16 yyprhs[] =
      239,   242,   245,   247,   248,   250,   252,   257,   262,   265,
      269,   273,   277,   278,   280,   283,   287,   291,   292,   294,
      296,   299,   303,   306,   307,   309,   311,   315,   318,   321,
-     323,   326,   327,   330,   333,   334,   336
+     323,   326,   327,   330,   334,   339,   341,   345,   347,   351,
+     354,   355,   357
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -512,16 +481,16 @@ static const yytype_int8 yyrhs[] =
 {
       54,     0,    -1,    55,    -1,    54,    55,    -1,    -1,    56,
       57,    -1,    -1,    12,    23,    58,    60,    -1,    -1,    23,
-      59,    60,    -1,    60,    -1,    84,    -1,    96,    -1,    98,
+      59,    60,    -1,    60,    -1,    84,    -1,    99,    -1,   101,
       -1,     1,    44,    -1,     1,    45,    -1,    64,    61,    44,
       -1,    -1,    62,    -1,    63,    -1,    62,    46,    63,    -1,
-      74,    97,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
+      74,   100,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
       65,    66,    -1,    67,    -1,    68,    -1,     5,    -1,    17,
       -1,    21,    -1,    11,    -1,    14,    -1,    69,    -1,    73,
       -1,    28,    47,    65,    48,    49,    -1,    28,    47,    65,
       49,    -1,    22,    37,    -1,    24,    37,    -1,    10,    37,
       -1,    22,    37,    87,    -1,    24,    37,    87,    -1,    10,
-      37,    32,    -1,    10,    32,    -1,    22,    87,    -1,    24,
+      37,    96,    -1,    10,    96,    -1,    22,    87,    -1,    24,
       87,    -1,     7,    -1,    19,    -1,    15,    -1,    16,    -1,
       20,    -1,    25,    -1,    13,    -1,     9,    -1,    26,    -1,
        6,    -1,    41,    -1,    48,    71,    -1,    -1,    72,    -1,
@@ -543,26 +512,29 @@ static const yytype_int8 yyrhs[] =
       91,    44,    -1,     1,    44,    -1,    -1,    92,    -1,    93,
       -1,    92,    46,    93,    -1,    76,    95,    -1,    37,    94,
       -1,    94,    -1,    52,    34,    -1,    -1,    95,    31,    -1,
-      30,    44,    -1,    -1,    30,    -1,    29,    47,    37,    49,
-      44,    -1
+      51,    97,    45,    -1,    51,    97,    46,    45,    -1,    98,
+      -1,    97,    46,    98,    -1,    37,    -1,    37,    50,    34,
+      -1,    30,    44,    -1,    -1,    30,    -1,    29,    47,    37,
+      49,    44,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   103,   103,   104,   108,   108,   114,   114,   116,   116,
-     118,   119,   120,   121,   122,   123,   127,   141,   142,   146,
-     154,   167,   173,   174,   178,   179,   183,   189,   193,   194,
-     195,   196,   197,   201,   202,   203,   204,   208,   210,   212,
-     216,   223,   230,   239,   240,   241,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   259,   264,   265,
-     269,   270,   274,   274,   274,   275,   283,   284,   288,   297,
-     299,   301,   303,   305,   312,   313,   317,   318,   319,   321,
-     323,   325,   327,   332,   333,   334,   338,   339,   343,   344,
-     349,   354,   356,   360,   361,   369,   373,   375,   377,   379,
-     381,   386,   395,   396,   401,   406,   407,   411,   412,   416,
-     417,   421,   423,   428,   429,   433,   434,   438,   439,   440,
-     444,   448,   449,   453,   457,   458,   462
+       0,   104,   104,   105,   109,   109,   115,   115,   117,   117,
+     119,   120,   121,   122,   123,   124,   128,   142,   143,   147,
+     155,   168,   174,   175,   179,   180,   184,   190,   194,   195,
+     196,   197,   198,   202,   203,   204,   205,   209,   211,   213,
+     217,   224,   231,   241,   244,   245,   249,   250,   251,   252,
+     253,   254,   255,   256,   257,   258,   259,   263,   268,   269,
+     273,   274,   278,   278,   278,   279,   287,   288,   292,   301,
+     303,   305,   307,   309,   316,   317,   321,   322,   323,   325,
+     327,   329,   331,   336,   337,   338,   342,   343,   347,   348,
+     353,   358,   360,   364,   365,   373,   377,   379,   381,   383,
+     385,   390,   399,   400,   405,   410,   411,   415,   416,   420,
+     421,   425,   427,   432,   433,   437,   438,   442,   443,   444,
+     448,   452,   453,   457,   458,   462,   463,   466,   471,   479,
+     483,   484,   488
 };
 #endif
 
@@ -581,8 +553,8 @@ static const char *const yytname[] =
   "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE",
   "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING",
   "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'",
-  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "@1",
-  "declaration1", "@2", "@3", "simple_declaration",
+  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "$@1",
+  "declaration1", "$@2", "$@3", "simple_declaration",
   "init_declarator_list_opt", "init_declarator_list", "init_declarator",
   "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier",
   "storage_class_specifier", "type_specifier", "simple_type_specifier",
@@ -596,7 +568,8 @@ static const char *const yytname[] =
   "member_specification", "member_declaration",
   "member_declarator_list_opt", "member_declarator_list",
   "member_declarator", "member_bitfield_declarator", "attribute_opt",
-  "asm_definition", "asm_phrase_opt", "export_definition", 0
+  "enum_body", "enumerator_list", "enumerator", "asm_definition",
+  "asm_phrase_opt", "export_definition", 0
 };
 #endif
 
@@ -629,7 +602,8 @@ static const yytype_uint8 yyr1[] =
       81,    82,    82,    83,    83,    83,    83,    83,    83,    83,
       83,    84,    85,    85,    86,    87,    87,    88,    88,    89,
       89,    90,    90,    91,    91,    92,    92,    93,    93,    93,
-      94,    95,    95,    96,    97,    97,    98
+      94,    95,    95,    96,    96,    97,    97,    98,    98,    99,
+     100,   100,   101
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -647,7 +621,8 @@ static const yytype_uint8 yyr2[] =
        2,     2,     1,     0,     1,     1,     4,     4,     2,     3,
        3,     3,     0,     1,     2,     3,     3,     0,     1,     1,
        2,     3,     2,     0,     1,     1,     3,     2,     2,     1,
-       2,     0,     2,     2,     0,     1,     5
+       2,     0,     2,     3,     4,     1,     3,     1,     3,     2,
+       0,     1,     5
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -659,17 +634,18 @@ static const yytype_uint8 yydefact[] =
       62,    53,     0,    31,     0,    52,    32,    48,    49,    29,
       65,    47,    50,    30,     0,     8,     0,    51,    54,    63,
        0,     0,     0,    64,    56,     5,    10,    17,    23,    24,
-      26,    27,    33,    34,    11,    12,    13,    14,    15,    43,
-      39,     6,    37,     0,    44,    22,    38,    45,     0,     0,
-     123,    68,     0,    58,     0,    18,    19,     0,   124,    67,
-      25,    42,    22,    40,     0,   113,     0,     0,   109,     9,
-      17,    41,     0,     0,     0,     0,    57,    59,    60,    16,
-       0,    66,   125,   101,   121,    71,     0,     7,   112,   106,
-      76,    77,     0,     0,     0,   121,    75,     0,   114,   115,
-     119,   105,     0,   110,   124,     0,    36,     0,    73,    72,
-      61,    20,   102,     0,    93,     0,    84,    87,    88,   118,
+      26,    27,    33,    34,    11,    12,    13,    14,    15,    39,
+       0,    43,     6,    37,     0,    44,    22,    38,    45,     0,
+       0,   129,    68,     0,    58,     0,    18,    19,     0,   130,
+      67,    25,    42,   127,     0,   125,    22,    40,     0,   113,
+       0,     0,   109,     9,    17,    41,     0,     0,     0,     0,
+      57,    59,    60,    16,     0,    66,   131,   101,   121,    71,
+       0,     0,   123,     0,     7,   112,   106,    76,    77,     0,
+       0,     0,   121,    75,     0,   114,   115,   119,   105,     0,
+     110,   130,     0,    36,     0,    73,    72,    61,    20,   102,
+       0,    93,     0,    84,    87,    88,   128,   124,   126,   118,
        0,    76,     0,   120,    74,   117,    80,     0,   111,     0,
-      35,   126,   122,     0,    21,   103,    70,    94,    56,     0,
+      35,   132,   122,     0,    21,   103,    70,    94,    56,     0,
       93,    90,    92,    69,    83,     0,    82,    81,     0,     0,
      116,   104,     0,    95,     0,    91,    98,     0,    85,    89,
       79,    78,   100,    99,     0,     0,    97,    96
@@ -678,46 +654,47 @@ static const yytype_uint8 yydefact[] =
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     2,     3,    35,    72,    55,    36,    64,    65,
-      66,    75,    38,    39,    40,    41,    42,    67,    86,    87,
-      43,   114,    69,   105,   106,   125,   126,   127,   128,   151,
-     152,    44,   144,   145,    54,    76,    77,    78,   107,   108,
-     109,   110,   122,    45,    94,    46
+      -1,     1,     2,     3,    35,    76,    56,    36,    65,    66,
+      67,    79,    38,    39,    40,    41,    42,    68,    90,    91,
+      43,   121,    70,   112,   113,   132,   133,   134,   135,   161,
+     162,    44,   154,   155,    55,    80,    81,    82,   114,   115,
+     116,   117,   129,    51,    74,    75,    45,    98,    46
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -134
+#define YYPACT_NINF -135
 static const yytype_int16 yypact[] =
 {
-    -134,    16,  -134,   312,  -134,  -134,    20,  -134,  -134,  -134,
-    -134,  -134,   -18,  -134,    -3,  -134,  -134,  -134,  -134,  -134,
-    -134,  -134,  -134,  -134,   -26,  -134,   -25,  -134,  -134,  -134,
-      -7,     5,    27,  -134,  -134,  -134,  -134,    46,   482,  -134,
-    -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,
-      -8,  -134,    30,    97,  -134,   482,    30,  -134,   482,     7,
-    -134,  -134,    12,    10,    42,    55,  -134,    46,   -15,    15,
-    -134,  -134,   482,  -134,    25,    26,    47,   145,  -134,  -134,
-      46,  -134,   356,    39,    71,    77,  -134,    10,  -134,  -134,
-      46,  -134,  -134,  -134,  -134,  -134,   193,  -134,  -134,  -134,
-      75,  -134,     6,    95,    43,  -134,    28,    86,    85,  -134,
-    -134,  -134,    88,  -134,   103,    87,  -134,    91,  -134,  -134,
-    -134,  -134,   -23,    90,   401,    94,   101,   102,  -134,  -134,
-      98,  -134,   108,  -134,  -134,   109,  -134,   230,  -134,    26,
-    -134,  -134,  -134,   134,  -134,  -134,  -134,  -134,  -134,     9,
-      48,  -134,    35,  -134,  -134,   445,  -134,  -134,   125,   126,
-    -134,  -134,   128,  -134,   129,  -134,  -134,   267,  -134,  -134,
-    -134,  -134,  -134,  -134,   130,   131,  -134,  -134
+    -135,    20,  -135,   321,  -135,  -135,    30,  -135,  -135,  -135,
+    -135,  -135,   -28,  -135,     2,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,    -6,  -135,     9,  -135,  -135,  -135,
+      -5,    15,   -17,  -135,  -135,  -135,  -135,    18,   491,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -22,
+      31,  -135,  -135,    19,   106,  -135,   491,    19,  -135,   491,
+      50,  -135,  -135,    11,    -3,    51,    57,  -135,    18,   -14,
+      14,  -135,  -135,    48,    46,  -135,   491,  -135,    33,    32,
+      59,   154,  -135,  -135,    18,  -135,   365,    56,    60,    61,
+    -135,    -3,  -135,  -135,    18,  -135,  -135,  -135,  -135,  -135,
+     202,    74,  -135,   -23,  -135,  -135,  -135,    77,  -135,    16,
+     101,    49,  -135,    34,    92,    93,  -135,  -135,  -135,    94,
+    -135,   110,    95,  -135,    97,  -135,  -135,  -135,  -135,   -20,
+      96,   410,    99,   113,   100,  -135,  -135,  -135,  -135,  -135,
+     103,  -135,   107,  -135,  -135,   111,  -135,   239,  -135,    32,
+    -135,  -135,  -135,   123,  -135,  -135,  -135,  -135,  -135,     3,
+      52,  -135,    38,  -135,  -135,   454,  -135,  -135,   117,   128,
+    -135,  -135,   134,  -135,   135,  -135,  -135,   276,  -135,  -135,
+    -135,  -135,  -135,  -135,   137,   138,  -135,  -135
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -134,  -134,   180,  -134,  -134,  -134,  -134,   -33,  -134,  -134,
-      93,     0,   -58,   -37,  -134,  -134,  -134,   -73,  -134,  -134,
-     -54,   -32,  -134,   -81,  -134,  -133,  -134,  -134,    29,   -50,
-    -134,  -134,  -134,  -134,   -20,  -134,  -134,   110,  -134,  -134,
-      49,    96,    80,  -134,  -134,  -134
+    -135,  -135,   187,  -135,  -135,  -135,  -135,   -50,  -135,  -135,
+      98,     0,   -59,   -37,  -135,  -135,  -135,   -77,  -135,  -135,
+     -54,   -30,  -135,   -90,  -135,  -134,  -135,  -135,    24,   -58,
+    -135,  -135,  -135,  -135,   -18,  -135,  -135,   109,  -135,  -135,
+      44,    87,    84,   148,  -135,   102,  -135,  -135,  -135
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -727,116 +704,118 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -109
 static const yytype_int16 yytable[] =
 {
-      82,    70,   104,    37,   159,    68,    57,   130,   142,    88,
-     162,    52,    56,    84,    49,    92,     4,    93,    10,    50,
-      51,   132,    79,   134,    71,    53,    53,   143,    20,   104,
-      85,   104,    73,   120,   175,    91,    81,    29,   124,    97,
-      58,    33,   -93,   131,    83,    70,   147,   101,    95,    61,
-     163,   150,    59,   102,    63,    80,   149,    63,   -93,    62,
-      63,   136,    96,   100,    47,    48,   104,   101,   166,    98,
-      99,    60,    80,   102,    63,   137,   150,   150,   103,   124,
-     131,    53,   167,    61,   101,   147,    89,    70,   117,   163,
-     102,    63,   111,    62,    63,   149,    63,   124,    74,   164,
-     165,    90,     7,     8,     9,    10,    11,    12,    13,   124,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-     118,    26,    27,    28,    29,    30,   119,   103,    33,   133,
-     138,   139,    98,    92,   -22,   141,   140,   154,    34,   146,
-     142,   -22,  -107,   153,   -22,   -22,   112,   156,   155,   -22,
-       7,     8,     9,    10,    11,    12,    13,   157,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,   161,    26,
-      27,    28,    29,    30,   170,   171,    33,   172,   173,   176,
-     177,     5,   -22,   121,   169,   135,    34,   113,   160,   -22,
-    -108,     0,   -22,   -22,   123,     0,   129,   -22,     7,     8,
-       9,    10,    11,    12,    13,     0,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,     0,    26,    27,    28,
-      29,    30,     0,     0,    33,     0,     0,     0,     0,   -86,
-       0,   158,     0,     0,    34,     7,     8,     9,    10,    11,
-      12,    13,   -86,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
-       0,    33,     0,     0,     0,     0,   -86,     0,   174,     0,
-       0,    34,     7,     8,     9,    10,    11,    12,    13,   -86,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-       0,    26,    27,    28,    29,    30,     0,     0,    33,     0,
-       0,     0,     0,   -86,     0,     0,     0,     0,    34,     0,
-       0,     0,     0,     6,     0,     0,   -86,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,     0,     0,     0,     0,     0,   -22,
-       0,     0,     0,    34,     0,     0,   -22,     0,     0,   -22,
-     -22,     7,     8,     9,    10,    11,    12,    13,     0,    15,
+      86,    71,   111,    37,   172,    10,    83,    69,    58,    49,
+      92,   152,    88,   169,    73,    20,    96,   140,    97,   142,
+       4,   144,   137,    50,    29,    52,   104,    61,    33,    50,
+     153,    53,   111,    89,   111,    77,   -93,   127,    95,    85,
+     157,   131,    59,   185,   173,    54,    57,    99,    62,    71,
+     159,    64,   -93,   141,   160,    62,    84,   108,    63,    64,
+      54,   100,    60,   109,    64,    63,    64,   146,    73,   107,
+      54,   176,   111,   108,    47,    48,    84,   105,   106,   109,
+      64,   147,   160,   160,   110,   177,   141,    87,   131,   157,
+     108,   102,   103,   173,    71,    93,   109,    64,   101,   159,
+      64,   174,   175,    94,   118,   124,   131,    78,   136,   125,
+     126,     7,     8,     9,    10,    11,    12,    13,   131,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,   110,
+      26,    27,    28,    29,    30,   143,   148,    33,   105,   149,
+      96,   151,   152,   -22,   150,   156,   165,    34,   163,   164,
+     -22,  -107,   166,   -22,   -22,   119,   167,   171,   -22,     7,
+       8,     9,    10,    11,    12,    13,   180,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,   181,    26,    27,
+      28,    29,    30,   182,   183,    33,   186,   187,     5,   179,
+     120,   -22,   128,   170,   139,    34,   145,    72,   -22,  -108,
+       0,   -22,   -22,   130,     0,   138,   -22,     7,     8,     9,
+      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
+      30,     0,     0,    33,     0,     0,     0,     0,   -86,     0,
+     168,     0,     0,    34,     7,     8,     9,    10,    11,    12,
+      13,   -86,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,     0,    26,    27,    28,    29,    30,     0,     0,
+      33,     0,     0,     0,     0,   -86,     0,   184,     0,     0,
+      34,     7,     8,     9,    10,    11,    12,    13,   -86,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,     0,
       26,    27,    28,    29,    30,     0,     0,    33,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    34,     0,     0,
-       0,     0,     0,     0,   115,   116,     7,     8,     9,    10,
-      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
-       0,     0,    33,     0,     0,     0,     0,     0,   147,     0,
-       0,     0,   148,     0,     0,     0,     0,     0,   149,    63,
+       0,     0,   -86,     0,     0,     0,     0,    34,     0,     0,
+       0,     0,     6,     0,     0,   -86,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,     0,     0,     0,     0,     0,   -22,     0,
+       0,     0,    34,     0,     0,   -22,     0,     0,   -22,   -22,
        7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
       17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
       27,    28,    29,    30,     0,     0,    33,     0,     0,     0,
-       0,   168,     0,     0,     0,     0,    34,     7,     8,     9,
-      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
-      30,     0,     0,    33,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    34
+       0,     0,     0,     0,     0,     0,    34,     0,     0,     0,
+       0,     0,     0,   122,   123,     7,     8,     9,    10,    11,
+      12,    13,     0,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
+       0,    33,     0,     0,     0,     0,     0,   157,     0,     0,
+       0,   158,     0,     0,     0,     0,     0,   159,    64,     7,
+       8,     9,    10,    11,    12,    13,     0,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,     0,    26,    27,
+      28,    29,    30,     0,     0,    33,     0,     0,     0,     0,
+     178,     0,     0,     0,     0,    34,     7,     8,     9,    10,
+      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
+       0,     0,    33,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    34
 };
 
 static const yytype_int16 yycheck[] =
 {
-      58,    38,    75,     3,   137,    37,    26,     1,    31,    63,
-       1,    37,    37,     1,    32,    30,     0,    32,     8,    37,
-      23,   102,    55,   104,    32,    51,    51,    50,    18,   102,
-      62,   104,    52,    87,   167,    67,    56,    27,    96,    72,
-      47,    31,    33,    37,    37,    82,    37,    41,    33,    37,
-      41,   124,    47,    47,    48,    55,    47,    48,    49,    47,
-      48,    33,    47,    37,    44,    45,   139,    41,    33,    44,
-      45,    44,    72,    47,    48,    47,   149,   150,    52,   137,
-      37,    51,    47,    37,    41,    37,    44,   124,    49,    41,
-      47,    48,    45,    47,    48,    47,    48,   155,     1,   149,
-     150,    46,     5,     6,     7,     8,     9,    10,    11,   167,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      49,    24,    25,    26,    27,    28,    49,    52,    31,    34,
-      44,    46,    44,    30,    37,    44,    49,    36,    41,    49,
-      31,    44,    45,    49,    47,    48,     1,    49,    46,    52,
-       5,     6,     7,     8,     9,    10,    11,    49,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    34,    24,
-      25,    26,    27,    28,    49,    49,    31,    49,    49,    49,
-      49,     1,    37,    90,   155,   105,    41,    77,   139,    44,
-      45,    -1,    47,    48,     1,    -1,   100,    52,     5,     6,
-       7,     8,     9,    10,    11,    -1,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    -1,    24,    25,    26,
-      27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,
-      -1,     1,    -1,    -1,    41,     5,     6,     7,     8,     9,
-      10,    11,    49,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
-      -1,    31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,
-      -1,    41,     5,     6,     7,     8,     9,    10,    11,    49,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      -1,    24,    25,    26,    27,    28,    -1,    -1,    31,    -1,
-      -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,
-      -1,    -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,
-      -1,    -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,
-      48,     5,     6,     7,     8,     9,    10,    11,    -1,    13,
+      59,    38,    79,     3,     1,     8,    56,    37,    26,    37,
+      64,    31,     1,   147,    37,    18,    30,     1,    32,   109,
+       0,   111,    45,    51,    27,    23,    76,    44,    31,    51,
+      50,    37,   109,    63,   111,    53,    33,    91,    68,    57,
+      37,   100,    47,   177,    41,    51,    37,    33,    37,    86,
+      47,    48,    49,    37,   131,    37,    56,    41,    47,    48,
+      51,    47,    47,    47,    48,    47,    48,    33,    37,    37,
+      51,    33,   149,    41,    44,    45,    76,    44,    45,    47,
+      48,    47,   159,   160,    52,    47,    37,    37,   147,    37,
+      41,    45,    46,    41,   131,    44,    47,    48,    50,    47,
+      48,   159,   160,    46,    45,    49,   165,     1,    34,    49,
+      49,     5,     6,     7,     8,     9,    10,    11,   177,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    52,
+      24,    25,    26,    27,    28,    34,    44,    31,    44,    46,
+      30,    44,    31,    37,    49,    49,    46,    41,    49,    36,
+      44,    45,    49,    47,    48,     1,    49,    34,    52,     5,
+       6,     7,     8,     9,    10,    11,    49,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    49,    24,    25,
+      26,    27,    28,    49,    49,    31,    49,    49,     1,   165,
+      81,    37,    94,   149,   107,    41,   112,    49,    44,    45,
+      -1,    47,    48,     1,    -1,   103,    52,     5,     6,     7,
+       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,    -1,
+       1,    -1,    -1,    41,     5,     6,     7,     8,     9,    10,
+      11,    49,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    -1,    24,    25,    26,    27,    28,    -1,    -1,
+      31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,    -1,
+      41,     5,     6,     7,     8,     9,    10,    11,    49,    13,
       14,    15,    16,    17,    18,    19,    20,    21,    22,    -1,
       24,    25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,
-      -1,    -1,    -1,    -1,    48,    49,     5,     6,     7,     8,
-       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
-      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
-      -1,    -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,
+      -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,    -1,
+      -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
+      -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,    48,
        5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
       25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,
-      -1,    36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,
-       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
-      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    41
+      -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,    -1,
+      -1,    -1,    -1,    48,    49,     5,     6,     7,     8,     9,
+      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
+      -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,    -1,
+      -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,     5,
+       6,     7,     8,     9,    10,    11,    -1,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    -1,    24,    25,
+      26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,
+      36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,     8,
+       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
+      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    41
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -847,15 +826,16 @@ static const yytype_uint8 yystos[] =
        8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
       28,    29,    30,    31,    41,    57,    60,    64,    65,    66,
-      67,    68,    69,    73,    84,    96,    98,    44,    45,    32,
-      37,    23,    37,    51,    87,    59,    37,    87,    47,    47,
-      44,    37,    47,    48,    61,    62,    63,    70,    74,    75,
-      66,    32,    58,    87,     1,    64,    88,    89,    90,    60,
-      64,    87,    65,    37,     1,    74,    71,    72,    73,    44,
-      46,    74,    30,    32,    97,    33,    47,    60,    44,    45,
-      37,    41,    47,    52,    70,    76,    77,    91,    92,    93,
-      94,    45,     1,    90,    74,    48,    49,    49,    49,    49,
-      73,    63,    95,     1,    65,    78,    79,    80,    81,    94,
+      67,    68,    69,    73,    84,    99,   101,    44,    45,    37,
+      51,    96,    23,    37,    51,    87,    59,    37,    87,    47,
+      47,    44,    37,    47,    48,    61,    62,    63,    70,    74,
+      75,    66,    96,    37,    97,    98,    58,    87,     1,    64,
+      88,    89,    90,    60,    64,    87,    65,    37,     1,    74,
+      71,    72,    73,    44,    46,    74,    30,    32,   100,    33,
+      47,    50,    45,    46,    60,    44,    45,    37,    41,    47,
+      52,    70,    76,    77,    91,    92,    93,    94,    45,     1,
+      90,    74,    48,    49,    49,    49,    49,    73,    63,    95,
+       1,    65,    78,    79,    80,    81,    34,    45,    98,    94,
        1,    37,    76,    34,    76,    95,    33,    47,    44,    46,
       49,    44,    31,    50,    85,    86,    49,    37,    41,    47,
       70,    82,    83,    49,    36,    46,    49,    49,     1,    78,
@@ -1045,17 +1025,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 #else
 static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -1089,11 +1072,11 @@ yy_reduce_print (yyvsp, yyrule)
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      fprintf (stderr, "   $%d = ", yyi + 1);
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
                                       );
-      fprintf (stderr, "\n");
+      YYFPRINTF (stderr, "\n");
     }
 }
 
@@ -1373,10 +1356,8 @@ yydestruct (yymsg, yytype, yyvaluep)
        break;
     }
 }
-\f
 
 /* Prevent warnings from -Wmissing-prototypes.  */
-
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -1392,11 +1373,10 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-
-/* The look-ahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
-/* The semantic value of the look-ahead symbol.  */
+/* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
@@ -1404,9 +1384,9 @@ int yynerrs;
 
 
 
-/*----------.
-| yyparse.  |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1430,66 +1410,68 @@ yyparse ()
 #endif
 #endif
 {
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
 
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
 
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
 
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
 
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
 
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
 
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
 
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
+    YYSIZE_T yystacksize;
 
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
 
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
+  yychar = YYEMPTY; /* Cause a token to be read.  */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
-
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1519,7 +1501,6 @@ yyparse ()
        YYSTYPE *yyvs1 = yyvs;
        yytype_int16 *yyss1 = yyss;
 
-
        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
@@ -1527,7 +1508,6 @@ yyparse ()
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
-
                    &yystacksize);
 
        yyss = yyss1;
@@ -1550,9 +1530,8 @@ yyparse ()
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
        if (! yyptr)
          goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
+       YYSTACK_RELOCATE (yyss_alloc, yyss);
+       YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
@@ -1563,7 +1542,6 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long int) yystacksize));
 
@@ -1573,6 +1551,9 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1581,16 +1562,16 @@ yyparse ()
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
+     lookahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to look-ahead token.  */
+  /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
     goto yydefault;
 
-  /* Not known => get a look-ahead token if don't already have one.  */
+  /* Not known => get a lookahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1622,20 +1603,16 @@ yybackup:
       goto yyreduce;
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the look-ahead token.  */
+  /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1675,47 +1652,65 @@ yyreduce:
   switch (yyn)
     {
         case 4:
-#line 108 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 109 "scripts/genksyms/parse.y"
     { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
     break;
 
   case 5:
-#line 110 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 111 "scripts/genksyms/parse.y"
     { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;}
     break;
 
   case 6:
-#line 114 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 115 "scripts/genksyms/parse.y"
     { is_typedef = 1; ;}
     break;
 
   case 7:
-#line 115 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 116 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 8:
-#line 116 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 117 "scripts/genksyms/parse.y"
     { is_typedef = 1; ;}
     break;
 
   case 9:
-#line 117 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 118 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 14:
-#line 122 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 123 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 15:
-#line 123 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 124 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 16:
-#line 128 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 129 "scripts/genksyms/parse.y"
     { if (current_name) {
                    struct string_list *decl = (*(yyvsp[(3) - (3)]))->next;
                    (*(yyvsp[(3) - (3)]))->next = NULL;
@@ -1729,12 +1724,16 @@ yyreduce:
     break;
 
   case 17:
-#line 141 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 142 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 19:
-#line 147 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 148 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(1) - (1)]);
                  *(yyvsp[(1) - (1)]) = NULL;
                  add_symbol(current_name,
@@ -1745,7 +1744,9 @@ yyreduce:
     break;
 
   case 20:
-#line 155 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 156 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(3) - (3)]);
                  *(yyvsp[(3) - (3)]) = NULL;
                  free_list(*(yyvsp[(2) - (3)]), NULL);
@@ -1758,27 +1759,37 @@ yyreduce:
     break;
 
   case 21:
-#line 168 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 169 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;}
     break;
 
   case 22:
-#line 173 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 174 "scripts/genksyms/parse.y"
     { decl_spec = NULL; ;}
     break;
 
   case 24:
-#line 178 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 179 "scripts/genksyms/parse.y"
     { decl_spec = *(yyvsp[(1) - (1)]); ;}
     break;
 
   case 25:
-#line 179 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 180 "scripts/genksyms/parse.y"
     { decl_spec = *(yyvsp[(2) - (2)]); ;}
     break;
 
   case 26:
-#line 184 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 185 "scripts/genksyms/parse.y"
     { /* Version 2 checksumming ignores storage class, as that
                     is really irrelevant to the linkage.  */
                  remove_node((yyvsp[(1) - (1)]));
@@ -1787,32 +1798,44 @@ yyreduce:
     break;
 
   case 31:
-#line 196 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 197 "scripts/genksyms/parse.y"
     { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 32:
-#line 197 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 198 "scripts/genksyms/parse.y"
     { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 37:
-#line 209 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 210 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 38:
-#line 211 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 212 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 39:
-#line 213 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 214 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 40:
-#line 217 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 218 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
                  r = copy_node(i); r->tag = SYM_STRUCT;
                  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1822,7 +1845,9 @@ yyreduce:
     break;
 
   case 41:
-#line 224 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 225 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
                  r = copy_node(i); r->tag = SYM_UNION;
                  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1832,7 +1857,9 @@ yyreduce:
     break;
 
   case 42:
-#line 231 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 232 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
                  r = copy_node(i); r->tag = SYM_ENUM;
                  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1842,42 +1869,58 @@ yyreduce:
     break;
 
   case 43:
-#line 239 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
+
+/* Line 1455 of yacc.c  */
+#line 242 "scripts/genksyms/parse.y"
+    { add_symbol(NULL, SYM_ENUM, NULL, 0); (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 44:
-#line 240 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 244 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 45:
-#line 241 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 245 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 56:
-#line 255 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 259 "scripts/genksyms/parse.y"
     { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 57:
-#line 260 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 264 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 58:
-#line 264 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 268 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 61:
-#line 270 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 274 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 65:
-#line 276 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 280 "scripts/genksyms/parse.y"
     { /* restrict has no effect in prototypes so ignore it */
                  remove_node((yyvsp[(1) - (1)]));
                  (yyval) = (yyvsp[(1) - (1)]);
@@ -1885,12 +1928,16 @@ yyreduce:
     break;
 
   case 66:
-#line 283 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 287 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 68:
-#line 289 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 293 "scripts/genksyms/parse.y"
     { if (current_name != NULL) {
                    error_with_pos("unexpected second declaration name");
                    YYERROR;
@@ -1902,97 +1949,135 @@ yyreduce:
     break;
 
   case 69:
-#line 298 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 302 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 70:
-#line 300 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 304 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 71:
-#line 302 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 306 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 72:
-#line 304 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 308 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 73:
-#line 306 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 310 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 74:
-#line 312 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 316 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 78:
-#line 320 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 324 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 79:
-#line 322 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 326 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 80:
-#line 324 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 328 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 81:
-#line 326 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 330 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 82:
-#line 328 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 332 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 83:
-#line 332 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 336 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 85:
-#line 334 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 338 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 86:
-#line 338 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 342 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 89:
-#line 345 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 349 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 90:
-#line 350 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 354 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 91:
-#line 355 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 359 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 93:
-#line 360 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 364 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 94:
-#line 362 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 366 "scripts/genksyms/parse.y"
     { /* For version 2 checksums, we don't want to remember
                     private parameter names.  */
                  remove_node((yyvsp[(1) - (1)]));
@@ -2001,39 +2086,53 @@ yyreduce:
     break;
 
   case 95:
-#line 370 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 374 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (1)]));
                  (yyval) = (yyvsp[(1) - (1)]);
                ;}
     break;
 
   case 96:
-#line 374 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 378 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 97:
-#line 376 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 380 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 98:
-#line 378 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 382 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 99:
-#line 380 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 384 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 100:
-#line 382 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 386 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 101:
-#line 387 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 391 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(2) - (3)]);
                  *(yyvsp[(2) - (3)]) = NULL;
                  add_symbol(current_name, SYM_NORMAL, decl, is_extern);
@@ -2042,93 +2141,163 @@ yyreduce:
     break;
 
   case 102:
-#line 395 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 399 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 104:
-#line 402 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 406 "scripts/genksyms/parse.y"
     { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 105:
-#line 406 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 410 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 106:
-#line 407 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 411 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 107:
-#line 411 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 415 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 110:
-#line 417 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 421 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 111:
-#line 422 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 426 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 112:
-#line 424 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 428 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 113:
-#line 428 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 432 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 116:
-#line 434 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 438 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 117:
-#line 438 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 442 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 118:
-#line 439 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 443 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 120:
-#line 444 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 448 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 121:
-#line 448 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 452 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 123:
-#line 453 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
+
+/* Line 1455 of yacc.c  */
+#line 457 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 124:
-#line 457 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 458 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 127:
+
+/* Line 1455 of yacc.c  */
+#line 467 "scripts/genksyms/parse.y"
+    {
+                       const char *name = strdup((*(yyvsp[(1) - (1)]))->string);
+                       add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+               ;}
+    break;
+
+  case 128:
+
+/* Line 1455 of yacc.c  */
+#line 472 "scripts/genksyms/parse.y"
+    {
+                       const char *name = strdup((*(yyvsp[(1) - (3)]))->string);
+                       struct string_list *expr = copy_list_range(*(yyvsp[(3) - (3)]), *(yyvsp[(2) - (3)]));
+                       add_symbol(name, SYM_ENUM_CONST, expr, 0);
+               ;}
+    break;
+
+  case 129:
+
+/* Line 1455 of yacc.c  */
+#line 479 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 130:
+
+/* Line 1455 of yacc.c  */
+#line 483 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
-  case 126:
-#line 463 "scripts/genksyms/parse.y"
+  case 132:
+
+/* Line 1455 of yacc.c  */
+#line 489 "scripts/genksyms/parse.y"
     { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;}
     break;
 
 
-/* Line 1267 of yacc.c.  */
-#line 2132 "scripts/genksyms/parse.c"
+
+/* Line 1455 of yacc.c  */
+#line 2301 "scripts/genksyms/parse.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2139,7 +2308,6 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
@@ -2204,7 +2372,7 @@ yyerrlab:
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse look-ahead token after an
+      /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -2221,7 +2389,7 @@ yyerrlab:
        }
     }
 
-  /* Else will try to reuse look-ahead token after shifting the error
+  /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -2278,9 +2446,6 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   *++yyvsp = yylval;
 
 
@@ -2305,7 +2470,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2316,7 +2481,7 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
      yydestruct ("Cleanup: discarding lookahead",
                 yytoken, &yylval);
   /* Do not reclaim the symbols of the rule which action triggered
@@ -2342,7 +2507,9 @@ yyreturn:
 }
 
 
-#line 467 "scripts/genksyms/parse.y"
+
+/* Line 1675 of yacc.c  */
+#line 493 "scripts/genksyms/parse.y"
 
 
 static void
index c4eeec652b79958eee113475f7f6b214f23f935f..517523669251b9638ff0e933c7cb9ff9fe97fb00 100644 (file)
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+   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, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
      FILENAME = 298
    };
 #endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
+
index 09a265cd71939cba93839a53ba3b5ebf23574254..ba5c242866c11b4c0803822bd45b940ad16b8474 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 #include "genksyms.h"
 
 static int is_typedef;
@@ -227,16 +228,19 @@ type_specifier:
                  add_symbol(i->string, SYM_UNION, s, is_extern);
                  $$ = $3;
                }
-       | ENUM_KEYW IDENT BRACE_PHRASE
+       | ENUM_KEYW IDENT enum_body
                { struct string_list *s = *$3, *i = *$2, *r;
                  r = copy_node(i); r->tag = SYM_ENUM;
                  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;
                  add_symbol(i->string, SYM_ENUM, s, is_extern);
                  $$ = $3;
                }
-
-       /* Anonymous s/u/e definitions.  Nothing needs doing.  */
-       | ENUM_KEYW BRACE_PHRASE                        { $$ = $2; }
+       /*
+        * Anonymous enum definition. Tell add_symbol() to restart its counter.
+        */
+       | ENUM_KEYW enum_body
+               { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
+       /* Anonymous s/u definitions.  Nothing needs doing.  */
        | STRUCT_KEYW class_body                        { $$ = $2; }
        | UNION_KEYW class_body                         { $$ = $2; }
        ;
@@ -449,6 +453,28 @@ attribute_opt:
        | attribute_opt ATTRIBUTE_PHRASE
        ;
 
+enum_body:
+       '{' enumerator_list '}'                         { $$ = $3; }
+       | '{' enumerator_list ',' '}'                   { $$ = $4; }
+        ;
+
+enumerator_list:
+       enumerator
+       | enumerator_list ',' enumerator
+
+enumerator:
+       IDENT
+               {
+                       const char *name = strdup((*$1)->string);
+                       add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+               }
+       | IDENT '=' EXPRESSION_PHRASE
+               {
+                       const char *name = strdup((*$1)->string);
+                       struct string_list *expr = copy_list_range(*$3, *$2);
+                       add_symbol(name, SYM_ENUM_CONST, expr, 0);
+               }
+
 asm_definition:
        ASM_PHRASE ';'                                  { $$ = $2; }
        ;
index e8fba959fffb4681f397857288c5aab4d159f895..cd104afcc5f27d8dca823ae33edeece2868e28d5 100644 (file)
@@ -1248,6 +1248,19 @@ static int is_function(Elf_Sym *sym)
                return -1;
 }
 
+static void print_section_list(const char * const list[20])
+{
+       const char *const *s = list;
+
+       while (*s) {
+               fprintf(stderr, "%s", *s);
+               s++;
+               if (*s)
+                       fprintf(stderr, ", ");
+       }
+       fprintf(stderr, "\n");
+}
+
 /*
  * Print a warning about a section mismatch.
  * Try to find symbols near it so user can find it.
@@ -1304,7 +1317,6 @@ static void report_sec_mismatch(const char *modname,
                break;
        case DATA_TO_ANY_INIT: {
                prl_to = sec2annotation(tosec);
-               const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
                "the %s %s%s%s\n"
@@ -1312,9 +1324,7 @@ static void report_sec_mismatch(const char *modname,
                "variable with __init* or __refdata (see linux/init.h) "
                "or name the variable:\n",
                fromsym, to, prl_to, tosym, to_p);
-               while (*s)
-                       fprintf(stderr, "%s, ", *s++);
-               fprintf(stderr, "\n");
+               print_section_list(mismatch->symbol_white_list);
                free(prl_to);
                break;
        }
@@ -1329,7 +1339,6 @@ static void report_sec_mismatch(const char *modname,
                break;
        case DATA_TO_ANY_EXIT: {
                prl_to = sec2annotation(tosec);
-               const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
                "the %s %s%s%s\n"
@@ -1337,9 +1346,7 @@ static void report_sec_mismatch(const char *modname,
                "variable with __exit* (see linux/init.h) or "
                "name the variable:\n",
                fromsym, to, prl_to, tosym, to_p);
-               while (*s)
-                       fprintf(stderr, "%s, ", *s++);
-               fprintf(stderr, "\n");
+               print_section_list(mismatch->symbol_white_list);
                free(prl_to);
                break;
        }
index d0b931b994fccebc025c1c281c8cfd1573b7f64b..a834b935f5363d80ab56b15a1acf3cb477f21e42 100644 (file)
@@ -127,7 +127,8 @@ rm -r $(perf-tar);                                                  \
 $(if $(findstring tar-src,$@),,                                     \
 $(if $(findstring bz2,$@),bzip2,                                    \
 $(if $(findstring gz,$@),gzip,                                      \
-$(error unknown target $@)))                                       \
+$(if $(findstring xz,$@),xz,                                        \
+$(error unknown target $@))))                                       \
        -f -9 $(perf-tar).tar)
 
 perf-%pkg: FORCE
@@ -142,7 +143,9 @@ help: FORCE
        @echo '  tar-pkg             - Build the kernel as an uncompressed tarball'
        @echo '  targz-pkg           - Build the kernel as a gzip compressed tarball'
        @echo '  tarbz2-pkg          - Build the kernel as a bzip2 compressed tarball'
+       @echo '  tarxz-pkg           - Build the kernel as a xz compressed tarball'
        @echo '  perf-tar-src-pkg    - Build $(perf-tar).tar source tarball'
        @echo '  perf-targz-src-pkg  - Build $(perf-tar).tar.gz source tarball'
        @echo '  perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
+       @echo '  perf-tarxz-src-pkg  - Build $(perf-tar).tar.xz source tarball'
 
index 51b2aa0acb82db959b67ca1170439c436ae0ab3b..83c9c04102f2bc9fd06d783d31df60eb5e793c5d 100644 (file)
@@ -35,6 +35,10 @@ case "${1}" in
                compress="bzip2 -c9"
                file_ext=".bz2"
                ;;
+       tarxz-pkg)
+               compress="xz -c9"
+               file_ext=".xz"
+               ;;
        *)
                echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2
                exit 1
index ef8729f48586d193d3926d5bd6c4d0b9c34bcb96..4d403844e137a59f53f032bc4972a35e86b2327f 100755 (executable)
@@ -86,12 +86,16 @@ scm_version()
 
        # Check for mercurial and a mercurial repo.
        if test -d .hg && hgid=`hg id 2>/dev/null`; then
-               tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
-
-               # Do we have an untagged version?
-               if [ -z "$tag" -o "$tag" = tip ]; then
-                       id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+               # Do we have an tagged version?  If so, latesttagdistance == 1
+               if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then
+                       id=`hg log -r . --template '{latesttag}'`
                        printf '%s%s' -hg "$id"
+               else
+                       tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+                       if [ -z "$tag" -o "$tag" = tip ]; then
+                               id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+                               printf '%s%s' -hg "$id"
+                       fi
                fi
 
                # Are there uncommitted changes?
index 92fdc4546141125a14410af0b8d4b1ce8464e2fe..bd6185d529cff980e8516429abdc9f3ca2646391 100755 (executable)
@@ -114,6 +114,11 @@ docscope()
        cscope -b -f cscope.out
 }
 
+dogtags()
+{
+       all_sources | gtags -f -
+}
+
 exuberant()
 {
        all_sources | xargs $1 -a                               \
@@ -187,6 +192,10 @@ case "$1" in
                docscope
                ;;
 
+       "gtags")
+               dogtags
+               ;;
+
        "tags")
                rm -f tags
                xtags ctags
index 44d39785e50da4a67bdde65a86e55b6a795e55b3..7493c0ee51cc93e7cc7a7a7a3920a917ab560659 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
+ * Copyright (c) 2002 - 2011 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 /*
+ * unifdef - remove ifdef'ed lines
+ *
  * This code was derived from software contributed to Berkeley by Dave Yost.
  * It was rewritten to support ANSI C by Tony Finch. The original version
  * of unifdef carried the 4-clause BSD copyright licence. None of its code
  * remains in this version (though some of the names remain) so it now
  * carries a more liberal licence.
  *
- * The latest version is available from http://dotat.at/prog/unifdef
- */
-
-static const char * const copyright[] = {
-    "@(#) Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>\n",
-    "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $",
-};
-
-/*
- * unifdef - remove ifdef'ed lines
- *
  *  Wishlist:
  *      provide an option which will append the name of the
  *        appropriate symbol after #else's and #endif's
@@ -48,12 +39,16 @@ static const char * const copyright[] = {
  *        #else's and #endif's to see that they match their
  *        corresponding #ifdef or #ifndef
  *
- *   The first two items above require better buffer handling, which would
- *     also make it possible to handle all "dodgy" directives correctly.
+ *   These require better buffer handling, which would also make
+ *   it possible to handle all "dodgy" directives correctly.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -61,6 +56,12 @@ static const char * const copyright[] = {
 #include <string.h>
 #include <unistd.h>
 
+const char copyright[] =
+    "@(#) $Version: unifdef-2.5 $\n"
+    "@(#) $Author: Tony Finch (dot@dotat.at) $\n"
+    "@(#) $URL: http://dotat.at/prog/unifdef $\n"
+;
+
 /* types of input lines: */
 typedef enum {
        LT_TRUEI,               /* a true #if with ignore flag */
@@ -152,6 +153,11 @@ static char const * const linestate_name[] = {
  */
 #define        EDITSLOP        10
 
+/*
+ * For temporary filenames
+ */
+#define TEMPLATE        "unifdef.XXXXXX"
+
 /*
  * Globals.
  */
@@ -165,6 +171,7 @@ static bool             strictlogic;                /* -K: keep ambiguous #ifs */
 static bool             killconsts;            /* -k: eval constant #ifs */
 static bool             lnnum;                 /* -n: add #line directives */
 static bool             symlist;               /* -s: output symbol list */
+static bool             symdepth;              /* -S: output symbol depth */
 static bool             text;                  /* -t: this is a text file */
 
 static const char      *symname[MAXSYMS];      /* symbol name */
@@ -175,10 +182,18 @@ static int              nsyms;                    /* number of symbols */
 static FILE            *input;                 /* input file pointer */
 static const char      *filename;              /* input file name */
 static int              linenum;               /* current line number */
+static FILE            *output;                        /* output file pointer */
+static const char      *ofilename;             /* output file name */
+static bool             overwriting;           /* output overwrites input */
+static char             tempname[FILENAME_MAX];        /* used when overwriting */
 
 static char             tline[MAXLINE+EDITSLOP];/* input buffer plus space */
 static char            *keyword;               /* used for editing #elif's */
 
+static const char      *newline;               /* input file format */
+static const char       newline_unix[] = "\n";
+static const char       newline_crlf[] = "\r\n";
+
 static Comment_state    incomment;             /* comment parser state */
 static Line_state       linestate;             /* #if line parser state */
 static Ifstate          ifstate[MAXDEPTH];     /* #if processor state */
@@ -189,10 +204,13 @@ static int              delcount;         /* count of deleted lines */
 static unsigned         blankcount;            /* count of blank lines */
 static unsigned         blankmax;              /* maximum recent blankcount */
 static bool             constexpr;             /* constant #if expression */
+static bool             zerosyms = true;       /* to format symdepth output */
+static bool             firstsym;              /* ditto */
 
 static int              exitstat;              /* program exit status */
 
 static void             addsym(bool, bool, char *);
+static void             closeout(void);
 static void             debug(const char *, ...);
 static void             done(void);
 static void             error(const char *);
@@ -212,6 +230,7 @@ static void             state(Ifstate);
 static int              strlcmp(const char *, const char *, size_t);
 static void             unnest(void);
 static void             usage(void);
+static void             version(void);
 
 #define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
@@ -223,7 +242,7 @@ main(int argc, char *argv[])
 {
        int opt;
 
-       while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
+       while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1)
                switch (opt) {
                case 'i': /* treat stuff controlled by these symbols as text */
                        /*
@@ -245,16 +264,15 @@ main(int argc, char *argv[])
                case 'U': /* undef a symbol */
                        addsym(false, false, optarg);
                        break;
-               case 'I':
-                       /* no-op for compatibility with cpp */
-                       break;
-               case 'B': /* compress blank lines around removed section */
-                       compblank = true;
+               case 'I': /* no-op for compatibility with cpp */
                        break;
                case 'b': /* blank deleted lines instead of omitting them */
                case 'l': /* backwards compatibility */
                        lnblank = true;
                        break;
+               case 'B': /* compress blank lines around removed section */
+                       compblank = true;
+                       break;
                case 'c': /* treat -D as -U and vice versa */
                        complement = true;
                        break;
@@ -273,12 +291,20 @@ main(int argc, char *argv[])
                case 'n': /* add #line directive after deleted lines */
                        lnnum = true;
                        break;
+               case 'o': /* output to a file */
+                       ofilename = optarg;
+                       break;
                case 's': /* only output list of symbols that control #ifs */
                        symlist = true;
                        break;
+               case 'S': /* list symbols with their nesting depth */
+                       symlist = symdepth = true;
+                       break;
                case 't': /* don't parse C comments */
                        text = true;
                        break;
+               case 'V': /* print version */
+                       version();
                default:
                        usage();
                }
@@ -290,21 +316,68 @@ main(int argc, char *argv[])
                errx(2, "can only do one file");
        } else if (argc == 1 && strcmp(*argv, "-") != 0) {
                filename = *argv;
-               input = fopen(filename, "r");
+               input = fopen(filename, "rb");
                if (input == NULL)
                        err(2, "can't open %s", filename);
        } else {
                filename = "[stdin]";
                input = stdin;
        }
+       if (ofilename == NULL) {
+               ofilename = "[stdout]";
+               output = stdout;
+       } else {
+               struct stat ist, ost;
+               if (stat(ofilename, &ost) == 0 &&
+                   fstat(fileno(input), &ist) == 0)
+                       overwriting = (ist.st_dev == ost.st_dev
+                                   && ist.st_ino == ost.st_ino);
+               if (overwriting) {
+                       const char *dirsep;
+                       int ofd;
+
+                       dirsep = strrchr(ofilename, '/');
+                       if (dirsep != NULL)
+                               snprintf(tempname, sizeof(tempname),
+                                   "%.*s/" TEMPLATE,
+                                   (int)(dirsep - ofilename), ofilename);
+                       else
+                               snprintf(tempname, sizeof(tempname),
+                                   TEMPLATE);
+                       ofd = mkstemp(tempname);
+                       if (ofd != -1)
+                               output = fdopen(ofd, "wb+");
+                       if (output == NULL)
+                               err(2, "can't create temporary file");
+                       fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+               } else {
+                       output = fopen(ofilename, "wb");
+                       if (output == NULL)
+                               err(2, "can't open %s", ofilename);
+               }
+       }
        process();
        abort(); /* bug */
 }
 
+static void
+version(void)
+{
+       const char *c = copyright;
+       for (;;) {
+               while (*++c != '$')
+                       if (*c == '\0')
+                               exit(0);
+               while (*++c != '$')
+                       putc(*c, stderr);
+               putc('\n', stderr);
+       }
+}
+
 static void
 usage(void)
 {
-       fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]"
+       fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]"
            " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
        exit(2);
 }
@@ -322,7 +395,8 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct.
+ * latter into a #if to keep the nesting correct. We use strncpy() to
+ * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
  * always be kept and the rest of the sequence after the next #elif or
@@ -375,11 +449,11 @@ static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); }
 static void Idrop (void) { Fdrop();  ignoreon(); }
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }
-/* edit this line */
+/* modify this line */
 static void Mpass (void) { strncpy(keyword, "if  ", 4); Pelif(); }
-static void Mtrue (void) { keywordedit("else\n");  state(IS_TRUE_MIDDLE); }
-static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); }
-static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); }
+static void Mtrue (void) { keywordedit("else");  state(IS_TRUE_MIDDLE); }
+static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); }
+static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); }
 
 static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
 /* IS_OUTSIDE */
@@ -431,13 +505,6 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
  * State machine utility functions
  */
 static void
-done(void)
-{
-       if (incomment)
-               error("EOF in comment");
-       exit(exitstat);
-}
-static void
 ignoreoff(void)
 {
        if (depth == 0)
@@ -452,14 +519,8 @@ ignoreon(void)
 static void
 keywordedit(const char *replacement)
 {
-       size_t size = tline + sizeof(tline) - keyword;
-       char *dst = keyword;
-       const char *src = replacement;
-       if (size != 0) {
-               while ((--size != 0) && (*src != '\0'))
-                       *dst++ = *src++;
-               *dst = '\0';
-       }
+       snprintf(keyword, tline + sizeof(tline) - keyword,
+           "%s%s", replacement, newline);
        print();
 }
 static void
@@ -494,24 +555,26 @@ flushline(bool keep)
        if (symlist)
                return;
        if (keep ^ complement) {
-               bool blankline = tline[strspn(tline, " \t\n")] == '\0';
+               bool blankline = tline[strspn(tline, " \t\r\n")] == '\0';
                if (blankline && compblank && blankcount != blankmax) {
                        delcount += 1;
                        blankcount += 1;
                } else {
                        if (lnnum && delcount > 0)
-                               printf("#line %d\n", linenum);
-                       fputs(tline, stdout);
+                               printf("#line %d%s", linenum, newline);
+                       fputs(tline, output);
                        delcount = 0;
                        blankmax = blankcount = blankline ? blankcount + 1 : 0;
                }
        } else {
                if (lnblank)
-                       putc('\n', stdout);
+                       fputs(newline, output);
                exitstat = 1;
                delcount += 1;
                blankcount = 0;
        }
+       if (debugging)
+               fflush(output);
 }
 
 /*
@@ -520,21 +583,54 @@ flushline(bool keep)
 static void
 process(void)
 {
-       Linetype lineval;
-
        /* When compressing blank lines, act as if the file
           is preceded by a large number of blank lines. */
        blankmax = blankcount = 1000;
        for (;;) {
-               linenum++;
-               lineval = parseline();
+               Linetype lineval = parseline();
                trans_table[ifstate[depth]][lineval]();
-               debug("process %s -> %s depth %d",
-                   linetype_name[lineval],
+               debug("process line %d %s -> %s depth %d",
+                   linenum, linetype_name[lineval],
                    ifstate_name[ifstate[depth]], depth);
        }
 }
 
+/*
+ * Flush the output and handle errors.
+ */
+static void
+closeout(void)
+{
+       if (symdepth && !zerosyms)
+               printf("\n");
+       if (fclose(output) == EOF) {
+               warn("couldn't write to %s", ofilename);
+               if (overwriting) {
+                       unlink(tempname);
+                       errx(2, "%s unchanged", filename);
+               } else {
+                       exit(2);
+               }
+       }
+}
+
+/*
+ * Clean up and exit.
+ */
+static void
+done(void)
+{
+       if (incomment)
+               error("EOF in comment");
+       closeout();
+       if (overwriting && rename(tempname, ofilename) == -1) {
+               warn("couldn't rename temporary file");
+               unlink(tempname);
+               errx(2, "%s unchanged", ofilename);
+       }
+       exit(exitstat);
+}
+
 /*
  * Parse a line and determine its type. We keep the preprocessor line
  * parser state between calls in the global variable linestate, with
@@ -549,14 +645,22 @@ parseline(void)
        Linetype retval;
        Comment_state wascomment;
 
+       linenum++;
        if (fgets(tline, MAXLINE, input) == NULL)
                return (LT_EOF);
+       if (newline == NULL) {
+               if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1)
+                       newline = newline_crlf;
+               else
+                       newline = newline_unix;
+       }
        retval = LT_PLAIN;
        wascomment = incomment;
        cp = skipcomment(tline);
        if (linestate == LS_START) {
                if (*cp == '#') {
                        linestate = LS_HASH;
+                       firstsym = true;
                        cp = skipcomment(cp + 1);
                } else if (*cp != '\0')
                        linestate = LS_DIRTY;
@@ -566,7 +670,8 @@ parseline(void)
                cp = skipsym(cp);
                kwlen = cp - keyword;
                /* no way can we deal with a continuation inside a keyword */
-               if (strncmp(cp, "\\\n", 2) == 0)
+               if (strncmp(cp, "\\\r\n", 3) == 0 ||
+                   strncmp(cp, "\\\n", 2) == 0)
                        Eioccc();
                if (strlcmp("ifdef", keyword, kwlen) == 0 ||
                    strlcmp("ifndef", keyword, kwlen) == 0) {
@@ -617,9 +722,8 @@ parseline(void)
                        size_t len = cp - tline;
                        if (fgets(tline + len, MAXLINE - len, input) == NULL) {
                                /* append the missing newline */
-                               tline[len+0] = '\n';
-                               tline[len+1] = '\0';
-                               cp++;
+                               strcpy(tline + len, newline);
+                               cp += strlen(newline);
                                linestate = LS_START;
                        } else {
                                linestate = LS_DIRTY;
@@ -630,7 +734,7 @@ parseline(void)
                while (*cp != '\0')
                        cp = skipcomment(cp + 1);
        }
-       debug("parser %s comment %s line",
+       debug("parser line %d state %s comment %s line", linenum,
            comment_name[incomment], linestate_name[linestate]);
        return (retval);
 }
@@ -875,11 +979,16 @@ skipcomment(const char *cp)
        }
        while (*cp != '\0')
                /* don't reset to LS_START after a line continuation */
-               if (strncmp(cp, "\\\n", 2) == 0)
+               if (strncmp(cp, "\\\r\n", 3) == 0)
+                       cp += 3;
+               else if (strncmp(cp, "\\\n", 2) == 0)
                        cp += 2;
                else switch (incomment) {
                case NO_COMMENT:
-                       if (strncmp(cp, "/\\\n", 3) == 0) {
+                       if (strncmp(cp, "/\\\r\n", 4) == 0) {
+                               incomment = STARTING_COMMENT;
+                               cp += 4;
+                       } else if (strncmp(cp, "/\\\n", 3) == 0) {
                                incomment = STARTING_COMMENT;
                                cp += 3;
                        } else if (strncmp(cp, "/*", 2) == 0) {
@@ -899,7 +1008,7 @@ skipcomment(const char *cp)
                        } else if (strncmp(cp, "\n", 1) == 0) {
                                linestate = LS_START;
                                cp += 1;
-                       } else if (strchr(" \t", *cp) != NULL) {
+                       } else if (strchr(" \r\t", *cp) != NULL) {
                                cp += 1;
                        } else
                                return (cp);
@@ -931,7 +1040,10 @@ skipcomment(const char *cp)
                                cp += 1;
                        continue;
                case C_COMMENT:
-                       if (strncmp(cp, "*\\\n", 3) == 0) {
+                       if (strncmp(cp, "*\\\r\n", 4) == 0) {
+                               incomment = FINISHING_COMMENT;
+                               cp += 4;
+                       } else if (strncmp(cp, "*\\\n", 3) == 0) {
                                incomment = FINISHING_COMMENT;
                                cp += 3;
                        } else if (strncmp(cp, "*/", 2) == 0) {
@@ -1015,7 +1127,13 @@ findsym(const char *str)
        if (cp == str)
                return (-1);
        if (symlist) {
-               printf("%.*s\n", (int)(cp-str), str);
+               if (symdepth && firstsym)
+                       printf("%s%3d", zerosyms ? "" : "\n", depth);
+               firstsym = zerosyms = false;
+               printf("%s%.*s%s",
+                   symdepth ? " " : "",
+                   (int)(cp-str), str,
+                   symdepth ? "" : "\n");
                /* we don't care about the value of the symbol */
                return (0);
        }
@@ -1052,7 +1170,7 @@ addsym(bool ignorethis, bool definethis, char *sym)
                        value[symind] = val+1;
                        *val = '\0';
                } else if (*val == '\0')
-                       value[symind] = "";
+                       value[symind] = "1";
                else
                        usage();
        } else {
@@ -1060,6 +1178,8 @@ addsym(bool ignorethis, bool definethis, char *sym)
                        usage();
                value[symind] = NULL;
        }
+       debug("addsym %s=%s", symname[symind],
+           value[symind] ? value[symind] : "undef");
 }
 
 /*
@@ -1100,5 +1220,6 @@ error(const char *msg)
        else
                warnx("%s: %d: %s (#if line %d depth %d)",
                    filename, linenum, msg, stifline[depth], depth);
+       closeout();
        errx(2, "output may be truncated");
 }
index ba7c63af6f3b2bc8a53a91de50ff9ad669468fb8..8ce792ea08e9f782d3e661dbbb99798839a08ed4 100755 (executable)
@@ -37,6 +37,8 @@ $default{"POWEROFF_ON_SUCCESS"}       = 0;
 $default{"BUILD_OPTIONS"}      = "";
 $default{"BISECT_SLEEP_TIME"}  = 60;   # sleep time between bisects
 $default{"CLEAR_LOG"}          = 0;
+$default{"BISECT_MANUAL"}      = 0;
+$default{"BISECT_SKIP"}                = 1;
 $default{"SUCCESS_LINE"}       = "login:";
 $default{"BOOTED_TIMEOUT"}     = 1;
 $default{"DIE_ON_FAILURE"}     = 1;
@@ -45,6 +47,7 @@ $default{"SCP_TO_TARGET"}     = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
 $default{"REBOOT"}             = "ssh \$SSH_USER\@\$MACHINE reboot";
 $default{"STOP_AFTER_SUCCESS"} = 10;
 $default{"STOP_AFTER_FAILURE"} = 60;
+$default{"STOP_TEST_AFTER"}    = 600;
 $default{"LOCALVERSION"}       = "-test";
 
 my $ktest_config;
@@ -81,6 +84,8 @@ my $addconfig;
 my $in_bisect = 0;
 my $bisect_bad = "";
 my $reverse_bisect;
+my $bisect_manual;
+my $bisect_skip;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
@@ -98,6 +103,7 @@ my $console;
 my $success_line;
 my $stop_after_success;
 my $stop_after_failure;
+my $stop_test_after;
 my $build_target;
 my $target_image;
 my $localversion;
@@ -462,6 +468,10 @@ sub dodie {
        `$power_off`;
     }
 
+    if (defined($opt{"LOG_FILE"})) {
+       print " See $opt{LOG_FILE} for more info.\n";
+    }
+
     die @_, "\n";
 }
 
@@ -760,8 +770,10 @@ sub monitor {
 
     my $success_start;
     my $failure_start;
+    my $monitor_start = time;
+    my $done = 0;
 
-    for (;;) {
+    while (!$done) {
 
        if ($booted) {
            $line = wait_for_input($monitor_fp, $booted_timeout);
@@ -796,7 +808,7 @@ sub monitor {
        }
 
        if ($full_line =~ /call trace:/i) {
-           if (!$skip_call_trace) {
+           if (!$bug && !$skip_call_trace) {
                $bug = 1;
                $failure_start = time;
            }
@@ -816,12 +828,19 @@ sub monitor {
        }
 
        if ($full_line =~ /Kernel panic -/) {
+           $failure_start = time;
            $bug = 1;
        }
 
        if ($line =~ /\n/) {
            $full_line = "";
        }
+
+       if ($stop_test_after > 0 && !$booted && !$bug) {
+           if (time - $monitor_start > $stop_test_after) {
+               $done = 1;
+           }
+       }
     }
 
     close(DMESG);
@@ -925,6 +944,18 @@ sub check_buildlog {
     return 1;
 }
 
+sub make_oldconfig {
+    my ($defconfig) = @_;
+
+    if (!run_command "$defconfig $make oldnoconfig") {
+       # Perhaps oldnoconfig doesn't exist in this version of the kernel
+       # try a yes '' | oldconfig
+       doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
+       run_command "yes '' | $defconfig $make oldconfig" or
+           dodie "failed make config oldconfig";
+    }
+}
+
 sub build {
     my ($type) = @_;
     my $defconfig = "";
@@ -970,8 +1001,12 @@ sub build {
        $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
     }
 
-    run_command "$defconfig $make $type" or
-       dodie "failed make config";
+    if ($type eq "oldnoconfig") {
+       make_oldconfig $defconfig;
+    } else {
+       run_command "$defconfig $make $type" or
+           dodie "failed make config";
+    }
 
     $redirect = "$buildlog";
     if (!run_command "$make $build_options") {
@@ -1025,6 +1060,21 @@ sub get_version {
     doprint "$version\n";
 }
 
+sub answer_bisect {
+    for (;;) {
+       doprint "Pass or fail? [p/f]";
+       my $ans = <STDIN>;
+       chomp $ans;
+       if ($ans eq "p" || $ans eq "P") {
+           return 1;
+       } elsif ($ans eq "f" || $ans eq "F") {
+           return 0;
+       } else {
+           print "Please answer 'P' or 'F'\n";
+       }
+    }
+}
+
 sub child_run_test {
     my $failed = 0;
 
@@ -1070,6 +1120,7 @@ sub do_run_test {
 
            # we are not guaranteed to get a full line
            $full_line .= $line;
+           doprint $line;
 
            if ($full_line =~ /call trace:/i) {
                $bug = 1;
@@ -1086,6 +1137,19 @@ sub do_run_test {
     } while (!$child_done && !$bug);
 
     if ($bug) {
+       my $failure_start = time;
+       my $now;
+       do {
+           $line = wait_for_input($monitor_fp, 1);
+           if (defined($line)) {
+               doprint $line;
+           }
+           $now = time;
+           if ($now - $failure_start >= $stop_after_failure) {
+               last;
+           }
+       } while (defined($line));
+
        doprint "Detected kernel crash!\n";
        # kill the child with extreme prejudice
        kill 9, $child_pid;
@@ -1131,7 +1195,15 @@ sub run_git_bisect {
     return 1;
 }
 
-# returns 1 on success, 0 on failure
+sub bisect_reboot {
+    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
+    reboot;
+    start_monitor;
+    wait_for_monitor $bisect_sleep_time;
+    end_monitor;
+}
+
+# returns 1 on success, 0 on failure, -1 on skip
 sub run_bisect_test {
     my ($type, $buildtype) = @_;
 
@@ -1145,6 +1217,10 @@ sub run_bisect_test {
     build $buildtype or $failed = 1;
 
     if ($type ne "build") {
+       if ($failed && $bisect_skip) {
+           $in_bisect = 0;
+           return -1;
+       }
        dodie "Failed on build" if $failed;
 
        # Now boot the box
@@ -1156,6 +1232,12 @@ sub run_bisect_test {
        monitor or $failed = 1;
 
        if ($type ne "boot") {
+           if ($failed && $bisect_skip) {
+               end_monitor;
+               bisect_reboot;
+               $in_bisect = 0;
+               return -1;
+           }
            dodie "Failed on boot" if $failed;
 
            do_run_test or $failed = 1;
@@ -1168,11 +1250,7 @@ sub run_bisect_test {
 
        # reboot the box to a good kernel
        if ($type ne "build") {
-           doprint "Reboot and sleep $bisect_sleep_time seconds\n";
-           reboot;
-           start_monitor;
-           wait_for_monitor $bisect_sleep_time;
-           end_monitor;
+           bisect_reboot;
        }
     } else {
        $result = 1;
@@ -1193,16 +1271,22 @@ sub run_bisect {
 
     my $ret = run_bisect_test $type, $buildtype;
 
+    if ($bisect_manual) {
+       $ret = answer_bisect;
+    }
 
     # Are we looking for where it worked, not failed?
     if ($reverse_bisect) {
        $ret = !$ret;
     }
 
-    if ($ret) {
+    if ($ret > 0) {
        return "good";
-    } else {
+    } elsif ($ret == 0) {
        return  "bad";
+    } elsif ($bisect_skip) {
+       doprint "HIT A BAD COMMIT ... SKIPPING\n";
+       return "skip";
     }
 }
 
@@ -1220,6 +1304,13 @@ sub bisect {
     my $type = $opt{"BISECT_TYPE[$i]"};
     my $start = $opt{"BISECT_START[$i]"};
     my $replay = $opt{"BISECT_REPLAY[$i]"};
+    my $start_files = $opt{"BISECT_FILES[$i]"};
+
+    if (defined($start_files)) {
+       $start_files = " -- " . $start_files;
+    } else {
+       $start_files = "";
+    }
 
     # convert to true sha1's
     $good = get_sha1($good);
@@ -1273,7 +1364,7 @@ sub bisect {
            die "Failed to checkout $head";
     }
 
-    run_command "git bisect start" or
+    run_command "git bisect start$start_files" or
        dodie "could not start bisect";
 
     run_command "git bisect good $good" or
@@ -1390,9 +1481,7 @@ sub create_config {
     close(OUT);
 
 #    exit;
-    run_command "$make oldnoconfig" or
-       dodie "failed make config oldconfig";
-
+    make_oldconfig "";
 }
 
 sub compare_configs {
@@ -1505,7 +1594,9 @@ sub run_config_bisect {
        }
 
        $ret = run_config_bisect_test $type;
-
+       if ($bisect_manual) {
+           $ret = answer_bisect;
+       }
        if ($ret) {
            process_passed %current_config;
            return 0;
@@ -1536,7 +1627,13 @@ sub run_config_bisect {
        $half = int($#start_list / 2);
     } while ($half > 0);
 
-    # we found a single config, try it again
+    # we found a single config, try it again unless we are running manually
+
+    if ($bisect_manual) {
+       process_failed $start_list[0];
+       return 1;
+    }
+
     my @tophalf = @start_list[0 .. 0];
 
     $ret = run_config_bisect_test $type;
@@ -1594,8 +1691,7 @@ sub config_bisect {
     close(IN);
 
     # Now run oldconfig with the minconfig (and addconfigs)
-    run_command "$defconfig $make oldnoconfig" or
-       dodie "failed make config oldconfig";
+    make_oldconfig $defconfig;
 
     # check to see what we lost (or gained)
     open (IN, $output_config)
@@ -1907,6 +2003,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
     $sleep_time = set_test_option("SLEEP_TIME", $i);
     $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
+    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
+    $bisect_skip = set_test_option("BISECT_SKIP", $i);
     $store_failures = set_test_option("STORE_FAILURES", $i);
     $timeout = set_test_option("TIMEOUT", $i);
     $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
@@ -1914,6 +2012,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $success_line = set_test_option("SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
+    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
     $build_target = set_test_option("BUILD_TARGET", $i);
     $ssh_exec = set_test_option("SSH_EXEC", $i);
     $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
index 3408c594b2deceaf5d58cd526a154362c427b6f2..4c5d6bd74a0207b50d8a74ff204270afdb60601a 100644 (file)
 # (default 60)
 #STOP_AFTER_FAILURE = 60
 
+# In case the console constantly fills the screen, having
+# a specified time to stop the test if it never succeeds nor fails
+# is recommended.
+# Note: this is ignored if a success or failure is detected.
+# (in seconds)
+# (default 600, -1 is to never stop)
+#STOP_TEST_AFTER = 600
+
 # Stop testing if a build fails. If set, the script will end if
 # a failure is detected, otherwise it will save off the .config,
 # dmesg and bootlog in a directory called
 #   git bisect good, git bisect bad, and running the git bisect replay
 #   if the BISECT_REPLAY is set.
 #
+# BISECT_SKIP = 1 (optional, default 0)
+#
+#   If BISECT_TYPE is set to test but the build fails, ktest will
+#   simply fail the test and end their. You could use BISECT_REPLAY
+#   and BISECT_START to resume after you found a new starting point,
+#   or you could set BISECT_SKIP to 1. If BISECT_SKIP is set to 1,
+#   when something other than the BISECT_TYPE fails, ktest.pl will
+#   run "git bisect skip" and try again.
+#
+# BISECT_FILES = <path> (optional, default undefined)
+#
+#   To just run the git bisect on a specific path, set BISECT_FILES.
+#   For example:
+#
+#     BISECT_FILES = arch/x86 kernel/time
+#
+#   Will run the bisect with "git bisect start -- arch/x86 kernel/time"
+#
 # BISECT_REVERSE = 1 (optional, default 0)
 #
 #   In those strange instances where it was broken forever
 #   With BISECT_REVERSE = 1, The test will consider failures as
 #   good, and success as bad.
 #
+# BISECT_MANUAL = 1 (optional, default 0)
+#
+#   In case there's a problem with automating the bisect for
+#   whatever reason. (Can't reboot, want to inspect each iteration)
+#   Doing a BISECT_MANUAL will have the test wait for you to
+#   tell it if the test passed or failed after each iteration.
+#   This is basicall the same as running git bisect yourself
+#   but ktest will rebuild and install the kernel for you.
+#
 # BISECT_CHECK = 1 (optional, default 0)
 #
 #   Just to be sure the good is good and bad is bad, setting
 #
 #   CONFIG_BISECT is the config that failed to boot
 #
+#   If BISECT_MANUAL is set, it will pause between iterations.
+#   This is useful to use just ktest.pl just for the config bisect.
+#   If you set it to build, it will run the bisect and you can
+#   control what happens in between iterations. It will ask you if
+#   the test succeeded or not and continue the config bisect.
+#
 # Example:
 #   TEST_START
 #   TEST_TYPE = config_bisect
 #   CONFIG_BISECT_TYPE = build
 #   CONFIG_BISECT = /home/test/Ā¢onfig-bad
 #   MIN_CONFIG = /home/test/config-min
+#   BISECT_MANUAL = 1
 #