]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Jan 2009 01:02:07 +0000 (17:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Jan 2009 01:02:07 +0000 (17:02 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (60 commits)
  uio: make uio_info's name and version const
  UIO: Documentation for UIO ioport info handling
  UIO: Pass information about ioports to userspace (V2)
  UIO: uio_pdrv_genirq: allow custom irq_flags
  UIO: use pci_ioremap_bar() in drivers/uio
  arm: struct device - replace bus_id with dev_name(), dev_set_name()
  libata: struct device - replace bus_id with dev_name(), dev_set_name()
  avr: struct device - replace bus_id with dev_name(), dev_set_name()
  block: struct device - replace bus_id with dev_name(), dev_set_name()
  chris: struct device - replace bus_id with dev_name(), dev_set_name()
  dmi: struct device - replace bus_id with dev_name(), dev_set_name()
  gadget: struct device - replace bus_id with dev_name(), dev_set_name()
  gpio: struct device - replace bus_id with dev_name(), dev_set_name()
  gpu: struct device - replace bus_id with dev_name(), dev_set_name()
  hwmon: struct device - replace bus_id with dev_name(), dev_set_name()
  i2o: struct device - replace bus_id with dev_name(), dev_set_name()
  IA64: struct device - replace bus_id with dev_name(), dev_set_name()
  i7300_idle: struct device - replace bus_id with dev_name(), dev_set_name()
  infiniband: struct device - replace bus_id with dev_name(), dev_set_name()
  ISDN: struct device - replace bus_id with dev_name(), dev_set_name()
  ...

361 files changed:
.mailmap
Documentation/ABI/testing/sysfs-devices-memory
Documentation/DMA-mapping.txt
Documentation/filesystems/Locking
Documentation/filesystems/proc.txt
Documentation/hwmon/adt7470
Documentation/ide/warm-plug-howto.txt
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/kernel-parameters.txt
Documentation/kprobes.txt
Documentation/magic-number.txt
Documentation/memory-hotplug.txt
Documentation/mips/AU1xxx_IDE.README
Documentation/powerpc/cpu_features.txt
Documentation/s390/Debugging390.txt
Documentation/s390/cds.txt
Documentation/s390/s390dbf.txt
Documentation/sysctl/vm.txt
Documentation/vm/unevictable-lru.txt
Documentation/x86/zero-page.txt
MAINTAINERS
arch/alpha/include/asm/atomic.h
arch/arm/include/asm/atomic.h
arch/arm/kernel/kprobes.c
arch/arm/mach-s3c2410/include/mach/spi.h
arch/avr32/include/asm/atomic.h
arch/avr32/kernel/traps.c
arch/blackfin/include/asm/atomic.h
arch/cris/include/asm/atomic.h
arch/h8300/include/asm/atomic.h
arch/ia64/include/asm/atomic.h
arch/ia64/kernel/kprobes.c
arch/ia64/mm/init.c
arch/m68knommu/include/asm/atomic.h
arch/mips/include/asm/atomic.h
arch/parisc/include/asm/atomic.h
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/kernel/kprobes.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mem.c
arch/s390/include/asm/atomic.h
arch/s390/kernel/kprobes.c
arch/s390/mm/init.c
arch/sh/include/asm/atomic.h
arch/sh/kernel/traps_32.c
arch/sh/mm/init.c
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/atomic_64.h
arch/um/kernel/trap.c
arch/x86/include/asm/atomic_32.h
arch/x86/include/asm/atomic_64.h
arch/x86/include/asm/unwind.h [deleted file]
arch/x86/kernel/kprobes.c
arch/x86/kernel/traps.c
arch/x86/mm/fault.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
drivers/acpi/processor_idle.c
drivers/base/memory.c
drivers/base/node.c
drivers/char/Kconfig
drivers/char/consolemap.c
drivers/char/mem.c
drivers/char/random.c
drivers/char/sysrq.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/edac_device.c
drivers/edac/edac_mc.c
drivers/edac/edac_pci.c
drivers/edac/edac_pci_sysfs.c
drivers/edac/i5400_edac.c [new file with mode: 0644]
drivers/edac/i82875p_edac.c
drivers/edac/mpc85xx_edac.c
drivers/firmware/dmi_scan.c
drivers/gpio/Kconfig
drivers/gpio/pca953x.c
drivers/gpio/twl4030-gpio.c
drivers/gpu/drm/drm_fops.c
drivers/hwmon/adt7462.c
drivers/hwmon/adt7470.c
drivers/hwmon/adt7473.c
drivers/hwmon/applesmc.c
drivers/hwmon/ibmpex.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/aec62xx.c
drivers/ide/alim15x3.c
drivers/ide/amd74xx.c
drivers/ide/au1xxx-ide.c
drivers/ide/cmd640.c
drivers/ide/cmd64x.c
drivers/ide/cs5520.c
drivers/ide/cy82c693.c
drivers/ide/falconide.c
drivers/ide/hpt366.c
drivers/ide/icside.c
drivers/ide/ide-acpi.c
drivers/ide/ide-atapi.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-disk.c
drivers/ide/ide-dma-sff.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-gd.c
drivers/ide/ide-gd.h
drivers/ide/ide-h8300.c
drivers/ide/ide-io.c
drivers/ide/ide-iops.c
drivers/ide/ide-lib.c
drivers/ide/ide-park.c
drivers/ide/ide-pm.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/it8172.c [new file with mode: 0644]
drivers/ide/it8213.c
drivers/ide/it821x.c
drivers/ide/ns87415.c
drivers/ide/palm_bk3710.c
drivers/ide/pdc202xx_new.c
drivers/ide/pdc202xx_old.c
drivers/ide/piix.c
drivers/ide/pmac.c
drivers/ide/q40ide.c
drivers/ide/qd65xx.c
drivers/ide/qd65xx.h
drivers/ide/sc1200.c
drivers/ide/scc_pata.c
drivers/ide/serverworks.c
drivers/ide/setup-pci.c
drivers/ide/sgiioc4.c
drivers/ide/siimage.c
drivers/ide/sis5513.c
drivers/ide/sl82c105.c
drivers/ide/slc90e66.c
drivers/ide/tc86c001.c
drivers/ide/triflex.c
drivers/ide/trm290.c
drivers/ide/tx4939ide.c
drivers/ide/umc8672.c
drivers/ide/via82cxxx.c
drivers/macintosh/therm_adt746x.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/video/v4l1-compat.c
drivers/message/i2o/device.c
drivers/message/i2o/driver.c
drivers/misc/ibmasm/module.c
drivers/misc/ioc4.c
drivers/misc/tifm_7xx1.c
drivers/parport/ieee1284.c
drivers/rapidio/rio-driver.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-at32ap700x.c
drivers/rtc/rtc-au1xxx.c [new file with mode: 0644]
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1216.c
drivers/rtc/rtc-ds1390.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds3234.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-max6902.c
drivers/rtc/rtc-mv.c [new file with mode: 0644]
drivers/rtc/rtc-pxa.c [new file with mode: 0644]
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-stk17ta8.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-twl4030.c
drivers/rtc/rtc-tx4939.c [new file with mode: 0644]
drivers/rtc/rtc-vr41xx.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/atmel_spi.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi_gpio.c [new file with mode: 0644]
drivers/spi/spi_s3c24xx.c
drivers/video/aty/aty128fb.c
drivers/video/bfin-t350mcqb-fb.c
drivers/video/carminefb.c
drivers/video/cyber2000fb.c
drivers/video/fbmem.c
drivers/video/gbefb.c
drivers/video/geode/gx1fb_core.c
drivers/video/geode/gxfb_core.c
drivers/video/geode/lxfb_core.c
drivers/video/gxt4500.c
drivers/video/i810/i810_accel.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/modedb.c
drivers/video/neofb.c
drivers/video/nvidia/nv_accel.c
drivers/video/pm3fb.c
drivers/video/sm501fb.c
drivers/video/via/viafbdev.c
firmware/dsp56k/bootstrap.asm
fs/Kconfig
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/inode.c
fs/autofs4/waitq.c
fs/bfs/inode.c
fs/binfmt_misc.c
fs/block_dev.c
fs/buffer.c
fs/char_dev.c
fs/compat.c
fs/direct-io.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/ecryptfs/miscdev.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/fs-writeback.c
fs/fuse/control.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/minix/dir.c
fs/mpage.c
fs/ncpfs/getopt.c
fs/proc/task_mmu.c
fs/select.c
fs/sync.c
fs/ubifs/super.c
include/asm-frv/atomic.h
include/asm-generic/bug.h
include/asm-generic/local.h
include/asm-generic/memory_model.h
include/asm-m32r/atomic.h
include/asm-m68k/atomic.h
include/asm-mn10300/atomic.h
include/asm-xtensa/atomic.h
include/linux/auto_dev-ioctl.h
include/linux/auto_fs4.h
include/linux/binfmts.h
include/linux/cgroup.h
include/linux/cpuset.h
include/linux/fs.h
include/linux/fuse.h
include/linux/gfp.h
include/linux/hugetlb.h
include/linux/i2c/twl4030.h
include/linux/ide.h
include/linux/interrupt.h
include/linux/kernel.h
include/linux/kprobes.h
include/linux/memory.h
include/linux/memory_hotplug.h
include/linux/migrate.h
include/linux/miscdevice.h
include/linux/mm.h
include/linux/module.h
include/linux/node.h
include/linux/page-flags.h
include/linux/pagevec.h
include/linux/pci_ids.h
include/linux/percpu_counter.h
include/linux/poll.h
include/linux/rio_drv.h
include/linux/rmap.h
include/linux/sched.h
include/linux/spi/spi_gpio.h [new file with mode: 0644]
include/linux/swap.h
include/linux/types.h
include/linux/unwind.h [deleted file]
include/linux/vmalloc.h
include/linux/writeback.h
init/Kconfig
init/do_mounts.c
init/do_mounts_md.c
init/main.c
ipc/ipc_sysctl.c
ipc/sem.c
ipc/shm.c
kernel/cgroup.c
kernel/compat.c
kernel/cpuset.c
kernel/dma-coherent.c
kernel/exit.c
kernel/fork.c
kernel/kmod.c
kernel/kprobes.c
kernel/module.c
kernel/panic.c
kernel/profile.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/test_kprobes.c
kernel/time.c
kernel/tsacct.c
lib/bust_spinlocks.c
lib/fault-inject.c
lib/percpu_counter.c
lib/prio_heap.c
lib/proportions.c
lib/radix-tree.c
lib/vsprintf.c
mm/Kconfig
mm/Makefile
mm/backing-dev.c
mm/bootmem.c
mm/filemap.c
mm/filemap_xip.c
mm/fremap.c
mm/hugetlb.c
mm/internal.h
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mlock.c
mm/mmap.c
mm/mprotect.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_cgroup.c
mm/page_io.c
mm/rmap.c
mm/shmem.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/tiny-shmem.c [deleted file]
mm/vmalloc.c
mm/vmscan.c
samples/firmware_class/firmware_sample_driver.c
samples/kobject/kobject-example.c
samples/kobject/kset-example.c
samples/markers/marker-example.c
samples/tracepoints/tracepoint-probe-sample.c
samples/tracepoints/tracepoint-probe-sample2.c
samples/tracepoints/tracepoint-sample.c
scripts/checkpatch.pl
scripts/markup_oops.pl [new file with mode: 0644]
sound/core/sound.c

index 97f7b4fb61398e2b0d4e3e6c2fc030f383849b39..4e83e7b52d15d2baf27f7f671483756c0c71c572 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -32,6 +32,7 @@ Christoph Hellwig <hch@lst.de>
 Corey Minyard <minyard@acm.org>
 David Brownell <david-b@pacbell.net>
 David Woodhouse <dwmw2@shinybook.infradead.org>
+Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
index 7a16fe1e2270d8e7353b209bd0dad24a5ce9b69e..9fe91c02ee40e4fb4bca0b1e7fb010f14d5554e3 100644 (file)
@@ -6,7 +6,6 @@ Description:
                internal state of the kernel memory blocks. Files could be
                added or removed dynamically to represent hot-add/remove
                operations.
-
 Users:         hotplug memory add/remove tools
                https://w3.opensource.ibm.com/projects/powerpc-utils/
 
@@ -19,6 +18,56 @@ Description:
                This is useful for a user-level agent to determine
                identify removable sections of the memory before attempting
                potentially expensive hot-remove memory operation
+Users:         hotplug memory remove tools
+               https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What:          /sys/devices/system/memory/memoryX/phys_device
+Date:          September 2008
+Contact:       Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+               The file /sys/devices/system/memory/memoryX/phys_device
+               is read-only and is designed to show the name of physical
+               memory device.  Implementation is currently incomplete.
 
+What:          /sys/devices/system/memory/memoryX/phys_index
+Date:          September 2008
+Contact:       Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+               The file /sys/devices/system/memory/memoryX/phys_index
+               is read-only and contains the section ID in hexadecimal
+               which is equivalent to decimal X contained in the
+               memory section directory name.
+
+What:          /sys/devices/system/memory/memoryX/state
+Date:          September 2008
+Contact:       Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+               The file /sys/devices/system/memory/memoryX/state
+               is read-write.  When read, it's contents show the
+               online/offline state of the memory section.  When written,
+               root can toggle the the online/offline state of a removable
+               memory section (see removable file description above)
+               using the following commands.
+               # echo online > /sys/devices/system/memory/memoryX/state
+               # echo offline > /sys/devices/system/memory/memoryX/state
+
+               For example, if /sys/devices/system/memory/memory22/removable
+               contains a value of 1 and
+               /sys/devices/system/memory/memory22/state contains the
+               string "online" the following command can be executed by
+               by root to offline that section.
+               # echo offline > /sys/devices/system/memory/memory22/state
 Users:         hotplug memory remove tools
                https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What:          /sys/devices/system/node/nodeX/memoryY
+Date:          September 2008
+Contact:       Gary Hade <garyhade@us.ibm.com>
+Description:
+               When CONFIG_NUMA is enabled
+               /sys/devices/system/node/nodeX/memoryY is a symbolic link that
+               points to the corresponding /sys/devices/system/memory/memoryY
+               memory section directory.  For example, the following symbolic
+               link is created for memory section 9 on node0.
+               /sys/devices/system/node/node0/memory9 -> ../../memory/memory9
+
index c74fec8c2351168d1329c527183f3a975234030e..b2a4d6d244d932cf7cd72d3034fba0ba2c853dff 100644 (file)
@@ -26,7 +26,7 @@ mapped only for the time they are actually used and unmapped after the DMA
 transfer.
 
 The following API will work of course even on platforms where no such
-hardware exists, see e.g. include/asm-i386/pci.h for how it is implemented on
+hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
 top of the virt_to_bus interface.
 
 First of all, you should make sure
index ccec55394380393ccf69a0272078ebd5465ceae3..cfbfa15a46ba6af6d642b8439f31ebf3abd46503 100644 (file)
@@ -397,7 +397,7 @@ prototypes:
 };
 
 locking rules:
-       All except ->poll() may block.
+       All may block.
                        BKL
 llseek:                        no      (see below)
 read:                  no
index 71df353e367c9e8c3f2833fe7114c875a6d49d3b..32e94635484f968c40291264d6e5b7df14d813ae 100644 (file)
@@ -1385,6 +1385,15 @@ swapcache reclaim.  Decreasing vfs_cache_pressure causes the kernel to prefer
 to retain dentry and inode caches.  Increasing vfs_cache_pressure beyond 100
 causes the kernel to prefer to reclaim dentries and inodes.
 
+dirty_background_bytes
+----------------------
+
+Contains the amount of dirty memory at which the pdflush background writeback
+daemon will start writeback.
+
+If dirty_background_bytes is written, dirty_background_ratio becomes a function
+of its value (dirty_background_bytes / the amount of dirtyable system memory).
+
 dirty_background_ratio
 ----------------------
 
@@ -1393,14 +1402,29 @@ pages + file cache, not including locked pages and HugePages), the number of
 pages at which the pdflush background writeback daemon will start writing out
 dirty data.
 
+If dirty_background_ratio is written, dirty_background_bytes becomes a function
+of its value (dirty_background_ratio * the amount of dirtyable system memory).
+
+dirty_bytes
+-----------
+
+Contains the amount of dirty memory at which a process generating disk writes
+will itself start writeback.
+
+If dirty_bytes is written, dirty_ratio becomes a function of its value
+(dirty_bytes / the amount of dirtyable system memory).
+
 dirty_ratio
------------------
+-----------
 
 Contains, as a percentage of the dirtyable system memory (free pages + mapped
 pages + file cache, not including locked pages and HugePages), the number of
 pages at which a process which is generating disk writes will itself start
 writing out dirty data.
 
+If dirty_ratio is written, dirty_bytes becomes a function of its value
+(dirty_ratio * the amount of dirtyable system memory).
+
 dirty_writeback_centisecs
 -------------------------
 
index 75d13ca147ccbe7234a85d4bf40ac715d3fa9c4d..8ce4aa0a0f5500cc5a6fbecc67644d4e1600dcf7 100644 (file)
@@ -31,15 +31,11 @@ Each of the measured inputs (temperature, fan speed) has corresponding high/low
 limit values. The ADT7470 will signal an ALARM if any measured value exceeds
 either limit.
 
-The ADT7470 DOES NOT sample all inputs continuously.  A single pin on the
-ADT7470 is connected to a multitude of thermal diodes, but the chip must be
-instructed explicitly to read the multitude of diodes.  If you want to use
-automatic fan control mode, you must manually read any of the temperature
-sensors or the fan control algorithm will not run.  The chip WILL NOT DO THIS
-AUTOMATICALLY; this must be done from userspace.  This may be a bug in the chip
-design, given that many other AD chips take care of this.  The driver will not
-read the registers more often than once every 5 seconds.  Further,
-configuration data is only read once per minute.
+The ADT7470 samples all inputs continuously.  A kernel thread is started up for
+the purpose of periodically querying the temperature sensors, thus allowing the
+automatic fan pwm control to set the fan speed.  The driver will not read the
+registers more often than once every 5 seconds.  Further, configuration data is
+only read once per minute.
 
 Special Features
 ----------------
@@ -72,5 +68,6 @@ pwm#_auto_point2_temp.
 Notes
 -----
 
-As stated above, the temperature inputs must be read periodically from
-userspace in order for the automatic pwm algorithm to run.
+The temperature inputs no longer need to be read periodically from userspace in
+order for the automatic pwm algorithm to run.  This was the case for earlier
+versions of the driver.
index d5885468b07261b283e3e65db5511ef2cf0c2c7c..98152bcd515aba70cba16d8815a61fb9c275dce9 100644 (file)
@@ -11,3 +11,8 @@ unplug old device(s) and plug new device(s)
 # echo -n "1" > /sys/class/ide_port/idex/scan
 
 done
+
+NOTE: please make sure that partitions are unmounted and that there are
+no other active references to devices before doing "delete_devices" step,
+also do not attempt "scan" step on devices currently in use -- otherwise
+results may be unpredictable and lead to data loss if you're unlucky
index 824699174436d9a49912873196e27f0d2a51c49a..f1d639903325ca697cd23f6e34e7074aba05daed 100644 (file)
@@ -84,7 +84,7 @@ Code  Seq#    Include File            Comments
 'B'    C0-FF                           advanced bbus
                                        <mailto:maassen@uni-freiburg.de>
 'C'    all     linux/soundcard.h
-'D'    all     asm-s390/dasd.h
+'D'    all     arch/s390/include/asm/dasd.h
 'E'    all     linux/input.h
 'F'    all     linux/fb.h
 'H'    all     linux/hiddev.h
@@ -105,7 +105,7 @@ Code        Seq#    Include File            Comments
 'S'    80-81   scsi/scsi_ioctl.h       conflict!
 'S'    82-FF   scsi/scsi.h             conflict!
 'T'    all     linux/soundcard.h       conflict!
-'T'    all     asm-i386/ioctls.h       conflict!
+'T'    all     arch/x86/include/asm/ioctls.h   conflict!
 'U'    00-EF   linux/drivers/usb/usb.h
 'V'    all     linux/vt.h
 'W'    00-1F   linux/watchdog.h        conflict!
@@ -120,7 +120,7 @@ Code        Seq#    Include File            Comments
                                        <mailto:natalia@nikhefk.nikhef.nl>
 'c'    00-7F   linux/comstats.h        conflict!
 'c'    00-7F   linux/coda.h            conflict!
-'c'    80-9F   asm-s390/chsc.h
+'c'    80-9F   arch/s390/include/asm/chsc.h
 'd'    00-FF   linux/char/drm/drm/h    conflict!
 'd'    00-DF   linux/video_decoder.h   conflict!
 'd'    F0-FF   linux/digi1.h
@@ -170,7 +170,7 @@ Code        Seq#    Include File            Comments
                                        <mailto:oe@port.de>
 0x80   00-1F   linux/fb.h
 0x81   00-1F   linux/videotext.h
-0x89   00-06   asm-i386/sockios.h
+0x89   00-06   arch/x86/include/asm/sockios.h
 0x89   0B-DF   linux/sockios.h
 0x89   E0-EF   linux/sockios.h         SIOCPROTOPRIVATE range
 0x89   F0-FF   linux/sockios.h         SIOCDEVPRIVATE range
index c6841eee9598ddd82932db9e4e4a451f9f33ad9d..d73fbd2b2b4503e4fb36325fe1ed2337eda6325f 100644 (file)
@@ -71,6 +71,11 @@ The @argument descriptions must begin on the very next line following
 this opening short function description line, with no intervening
 empty comment lines.
 
+If a function parameter is "..." (varargs), it should be listed in
+kernel-doc notation as:
+ * @...: description
+
+
 Example kernel-doc data structure comment.
 
 /**
@@ -282,6 +287,32 @@ struct my_struct {
 };
 
 
+Including documentation blocks in source files
+----------------------------------------------
+
+To facilitate having source code and comments close together, you can
+include kernel-doc documentation blocks that are free-form comments
+instead of being kernel-doc for functions, structures, unions,
+enums, or typedefs.  This could be used for something like a
+theory of operation for a driver or library code, for example.
+
+This is done by using a DOC: section keyword with a section title.  E.g.:
+
+/**
+ * DOC: Theory of Operation
+ *
+ * The whizbang foobar is a dilly of a gizmo.  It can do whatever you
+ * want it to do, at any time.  It reads your mind.  Here's how it works.
+ *
+ * foo bar splat
+ *
+ * The only drawback to this gizmo is that is can sometimes damage
+ * hardware, software, or its subject(s).
+ */
+
+DOC: sections are used in SGML templates files as indicated below.
+
+
 How to make new SGML template files
 -----------------------------------
 
@@ -302,6 +333,9 @@ exported using EXPORT_SYMBOL.
 !F<filename> <function [functions...]> is replaced by the
 documentation, in <filename>, for the functions listed.
 
+!P<filename> <section title> is replaced by the contents of the DOC:
+section titled <section title> from <filename>.
+Spaces are allowed in <section title>; do not quote the <section title>.
 
 Tim.
 */ <twaugh@redhat.com>
index a2d8805c03d5588f317a9677add758c94051e6a6..0b3f6711d2f1a5a084ddab87e3ce27b5efae72fb 100644 (file)
@@ -469,8 +469,8 @@ and is between 256 and 4096 characters. It is defined in the file
 
        clearcpuid=BITNUM [X86]
                        Disable CPUID feature X for the kernel. See
-                       include/asm-x86/cpufeature.h for the valid bit numbers.
-                       Note the Linux specific bits are not necessarily
+                       arch/x86/include/asm/cpufeature.h for the valid bit
+                       numbers. Note the Linux specific bits are not necessarily
                        stable over kernel options, but the vendor specific
                        ones should be.
                        Also note that user programs calling CPUID directly
@@ -551,6 +551,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        not work reliably with all consoles, but is known
                        to work with serial and VGA consoles.
 
+       coredump_filter=
+                       [KNL] Change the default value for
+                       /proc/<pid>/coredump_filter.
+                       See also Documentation/filesystems/proc.txt.
+
        cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
                        Format:
                        <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -1117,6 +1122,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
+       lmb=debug       [KNL] Enable lmb debug messages.
+
        load_ramdisk=   [RAM] List of ramdisks to load from floppy
                        See Documentation/blockdev/ramdisk.txt.
 
@@ -1569,6 +1576,10 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nr_uarts=       [SERIAL] maximum number of UARTs to be registered.
 
+       ohci1394_dma=early      [HW] enable debugging via the ohci1394 driver.
+                       See Documentation/debugging-via-ohci1394.txt for more
+                       info.
+
        olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
                        Rather than timing out after 20 ms if an EC
                        command is not properly ACKed, override the length
@@ -1793,10 +1804,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        autoconfiguration.
                        Ranges are in pairs (memory base and size).
 
-       dynamic_printk
-                       Enables pr_debug()/dev_dbg() calls if
-                       CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
-                       be switched on/off via <debugfs>/dynamic_printk/modules
+       dynamic_printk  Enables pr_debug()/dev_dbg() calls if
+                       CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
+                       These can also be switched on/off via
+                       <debugfs>/dynamic_printk/modules
 
        print-fatal-signals=
                        [KNL] debug: print fatal signals
@@ -1884,7 +1895,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        reboot=         [BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
                        Format: <reboot_mode>[,<reboot_mode2>[,...]]
-                       See arch/*/kernel/reboot.c or arch/*/kernel/process.c                   
+                       See arch/*/kernel/reboot.c or arch/*/kernel/process.c
 
        relax_domain_level=
                        [KNL, SMP] Set scheduler's default relax_domain_level.
@@ -2432,8 +2443,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format:
                        <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
 
-       norandmaps      Don't use address space randomization
-                       Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
+       norandmaps      Don't use address space randomization.  Equivalent to
+                       echo 0 > /proc/sys/kernel/randomize_va_space
 
 ______________________________________________________________________
 
index a79633d702bff23230bb0d76cb68565e078b4fb2..48b3de90eb1eb03ceb1929e4228ae3a57debc526 100644 (file)
@@ -497,7 +497,10 @@ The first column provides the kernel address where the probe is inserted.
 The second column identifies the type of probe (k - kprobe, r - kretprobe
 and j - jprobe), while the third column specifies the symbol+offset of
 the probe. If the probed function belongs to a module, the module name
-is also specified.
+is also specified. Following columns show probe status. If the probe is on
+a virtual address that is no longer valid (module init sections, module
+virtual addresses that correspond to modules that've been unloaded),
+such probes are marked with [GONE].
 
 /debug/kprobes/enabled: Turn kprobes ON/OFF
 
index 95070028d15eeae7e0bfb13993932eb40e2b84b1..505f19607542d5a328aebb1b06a331abbd967744 100644 (file)
@@ -125,14 +125,14 @@ TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
 ROUTER_MAGIC          0x524d4157  wan_device        include/linux/wanrouter.h
 SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
 SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
-GDA_MAGIC             0x58464552  gda               include/asm-mips64/sn/gda.h
+GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
 RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
 STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
 EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
 EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
-KV_MAGIC              0x5f4b565f  kernel_vars_s     include/asm-mips64/sn/klkernvars.h
+KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
 I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
 TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
 M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
@@ -158,7 +158,7 @@ CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
 QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
 QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
 HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
-NMI_MAGIC             0x48414d4d455201 nmi_s        include/asm-mips64/sn/nmi.h
+NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
 
 Note that there are also defined special per-driver magic numbers in sound
 memory management. See include/sound/sndmagic.h for complete list of them. Many
index 168117bd6ee8b8d7eafbb72c626a2434556f4cc9..4c2ecf537a4ad5d1edf47d5c5295416650364bd3 100644 (file)
@@ -124,7 +124,7 @@ config options.
     This option can be kernel module too.
 
 --------------------------------
-3 sysfs files for memory hotplug
+4 sysfs files for memory hotplug
 --------------------------------
 All sections have their device information under /sys/devices/system/memory as
 
@@ -138,11 +138,12 @@ For example, assume 1GiB section size. A device for a memory starting at
 (0x100000000 / 1Gib = 4)
 This device covers address range [0x100000000 ... 0x140000000)
 
-Under each section, you can see 3 files.
+Under each section, you can see 4 files.
 
 /sys/devices/system/memory/memoryXXX/phys_index
 /sys/devices/system/memory/memoryXXX/phys_device
 /sys/devices/system/memory/memoryXXX/state
+/sys/devices/system/memory/memoryXXX/removable
 
 'phys_index' : read-only and contains section id, same as XXX.
 'state'      : read-write
@@ -150,10 +151,20 @@ Under each section, you can see 3 files.
                at write: user can specify "online", "offline" command
 'phys_device': read-only: designed to show the name of physical memory device.
                This is not well implemented now.
+'removable'  : read-only: contains an integer value indicating
+               whether the memory section is removable or not
+               removable.  A value of 1 indicates that the memory
+               section is removable and a value of 0 indicates that
+               it is not removable.
 
 NOTE:
   These directories/files appear after physical memory hotplug phase.
 
+If CONFIG_NUMA is enabled the
+/sys/devices/system/memory/memoryXXX memory section
+directories can also be accessed via symbolic links located in
+the /sys/devices/system/node/node* directories.  For example:
+/sys/devices/system/node/node0/memory9 -> ../../memory/memory9
 
 --------------------------------
 4. Physical memory hot-add phase
@@ -365,7 +376,6 @@ node if necessary.
   - allowing memory hot-add to ZONE_MOVABLE. maybe we need some switch like
     sysctl or new control file.
   - showing memory section and physical device relationship.
-  - showing memory section and node relationship (maybe good for NUMA)
   - showing memory section is under ZONE_MOVABLE or not
   - test and make it better memory offlining.
   - support HugeTLB page migration and offlining.
index 25a6ed1aaa5b1e3e7aa2e774a7beab34f78001f9..f54962aea84dd571ef0f2f25adb1381b9ce69335 100644 (file)
@@ -44,7 +44,7 @@ FILES, CONFIGS AND COMPATABILITY
 
 Two files are introduced:
 
-  a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+  a) 'arch/mips/include/asm/mach-au1x00/au1xxx_ide.h'
      containes : struct _auide_hwif
                  timing parameters for PIO mode 0/1/2/3/4
                  timing parameters for MWDMA 0/1/2
index 472739880e87a9c527fb8fed2df591b2669a4c81..ffa4183fdb8b97f66dfd2fb0d8ba8bfa4a98995b 100644 (file)
@@ -31,7 +31,7 @@ anyways).
 
 After detecting the processor type, the kernel patches out sections of code
 that shouldn't be used by writing nop's over it. Using cpufeatures requires
-just 2 macros (found in include/asm-ppc/cputable.h), as seen in head.S
+just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
 transfer_to_handler:
 
        #ifdef CONFIG_ALTIVEC
index d30a281c570f025c35234fd52f2a899e29bc0ec2..10711d9f078860513959b4cbf7dfa7d71e21a409 100644 (file)
@@ -1402,7 +1402,7 @@ Syscalls are implemented on Linux for S390 by the Supervisor call instruction (S
 possibilities of these as the instruction is made up of a  0xA opcode & the second byte being
 the syscall number. They are traced using the simple command.
 TR SVC  <Optional value or range>
-the syscalls are defined in linux/include/asm-s390/unistd.h
+the syscalls are defined in linux/arch/s390/include/asm/unistd.h
 e.g. to trace all file opens just do
 TR SVC 5 ( as this is the syscall number of open )
 
index c4b7b2bd369ae74949cfd1182346dbc1d12427d6..480a78ef5a1e4240ced3abf810465c00a937f235 100644 (file)
@@ -98,7 +98,7 @@ platform. Some of the interface routines are specific to Linux/390 and some
 of them can be found on other Linux platforms implementations too.
 Miscellaneous function prototypes, data declarations, and macro definitions
 can be found in the architecture specific C header file
-linux/include/asm-s390/irq.h.
+linux/arch/s390/include/asm/irq.h.
 
 Overview of CDS interface concepts
 
index e05420973698a41002d77123c3aa9db8ecebc52d..2d10053dd97ea69ca314305f25b57bafaeab9e6c 100644 (file)
@@ -2,7 +2,7 @@ S390 Debug Feature
 ==================
 
 files: arch/s390/kernel/debug.c
-       include/asm-s390/debug.h
+       arch/s390/include/asm/debug.h
 
 Description:
 ------------
index d79eeda7a699cbeb72ad0a03332388f8d8a68eeb..cd05994a49e69795db29f75675180371e1fe3ae4 100644 (file)
@@ -41,7 +41,8 @@ Currently, these files are in /proc/sys/vm:
 
 ==============================================================
 
-dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
+dirty_bytes, dirty_ratio, dirty_background_bytes,
+dirty_background_ratio, dirty_expire_centisecs,
 dirty_writeback_centisecs, highmem_is_dirtyable,
 vfs_cache_pressure, laptop_mode, block_dump, swap_token_timeout,
 drop-caches, hugepages_treat_as_movable:
index 125eed560e5a1bfb25d08ee7ad903d3efd8faef4..0706a7282a8ca6ce26b39fd7d7d7c930d6891c94 100644 (file)
@@ -137,13 +137,6 @@ shrink_page_list() where they will be detected when vmscan walks the reverse
 map in try_to_unmap().  If try_to_unmap() returns SWAP_MLOCK, shrink_page_list()
 will cull the page at that point.
 
-Note that for anonymous pages, shrink_page_list() attempts to add the page to
-the swap cache before it tries to unmap the page.  To avoid this unnecessary
-consumption of swap space, shrink_page_list() calls try_to_munlock() to check
-whether any VM_LOCKED vmas map the page without attempting to unmap the page.
-If try_to_munlock() returns SWAP_MLOCK, shrink_page_list() will cull the page
-without consuming swap space.  try_to_munlock() will be described below.
-
 To "cull" an unevictable page, vmscan simply puts the page back on the lru
 list using putback_lru_page()--the inverse operation to isolate_lru_page()--
 after dropping the page lock.  Because the condition which makes the page
@@ -190,8 +183,8 @@ several places:
    in the VM_LOCKED flag being set for the vma.
 3) in the fault path, if mlocked pages are "culled" in the fault path,
    and when a VM_LOCKED stack segment is expanded.
-4) as mentioned above, in vmscan:shrink_page_list() with attempting to
-   reclaim a page in a VM_LOCKED vma--via try_to_unmap() or try_to_munlock().
+4) as mentioned above, in vmscan:shrink_page_list() when attempting to
+   reclaim a page in a VM_LOCKED vma via try_to_unmap().
 
 Mlocked pages become unlocked and rescued from the unevictable list when:
 
@@ -260,9 +253,9 @@ mlock_fixup() filters several classes of "special" vmas:
 
 2) vmas mapping hugetlbfs page are already effectively pinned into memory.
    We don't need nor want to mlock() these pages.  However, to preserve the
-   prior behavior of mlock()--before the unevictable/mlock changes--mlock_fixup()
-   will call make_pages_present() in the hugetlbfs vma range to allocate the
-   huge pages and populate the ptes.
+   prior behavior of mlock()--before the unevictable/mlock changes--
+   mlock_fixup() will call make_pages_present() in the hugetlbfs vma range
+   to allocate the huge pages and populate the ptes.
 
 3) vmas with VM_DONTEXPAND|VM_RESERVED are generally user space mappings of
    kernel pages, such as the vdso page, relay channel pages, etc.  These pages
@@ -322,7 +315,7 @@ __mlock_vma_pages_range()--the same function used to mlock a vma range--
 passing a flag to indicate that munlock() is being performed.
 
 Because the vma access protections could have been changed to PROT_NONE after
-faulting in and mlocking some pages, get_user_pages() was unreliable for visiting
+faulting in and mlocking pages, get_user_pages() was unreliable for visiting
 these pages for munlocking.  Because we don't want to leave pages mlocked(),
 get_user_pages() was enhanced to accept a flag to ignore the permissions when
 fetching the pages--all of which should be resident as a result of previous
@@ -416,8 +409,8 @@ Mlocked Pages:  munmap()/exit()/exec() System Call Handling
 When unmapping an mlocked region of memory, whether by an explicit call to
 munmap() or via an internal unmap from exit() or exec() processing, we must
 munlock the pages if we're removing the last VM_LOCKED vma that maps the pages.
-Before the unevictable/mlock changes, mlocking did not mark the pages in any way,
-so unmapping them required no processing.
+Before the unevictable/mlock changes, mlocking did not mark the pages in any
+way, so unmapping them required no processing.
 
 To munlock a range of memory under the unevictable/mlock infrastructure, the
 munmap() hander and task address space tear down function call
@@ -517,12 +510,10 @@ couldn't be mlocked.
 Mlocked pages:  try_to_munlock() Reverse Map Scan
 
 TODO/FIXME:  a better name might be page_mlocked()--analogous to the
-page_referenced() reverse map walker--especially if we continue to call this
-from shrink_page_list().  See related TODO/FIXME below.
+page_referenced() reverse map walker.
 
-When munlock_vma_page()--see "Mlocked Pages:  munlock()/munlockall() System
-Call Handling" above--tries to munlock a page, or when shrink_page_list()
-encounters an anonymous page that is not yet in the swap cache, they need to
+When munlock_vma_page()--see "Mlocked Pages:  munlock()/munlockall()
+System Call Handling" above--tries to munlock a page, it needs to
 determine whether or not the page is mapped by any VM_LOCKED vma, without
 actually attempting to unmap all ptes from the page.  For this purpose, the
 unevictable/mlock infrastructure introduced a variant of try_to_unmap() called
@@ -535,10 +526,7 @@ for VM_LOCKED vmas.  When such a vma is found for anonymous pages and file
 pages mapped in linear VMAs, as in the try_to_unmap() case, the functions
 attempt to acquire the associated mmap semphore, mlock the page via
 mlock_vma_page() and return SWAP_MLOCK.  This effectively undoes the
-pre-clearing of the page's PG_mlocked done by munlock_vma_page() and informs
-shrink_page_list() that the anonymous page should be culled rather than added
-to the swap cache in preparation for a try_to_unmap() that will almost
-certainly fail.
+pre-clearing of the page's PG_mlocked done by munlock_vma_page.
 
 If try_to_unmap() is unable to acquire a VM_LOCKED vma's associated mmap
 semaphore, it will return SWAP_AGAIN.  This will allow shrink_page_list()
@@ -557,10 +545,7 @@ However, the scan can terminate when it encounters a VM_LOCKED vma and can
 successfully acquire the vma's mmap semphore for read and mlock the page.
 Although try_to_munlock() can be called many [very many!] times when
 munlock()ing a large region or tearing down a large address space that has been
-mlocked via mlockall(), overall this is a fairly rare event.  In addition,
-although shrink_page_list() calls try_to_munlock() for every anonymous page that
-it handles that is not yet in the swap cache, on average anonymous pages will
-have very short reverse map lists.
+mlocked via mlockall(), overall this is a fairly rare event.
 
 Mlocked Page:  Page Reclaim in shrink_*_list()
 
@@ -588,8 +573,8 @@ Some examples of these unevictable pages on the LRU lists are:
    munlock_vma_page() was forced to let the page back on to the normal
    LRU list for vmscan to handle.
 
-shrink_inactive_list() also culls any unevictable pages that it finds
-on the inactive lists, again diverting them to the appropriate zone's unevictable
+shrink_inactive_list() also culls any unevictable pages that it finds on
+the inactive lists, again diverting them to the appropriate zone's unevictable
 lru list.  shrink_inactive_list() should only see SHM_LOCKed pages that became
 SHM_LOCKed after shrink_active_list() had moved them to the inactive list, or
 pages mapped into VM_LOCKED vmas that munlock_vma_page() couldn't isolate from
@@ -597,19 +582,7 @@ the lru to recheck via try_to_munlock().  shrink_inactive_list() won't notice
 the latter, but will pass on to shrink_page_list().
 
 shrink_page_list() again culls obviously unevictable pages that it could
-encounter for similar reason to shrink_inactive_list().  As already discussed,
-shrink_page_list() proactively looks for anonymous pages that should have
-PG_mlocked set but don't--these would not be detected by page_evictable()--to
-avoid adding them to the swap cache unnecessarily.  File pages mapped into
+encounter for similar reason to shrink_inactive_list().  Pages mapped into
 VM_LOCKED vmas but without PG_mlocked set will make it all the way to
-try_to_unmap().  shrink_page_list() will divert them to the unevictable list when
-try_to_unmap() returns SWAP_MLOCK, as discussed above.
-
-TODO/FIXME:  If we can enhance the swap cache to reliably remove entries
-with page_count(page) > 2, as long as all ptes are mapped to the page and
-not the swap entry, we can probably remove the call to try_to_munlock() in
-shrink_page_list() and just remove the page from the swap cache when
-try_to_unmap() returns SWAP_MLOCK.   Currently, remove_exclusive_swap_page()
-doesn't seem to allow that.
-
-
+try_to_unmap().  shrink_page_list() will divert them to the unevictable list
+when try_to_unmap() returns SWAP_MLOCK, as discussed above.
index 169ad423a3d12243023d5807d1d7a4025d1a3978..4f913857b8a26bae558c5b0f30a6bba0799fcbf9 100644 (file)
@@ -3,7 +3,7 @@ protocol of kernel. These should be filled by bootloader or 16-bit
 real-mode setup code of the kernel. References/settings to it mainly
 are in:
 
-  include/asm-x86/bootparam.h
+  arch/x86/include/asm/bootparam.h
 
 
 Offset Proto   Name            Meaning
index 141aff67bd6df3eae4545637cadeaffd7d0d368b..094dd52d73093f4f96679315b0c172f368ff1780 100644 (file)
@@ -616,7 +616,7 @@ M:  mkpetch@internode.on.net
 S:     Maintained
 
 ARM/TOSA MACHINE SUPPORT
-P:     Dmitry Baryshkov
+P:     Dmitry Eremin-Solenikov
 M:     dbaryshkov@gmail.com
 P:     Dirk Opfer
 M:     dirk@opfer-online.de
@@ -1092,11 +1092,8 @@ S:       Maintained
 
 CHECKPATCH
 P:     Andy Whitcroft
-M:     apw@shadowen.org
-P:     Randy Dunlap
-M:     rdunlap@xenotime.net
-P:     Joel Schopp
-M:     jschopp@austin.ibm.com
+M:     apw@canonical.com
+L:     linux-kernel@vger.kernel.org
 S:     Supported
 
 CISCO 10G ETHERNET DRIVER
index ca88e54dec93774770f3eb93629d908db69e499e..62b363584b2bda3761263d53a7cd17c30890debe 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ALPHA_ATOMIC_H
 #define _ALPHA_ATOMIC_H
 
+#include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/system.h>
 
  */
 
 
-/*
- * Counter is volatile to make sure gcc doesn't try to be clever
- * and move things around on us. We need to use _exactly_ the address
- * the user gave us, not some alias that contains the same information.
- */
-typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile long counter; } atomic64_t;
-
 #define ATOMIC_INIT(i)         ( (atomic_t) { (i) } )
 #define ATOMIC64_INIT(i)       ( (atomic64_t) { (i) } )
 
index 325f881ccb50204041ed15b824ae0b73e2dcae3f..ee99723b3a6c4899283a76ba26c7140c08a146dd 100644 (file)
 #define __ASM_ARM_ATOMIC_H
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 #include <asm/system.h>
 
-typedef struct { volatile int counter; } atomic_t;
-
 #define ATOMIC_INIT(i) { (i) }
 
 #ifdef __KERNEL__
index 3f9abe0e9aff7e124fd399ce4fd9c4a47380c044..f692efddd4497b0cc505f0eb9a3a526c922489a2 100644 (file)
@@ -92,9 +92,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        if (p->ainsn.insn) {
-               mutex_lock(&kprobe_mutex);
                free_insn_slot(p->ainsn.insn, 0);
-               mutex_unlock(&kprobe_mutex);
                p->ainsn.insn = NULL;
        }
 }
index 774f3adfe8ade0fb5bef6a5d2defc5af3fc4e6bf..1d300fb112b170777a0025d85a7faf7e85ad225d 100644 (file)
@@ -14,7 +14,7 @@
 #define __ASM_ARCH_SPI_H __FILE__
 
 struct s3c2410_spi_info {
-       unsigned long            pin_cs;        /* simple gpio cs */
+       int                      pin_cs;        /* simple gpio cs */
        unsigned int             num_cs;        /* total chipselects */
        int                      bus_num;       /* bus number to use. */
 
index 7ef3862a73d02443d95eaf6520ff45417f3f00d5..318815107748dc8ee335e8fc7d2fc47fab8b10c0 100644 (file)
@@ -14,9 +14,9 @@
 #ifndef __ASM_AVR32_ATOMIC_H
 #define __ASM_AVR32_ATOMIC_H
 
+#include <linux/types.h>
 #include <asm/system.h>
 
-typedef struct { volatile int counter; } atomic_t;
 #define ATOMIC_INIT(i)  { (i) }
 
 #define atomic_read(v)         ((v)->counter)
index 0d987373bc01b6b6424824711903b501294776da..d547c8df157da7f31c5459e2fd4f2395faf1bc34 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/kallsyms.h>
 #include <linux/kdebug.h>
index 7cf508718605db96d005fff016d7c522b24787cf..25776c19064b556ee52801b1759d3719a7ba9914 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
 
+#include <linux/types.h>
 #include <asm/system.h>        /* local_irq_XXX() */
 
 /*
@@ -13,9 +14,6 @@
  * Tony Kou (tonyko@lineo.ca)   Lineo Inc.   2001
  */
 
-typedef struct {
-       int counter;
-} atomic_t;
 #define ATOMIC_INIT(i) { (i) }
 
 #define atomic_read(v)         ((v)->counter)
index f71ea686a2ea701480630169623b69cfcabfbff8..5718dd8902a11d0953f77c03d75db4306c861073 100644 (file)
@@ -4,7 +4,7 @@
 #define __ASM_CRIS_ATOMIC__
 
 #include <linux/compiler.h>
-
+#include <linux/types.h>
 #include <asm/system.h>
 #include <arch/atomic.h>
 
@@ -13,8 +13,6 @@
  * resource counting etc..
  */
 
-typedef struct { volatile int counter; } atomic_t;
-
 #define ATOMIC_INIT(i)  { (i) }
 
 #define atomic_read(v) ((v)->counter)
index b4cf0ea97ede7a0975271b65f8f9d06d68abaea9..833186c8dc3b9cab79f0e801feb602ee952a098c 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef __ARCH_H8300_ATOMIC__
 #define __ARCH_H8300_ATOMIC__
 
+#include <linux/types.h>
+
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
  */
 
-typedef struct { int counter; } atomic_t;
 #define ATOMIC_INIT(i) { (i) }
 
 #define atomic_read(v)         ((v)->counter)
index 50c2b83fd5a04cccf72996add92fae7b2ba0b407..d37292bd98757402f2f075689bb0e04cf254cda6 100644 (file)
 #include <asm/intrinsics.h>
 #include <asm/system.h>
 
-/*
- * On IA-64, counter must always be volatile to ensure that that the
- * memory accesses are ordered.
- */
-typedef struct { volatile __s32 counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
 
 #define ATOMIC_INIT(i)         ((atomic_t) { (i) })
 #define ATOMIC64_INIT(i)       ((atomic64_t) { (i) })
index f07688da947c352217246d706435d09256d8894e..097b84d54e731c6ad7a0b27f9ac081ee0a4e67b8 100644 (file)
@@ -670,9 +670,11 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn, p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
-       mutex_unlock(&kprobe_mutex);
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn,
+                              p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
+               p->ainsn.insn = NULL;
+       }
 }
 /*
  * We are resuming execution after a single step fault, so the pt_regs
index 054bcd9439aa887a724fc031ec91701b7fefb218..56e12903973cc6456d9e2d7f48a7ec45e6301edd 100644 (file)
@@ -692,7 +692,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        pgdat = NODE_DATA(nid);
 
        zone = pgdat->node_zones + ZONE_NORMAL;
-       ret = __add_pages(zone, start_pfn, nr_pages);
+       ret = __add_pages(nid, zone, start_pfn, nr_pages);
 
        if (ret)
                printk("%s: Problem encountered in __add_pages() as ret=%d\n",
index d5632a305dae8e992626dc7d79efc778805f5a51..6bb674855a3f57867ddd6d829eb8ca3e953f9bc9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ARCH_M68KNOMMU_ATOMIC__
 #define __ARCH_M68KNOMMU_ATOMIC__
 
+#include <linux/types.h>
 #include <asm/system.h>
 
 /*
@@ -12,7 +13,6 @@
  * We do not have SMP m68k systems, so we don't have to deal with that.
  */
 
-typedef struct { int counter; } atomic_t;
 #define ATOMIC_INIT(i) { (i) }
 
 #define atomic_read(v)         ((v)->counter)
index 1232be3885b01caa879576f3a9a1fd6dc91c8dbc..c996c3b4d074ddc2c3ed785b7bd9839e4c1cb663 100644 (file)
 #define _ASM_ATOMIC_H
 
 #include <linux/irqflags.h>
+#include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
 #include <asm/system.h>
 
-typedef struct { volatile int counter; } atomic_t;
-
 #define ATOMIC_INIT(i)    { (i) }
 
 /*
@@ -404,8 +403,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 
 #ifdef CONFIG_64BIT
 
-typedef struct { volatile long counter; } atomic64_t;
-
 #define ATOMIC64_INIT(i)    { (i) }
 
 /*
index 57fcc4a5ebb4e93188fa338f786f49bcf509be35..edbfe25c5fc142475e26d7ffff051d5a61003731 100644 (file)
@@ -155,14 +155,11 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 #endif
 
-/* Note that we need not lock read accesses - aligned word writes/reads
- * are atomic, so a reader never sees unconsistent values.
- *
- * Cache-line alignment would conflict with, for example, linux/module.h
+/*
+ * Note that we need not lock read accesses - aligned word writes/reads
+ * are atomic, so a reader never sees inconsistent values.
  */
 
-typedef struct { volatile int counter; } atomic_t;
-
 /* It's possible to reduce all atomic operations to either
  * __atomic_add_return, atomic_set and atomic_read (the latter
  * is there only for consistency).
@@ -260,8 +257,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 
 #ifdef CONFIG_64BIT
 
-typedef struct { volatile s64 counter; } atomic64_t;
-
 #define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
 
 static __inline__ int
index 499be5bdd6fae52bd0f8894fa62e1553eb237912..b401950f5259e6a16a7d38a1fa3c0c509d6183ee 100644 (file)
@@ -5,7 +5,7 @@
  * PowerPC atomic operations
  */
 
-typedef struct { int counter; } atomic_t;
+#include <linux/types.h>
 
 #ifdef __KERNEL__
 #include <linux/compiler.h>
@@ -251,8 +251,6 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
 
 #ifdef __powerpc64__
 
-typedef struct { long counter; } atomic64_t;
-
 #define ATOMIC64_INIT(i)       { (i) }
 
 static __inline__ long atomic64_read(const atomic64_t *v)
index 26f0d0ab27a50261f99e5d36e831329d30f0834c..b1dafb6a9743938fdf4bc63bc0b771400122bc83 100644 (file)
@@ -17,6 +17,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep);
 
+/*
+ * The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs
+ * to override the version in mm/hugetlb.c
+ */
+#define vma_mmu_pagesize vma_mmu_pagesize
+
 /*
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
index de79915452c87d917728acbeefbd70a2b738d242..989edcdf0297fbf5d2ec03539e000b3a01c98d5d 100644 (file)
@@ -96,9 +96,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn, 0);
-       mutex_unlock(&kprobe_mutex);
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn, 0);
+               p->ainsn.insn = NULL;
+       }
 }
 
 static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
index 201c7a5486cb3f815e89ec8e54966b5f29f6feb0..9920d6a7cf290cc02339da13d337fa6eddbf021a 100644 (file)
@@ -512,6 +512,13 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
 }
 
+unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
+{
+       unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
+
+       return 1UL << mmu_psize_to_shift(psize);
+}
+
 /*
  * Called by asm hashtable.S for doing lazy icache flush
  */
index 53b06ebb3f2f7cad0a9dd690f30d0582184e8042..f00f09a77f12f3d628d0b0f51c1a56ebccbadb75 100644 (file)
@@ -132,7 +132,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        /* this should work for most non-highmem platforms */
        zone = pgdata->node_zones;
 
-       return __add_pages(zone, start_pfn, nr_pages);
+       return __add_pages(nid, zone, start_pfn, nr_pages);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
index 2d184655bc5d9b3cad0e9c1bddec672af404c042..de432f2de2d22ed3f9f2362023a52caacea1bcb2 100644 (file)
@@ -2,6 +2,7 @@
 #define __ARCH_S390_ATOMIC__
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 
 /*
  *  include/asm-s390/atomic.h
@@ -23,9 +24,6 @@
  * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
  */
 
-typedef struct {
-       int counter;
-} __attribute__ ((aligned (4))) atomic_t;
 #define ATOMIC_INIT(i)  { (i) }
 
 #ifdef __KERNEL__
@@ -149,9 +147,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 #undef __CS_LOOP
 
 #ifdef __s390x__
-typedef struct {
-       long long counter;
-} __attribute__ ((aligned (8))) atomic64_t;
 #define ATOMIC64_INIT(i)  { (i) }
 
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
index 569079ec4ff004f010d64df7d746b0a01caff44c..9b92856632cfdf3b44914db277adba0c09311a61 100644 (file)
@@ -218,9 +218,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn, 0);
-       mutex_unlock(&kprobe_mutex);
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn, 0);
+               p->ainsn.insn = NULL;
+       }
 }
 
 static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
index 158b0d6d70462942975048759222c6fa69874433..f0258ca3b17ed0905bd8a80a42f15e4355a6fd87 100644 (file)
@@ -183,7 +183,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        rc = vmem_add_mapping(start, size);
        if (rc)
                return rc;
-       rc = __add_pages(zone, PFN_DOWN(start), PFN_DOWN(size));
+       rc = __add_pages(nid, zone, PFN_DOWN(start), PFN_DOWN(size));
        if (rc)
                vmem_remove_mapping(start, size);
        return rc;
index c043ef003028e43fbffe622e801352ca61c3bb97..6327ffbb19928e51305a2d472cbdcd31863a0823 100644 (file)
@@ -7,16 +7,15 @@
  *
  */
 
-typedef struct { volatile int counter; } atomic_t;
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/system.h>
 
 #define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
 
 #define atomic_read(v)         ((v)->counter)
 #define atomic_set(v,i)                ((v)->counter = (i))
 
-#include <linux/compiler.h>
-#include <asm/system.h>
-
 #if defined(CONFIG_GUSA_RB)
 #include <asm/atomic-grb.h>
 #elif defined(CONFIG_CPU_SH4A)
index 88807a2aacc32c583d7b5d1e2392ad0961a87181..c0aa3d83ec0e5e799daaf9265f16f3c30bfbadc9 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
index 6cbef8caeb560e69776579d5525bbad028e9aaec..3edf297c829bd141ef7765f385eaf738fa0386db 100644 (file)
@@ -311,7 +311,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
        pgdat = NODE_DATA(nid);
 
        /* We only have ZONE_NORMAL, so this is easy.. */
-       ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
+       ret = __add_pages(nid, pgdat->node_zones + ZONE_NORMAL,
+                               start_pfn, nr_pages);
        if (unlikely(ret))
                printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
 
index 5c944b5a804003f5cc2a87b7972e5c22cd18ceb7..ce465975a6a5e545c577f71e3203ba47bb3060ae 100644 (file)
@@ -13,8 +13,6 @@
 
 #include <linux/types.h>
 
-typedef struct { volatile int counter; } atomic_t;
-
 #ifdef __KERNEL__
 
 #define ATOMIC_INIT(i)  { (i) }
index 5982c5ae7f0799e9159cd89096e80e99d600c8fe..a0a70649269693e199973b190939e48937fc8157 100644 (file)
@@ -10,9 +10,6 @@
 #include <linux/types.h>
 #include <asm/system.h>
 
-typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
-
 #define ATOMIC_INIT(i)         { (i) }
 #define ATOMIC64_INIT(i)       { (i) }
 
index 44e4904194951f680f187fd4f6137ca289b9cab8..7384d8accfe7d005d896eced4de7ab745452efef 100644 (file)
@@ -64,11 +64,10 @@ good_area:
 
        do {
                int fault;
-survive:
+
                fault = handle_mm_fault(mm, vma, address, is_write);
                if (unlikely(fault & VM_FAULT_ERROR)) {
                        if (fault & VM_FAULT_OOM) {
-                               err = -ENOMEM;
                                goto out_of_memory;
                        } else if (fault & VM_FAULT_SIGBUS) {
                                err = -EACCES;
@@ -104,18 +103,14 @@ out:
 out_nosemaphore:
        return err;
 
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
 out_of_memory:
-       if (is_global_init(current)) {
-               up_read(&mm->mmap_sem);
-               yield();
-               down_read(&mm->mmap_sem);
-               goto survive;
-       }
-       goto out;
+       /*
+        * We ran out of memory, call the OOM killer, and return the userspace
+        * (which will retry the fault, or kill us if we got oom-killed).
+        */
+       up_read(&mm->mmap_sem);
+       pagefault_out_of_memory();
+       return 0;
 }
 
 static void bad_segv(struct faultinfo fi, unsigned long ip)
@@ -214,9 +209,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
                si.si_addr = (void __user *)address;
                current->thread.arch.faultinfo = fi;
                force_sig_info(SIGBUS, &si, current);
-       } else if (err == -ENOMEM) {
-               printk(KERN_INFO "VM: killing process %s\n", current->comm);
-               do_exit(SIGKILL);
        } else {
                BUG_ON(err != -EFAULT);
                si.si_signo = SIGSEGV;
index ad5b9f6ecddf317e32f1abad071246b61471999a..85b46fba4229cc0334e05d5d9c5e66deff3fa69f 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_X86_ATOMIC_32_H
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 #include <asm/processor.h>
 #include <asm/cmpxchg.h>
 
  * resource counting etc..
  */
 
-/*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
- */
-typedef struct {
-       int counter;
-} atomic_t;
-
 #define ATOMIC_INIT(i) { (i) }
 
 /**
index 279d2a731f3fb57e9cdb061d1917df4ed7bb053e..8c21731984daacec35c6df87071b3b94b758c4ca 100644 (file)
@@ -1,25 +1,15 @@
 #ifndef _ASM_X86_ATOMIC_64_H
 #define _ASM_X86_ATOMIC_64_H
 
+#include <linux/types.h>
 #include <asm/alternative.h>
 #include <asm/cmpxchg.h>
 
-/* atomic_t should be 32 bit signed type */
-
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
  */
 
-/*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
- */
-typedef struct {
-       int counter;
-} atomic_t;
-
 #define ATOMIC_INIT(i) { (i) }
 
 /**
@@ -191,11 +181,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 #define atomic_inc_return(v)  (atomic_add_return(1, v))
 #define atomic_dec_return(v)  (atomic_sub_return(1, v))
 
-/* An 64bit atomic type */
-
-typedef struct {
-       long counter;
-} atomic64_t;
+/* The 64-bit atomic type */
 
 #define ATOMIC64_INIT(i)       { (i) }
 
diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
deleted file mode 100644 (file)
index 8b064bd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _ASM_X86_UNWIND_H
-#define _ASM_X86_UNWIND_H
-
-#define UNW_PC(frame) ((void)(frame), 0UL)
-#define UNW_SP(frame) ((void)(frame), 0UL)
-#define UNW_FP(frame) ((void)(frame), 0UL)
-
-static inline int arch_unw_user_mode(const void *info)
-{
-       return 0;
-}
-
-#endif /* _ASM_X86_UNWIND_H */
index 6c27679ec6aa1753be87e05b6c72a10553f69574..eead6f8f921850ce3c4fcc4ef3e5b6a2b8aaecc5 100644 (file)
@@ -376,9 +376,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
-       mutex_unlock(&kprobe_mutex);
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
+               p->ainsn.insn = NULL;
+       }
 }
 
 static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
index ce6650eb64e976e120cbefa87adae9b4675e94ed..c9a666cdd3db928278679f606c71a8006833065b 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/ptrace.h>
 #include <linux/string.h>
-#include <linux/unwind.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/kexec.h>
@@ -51,7 +50,6 @@
 #include <asm/debugreg.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
-#include <asm/unwind.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
index 57ec8c86a8776700729f682fc8a9b60b6a3482cd..9e268b6b204e1e3b34d639061aa43fcd9e0bbc3f 100644 (file)
@@ -667,7 +667,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
        if (unlikely(in_atomic() || !mm))
                goto bad_area_nosemaphore;
 
-again:
        /*
         * When running in the kernel we expect faults to occur only to
         * addresses in user space.  All other faults represent errors in the
@@ -859,25 +858,14 @@ no_context:
        oops_end(flags, regs, sig);
 #endif
 
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
 out_of_memory:
+       /*
+        * We ran out of memory, call the OOM killer, and return the userspace
+        * (which will retry the fault, or kill us if we got oom-killed).
+        */
        up_read(&mm->mmap_sem);
-       if (is_global_init(tsk)) {
-               yield();
-               /*
-                * Re-lookup the vma - in theory the vma tree might
-                * have changed:
-                */
-               goto again;
-       }
-
-       printk("VM: killing process %s\n", tsk->comm);
-       if (error_code & PF_USER)
-               do_group_exit(SIGKILL);
-       goto no_context;
+       pagefault_out_of_memory();
+       return;
 
 do_sigbus:
        up_read(&mm->mmap_sem);
index f99a6c6c432ebc5e53fac79bce694384c2ccdb05..544d724caeee010f149df1b26cf2c7baeab0e73f 100644 (file)
@@ -1079,7 +1079,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
 
-       return __add_pages(zone, start_pfn, nr_pages);
+       return __add_pages(nid, zone, start_pfn, nr_pages);
 }
 #endif
 
index 9f7a0d24d42a93b47e36d3ce40c70876f5d09e16..54c437e96541f2764aaeb566793b092e2af2f219 100644 (file)
@@ -857,7 +857,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        if (last_mapped_pfn > max_pfn_mapped)
                max_pfn_mapped = last_mapped_pfn;
 
-       ret = __add_pages(zone, start_pfn, nr_pages);
+       ret = __add_pages(nid, zone, start_pfn, nr_pages);
        WARN_ON_ONCE(ret);
 
        return ret;
index 38aca048e9515a6f0be0b36f6db9475cbaa889b3..66a9d81455628454f628496415f4bbee495732b4 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/pm_qos_params.h>
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
+#include <linux/irqflags.h>
 
 /*
  * Include the apic definitions for x86 to have the APIC timer related defines
index 5260e9e0df48a3f9b52221f179e72fac01b45f6a..989429cfed88a7395f38a4d1dd44d8d8ff8745ac 100644 (file)
@@ -347,8 +347,9 @@ static inline int memory_probe_init(void)
  * section belongs to...
  */
 
-static int add_memory_block(unsigned long node_id, struct mem_section *section,
-                    unsigned long state, int phys_device)
+static int add_memory_block(int nid, struct mem_section *section,
+                       unsigned long state, int phys_device,
+                       enum mem_add_context context)
 {
        struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
        int ret = 0;
@@ -370,6 +371,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
                ret = mem_create_simple_file(mem, phys_device);
        if (!ret)
                ret = mem_create_simple_file(mem, removable);
+       if (!ret) {
+               if (context == HOTPLUG)
+                       ret = register_mem_sect_under_node(mem, nid);
+       }
 
        return ret;
 }
@@ -382,7 +387,7 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
  *
  * This could be made generic for all sysdev classes.
  */
-static struct memory_block *find_memory_block(struct mem_section *section)
+struct memory_block *find_memory_block(struct mem_section *section)
 {
        struct kobject *kobj;
        struct sys_device *sysdev;
@@ -411,6 +416,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
        struct memory_block *mem;
 
        mem = find_memory_block(section);
+       unregister_mem_sect_under_nodes(mem);
        mem_remove_simple_file(mem, phys_index);
        mem_remove_simple_file(mem, state);
        mem_remove_simple_file(mem, phys_device);
@@ -424,9 +430,9 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
  * need an interface for the VM to add new memory regions,
  * but without onlining it.
  */
-int register_new_memory(struct mem_section *section)
+int register_new_memory(int nid, struct mem_section *section)
 {
-       return add_memory_block(0, section, MEM_OFFLINE, 0);
+       return add_memory_block(nid, section, MEM_OFFLINE, 0, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -458,7 +464,8 @@ int __init memory_dev_init(void)
        for (i = 0; i < NR_MEM_SECTIONS; i++) {
                if (!present_section_nr(i))
                        continue;
-               err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+               err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
+                                       0, BOOT);
                if (!ret)
                        ret = err;
        }
index 91636cd8b6c9ad2e12c2bb0a4925397b6b0c454b..43fa90b837eec4e4e79f6b5ef4d2fb99139317f1 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/memory.h>
 #include <linux/node.h>
 #include <linux/hugetlb.h>
 #include <linux/cpumask.h>
@@ -248,6 +249,105 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
        return 0;
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+#define page_initialized(page)  (page->lru.next)
+
+static int get_nid_for_pfn(unsigned long pfn)
+{
+       struct page *page;
+
+       if (!pfn_valid_within(pfn))
+               return -1;
+       page = pfn_to_page(pfn);
+       if (!page_initialized(page))
+               return -1;
+       return pfn_to_nid(pfn);
+}
+
+/* register memory section under specified node if it spans that node */
+int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
+{
+       unsigned long pfn, sect_start_pfn, sect_end_pfn;
+
+       if (!mem_blk)
+               return -EFAULT;
+       if (!node_online(nid))
+               return 0;
+       sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+       sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+       for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
+               int page_nid;
+
+               page_nid = get_nid_for_pfn(pfn);
+               if (page_nid < 0)
+                       continue;
+               if (page_nid != nid)
+                       continue;
+               return sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj,
+                                       &mem_blk->sysdev.kobj,
+                                       kobject_name(&mem_blk->sysdev.kobj));
+       }
+       /* mem section does not span the specified node */
+       return 0;
+}
+
+/* unregister memory section under all nodes that it spans */
+int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+{
+       nodemask_t unlinked_nodes;
+       unsigned long pfn, sect_start_pfn, sect_end_pfn;
+
+       if (!mem_blk)
+               return -EFAULT;
+       nodes_clear(unlinked_nodes);
+       sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+       sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+       for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
+               unsigned int nid;
+
+               nid = get_nid_for_pfn(pfn);
+               if (nid < 0)
+                       continue;
+               if (!node_online(nid))
+                       continue;
+               if (node_test_and_set(nid, unlinked_nodes))
+                       continue;
+               sysfs_remove_link(&node_devices[nid].sysdev.kobj,
+                        kobject_name(&mem_blk->sysdev.kobj));
+       }
+       return 0;
+}
+
+static int link_mem_sections(int nid)
+{
+       unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
+       unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
+       unsigned long pfn;
+       int err = 0;
+
+       for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+               unsigned long section_nr = pfn_to_section_nr(pfn);
+               struct mem_section *mem_sect;
+               struct memory_block *mem_blk;
+               int ret;
+
+               if (!present_section_nr(section_nr))
+                       continue;
+               mem_sect = __nr_to_section(section_nr);
+               mem_blk = find_memory_block(mem_sect);
+               ret = register_mem_sect_under_node(mem_blk, nid);
+               if (!err)
+                       err = ret;
+
+               /* discard ref obtained in find_memory_block() */
+               kobject_put(&mem_blk->sysdev.kobj);
+       }
+       return err;
+}
+#else
+static int link_mem_sections(int nid) { return 0; }
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
 int register_one_node(int nid)
 {
        int error = 0;
@@ -267,6 +367,9 @@ int register_one_node(int nid)
                        if (cpu_to_node(cpu) == nid)
                                register_cpu_under_node(cpu, nid);
                }
+
+               /* link memory sections under this node */
+               error = link_mem_sections(nid);
        }
 
        return error;
index 1697043119bd27084024b1dd57996f71561ce4a1..35914b6e1d2aee32ddf29dc63b14a6d09e8298e8 100644 (file)
@@ -841,7 +841,7 @@ config JS_RTC
 
 config GEN_RTC
        tristate "Generic /dev/rtc emulation"
-       depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32
+       depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
index 4246b8e36cb32853eedb658b3e96f3c4a46ba978..45d3e80156d45e15d08a1fa164686031126adc4c 100644 (file)
@@ -554,7 +554,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
                __get_user(fontpos, &list->fontpos);
                if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
                        err = err1;
-                       list++;
+               list++;
        }
        
        if (con_unify_unimap(vc, p))
index 6431f6921a67acde3c214f784904c4ebd0f62678..3586b3b3df3f50b1bc1c87669edc6ac54ef8ac67 100644 (file)
@@ -425,9 +425,6 @@ static ssize_t read_oldmem(struct file *file, char __user *buf,
 }
 #endif
 
-extern long vread(char *buf, char *addr, unsigned long count);
-extern long vwrite(char *buf, char *addr, unsigned long count);
-
 #ifdef CONFIG_DEVKMEM
 /*
  * This function reads the *virtual* memory as seen by the kernel.
index c7afc068c28dcf6a64306754953682b0f9cfb70e..7c13581ca9cd6ac1ea4a2d54e80397831cebd75f 100644 (file)
@@ -407,7 +407,7 @@ struct entropy_store {
        /* read-write data: */
        spinlock_t lock;
        unsigned add_ptr;
-       int entropy_count;      /* Must at no time exceed ->POOLBITS! */
+       int entropy_count;
        int input_rotate;
 };
 
@@ -767,11 +767,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 {
        unsigned long flags;
 
-       BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
-
        /* Hold lock while accounting */
        spin_lock_irqsave(&r->lock, flags);
 
+       BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
        DEBUG_ENT("trying to extract %d bits from %s\n",
                  nbytes * 8, r->name);
 
index 94966edfb44dedc340d4d81f230c43a0aec9b7bf..d41b9f6f7903d297976114553527ce51f7e44e3e 100644 (file)
@@ -82,7 +82,7 @@ static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_loglevel_op = {
        .handler        = sysrq_handle_loglevel,
-       .help_msg       = "loglevel0-8",
+       .help_msg       = "loglevel(0-9)",
        .action_msg     = "Changing Loglevel",
        .enable_mask    = SYSRQ_ENABLE_LOG,
 };
@@ -233,7 +233,7 @@ static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
 
 static struct sysrq_key_op sysrq_showallcpus_op = {
        .handler        = sysrq_handle_showallcpus,
-       .help_msg       = "aLlcpus",
+       .help_msg       = "show-backtrace-all-active-cpus(L)",
        .action_msg     = "Show backtrace of all active CPUs",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -247,7 +247,7 @@ static void sysrq_handle_showregs(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_showregs_op = {
        .handler        = sysrq_handle_showregs,
-       .help_msg       = "showPc",
+       .help_msg       = "show-registers(P)",
        .action_msg     = "Show Regs",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -258,7 +258,7 @@ static void sysrq_handle_showstate(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_showstate_op = {
        .handler        = sysrq_handle_showstate,
-       .help_msg       = "showTasks",
+       .help_msg       = "show-task-states(T)",
        .action_msg     = "Show State",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -269,7 +269,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_showstate_blocked_op = {
        .handler        = sysrq_handle_showstate_blocked,
-       .help_msg       = "shoW-blocked-tasks",
+       .help_msg       = "show-blocked-tasks(W)",
        .action_msg     = "Show Blocked State",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -297,7 +297,7 @@ static void sysrq_handle_showmem(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_showmem_op = {
        .handler        = sysrq_handle_showmem,
-       .help_msg       = "showMem",
+       .help_msg       = "show-memory-usage(M)",
        .action_msg     = "Show Memory",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -323,7 +323,7 @@ static void sysrq_handle_term(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_term_op = {
        .handler        = sysrq_handle_term,
-       .help_msg       = "tErm",
+       .help_msg       = "terminate-all-tasks(E)",
        .action_msg     = "Terminate All Tasks",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -341,7 +341,7 @@ static void sysrq_handle_moom(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_moom_op = {
        .handler        = sysrq_handle_moom,
-       .help_msg       = "Full",
+       .help_msg       = "memory-full-oom-kill(F)",
        .action_msg     = "Manual OOM execution",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -353,7 +353,7 @@ static void sysrq_handle_kill(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_kill_op = {
        .handler        = sysrq_handle_kill,
-       .help_msg       = "kIll",
+       .help_msg       = "kill-all-tasks(I)",
        .action_msg     = "Kill All Tasks",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -364,7 +364,7 @@ static void sysrq_handle_unrt(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_unrt_op = {
        .handler        = sysrq_handle_unrt,
-       .help_msg       = "Nice",
+       .help_msg       = "nice-all-RT-tasks(N)",
        .action_msg     = "Nice All RT Tasks",
        .enable_mask    = SYSRQ_ENABLE_RTNICE,
 };
index e2667a8c2997155a141da0a15a5054430bb86e0c..eee47fd16d79866899f7438fcdaea321a524d1f8 100644 (file)
@@ -109,6 +109,13 @@ config EDAC_X38
          Support for error detection and correction on the Intel
          X38 server chipsets.
 
+config EDAC_I5400
+       tristate "Intel 5400 (Seaburg) chipsets"
+       depends on EDAC_MM_EDAC && PCI && X86
+       help
+         Support for error detection and correction the Intel
+         i5400 MCH chipset (Seaburg).
+
 config EDAC_I82860
        tristate "Intel 82860"
        depends on EDAC_MM_EDAC && PCI && X86_32
index 62c2d9bad8dc711166cfb7ac63d144fe87b53319..b75196927de37901424bf58a6c009702ef7f1850 100644 (file)
@@ -20,6 +20,7 @@ endif
 obj-$(CONFIG_EDAC_AMD76X)              += amd76x_edac.o
 obj-$(CONFIG_EDAC_I5000)               += i5000_edac.o
 obj-$(CONFIG_EDAC_I5100)               += i5100_edac.o
+obj-$(CONFIG_EDAC_I5400)               += i5400_edac.o
 obj-$(CONFIG_EDAC_E7XXX)               += e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)               += e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)          += i82443bxgx_edac.o
index 4041e91432837b2d2cc9b898e10f04f20cc778ce..ca9113e1c1060ad9195d7cba55a35d70ed007f20 100644 (file)
@@ -333,7 +333,7 @@ static int add_edac_dev_to_global_list(struct edac_device_ctl_info *edac_dev)
 fail0:
        edac_printk(KERN_WARNING, EDAC_MC,
                        "%s (%s) %s %s already assigned %d\n",
-                       rover->dev->bus_id, edac_dev_name(rover),
+                       dev_name(rover->dev), edac_dev_name(rover),
                        rover->mod_name, rover->ctl_name, rover->dev_idx);
        return 1;
 
index d110392d48f4cd17a854744abdfaef372cd73a84..25d66940b4fa333eae0998c502f16936a3613299 100644 (file)
@@ -401,7 +401,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci)
 
 fail0:
        edac_printk(KERN_WARNING, EDAC_MC,
-               "%s (%s) %s %s already assigned %d\n", p->dev->bus_id,
+               "%s (%s) %s %s already assigned %d\n", dev_name(p->dev),
                edac_dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx);
        return 1;
 
index 22ec9d5d4312940199a7cf425cb73f3d10b11229..5d3c8083a40ebdee27dd34fb260038fcca01ad53 100644 (file)
@@ -150,7 +150,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci)
 fail0:
        edac_printk(KERN_WARNING, EDAC_PCI,
                "%s (%s) %s %s already assigned %d\n",
-               rover->dev->bus_id, edac_dev_name(rover),
+               dev_name(rover->dev), edac_dev_name(rover),
                rover->mod_name, rover->ctl_name, rover->pci_idx);
        return 1;
 
index 5c153dccc95e29ad2ac92658a5dec9a97da7d30a..422728cfe99493ec078bae3d8a392470be157130 100644 (file)
@@ -569,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
 
        local_irq_restore(flags);
 
-       debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id);
+       debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
 
        /* check the status reg for errors on boards NOT marked as broken
         * if broken, we cannot trust any of the status bits
@@ -600,13 +600,13 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
        }
 
 
-       debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id);
+       debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev));
 
        if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
                /* On bridges, need to examine secondary status register  */
                status = get_pci_parity_status(dev, 1);
 
-               debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id);
+               debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
 
                /* check the secondary status reg for errors,
                 * on NOT broken boards
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
new file mode 100644 (file)
index 0000000..b08b6d8
--- /dev/null
@@ -0,0 +1,1476 @@
+/*
+ * Intel 5400 class Memory Controllers kernel module (Seaburg)
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Copyright (c) 2008 by:
+ *      Ben Woodard <woodard@redhat.com>
+ *      Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ *
+ * Forked and adapted from the i5000_edac driver which was
+ * written by Douglas Thompson Linux Networx <norsk5@xmission.com>
+ *
+ * This module is based on the following document:
+ *
+ * Intel 5400 Chipset Memory Controller Hub (MCH) - Datasheet
+ *     http://developer.intel.com/design/chipsets/datashts/313070.htm
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+
+#include "edac_core.h"
+
+/*
+ * Alter this version for the I5400 module when modifications are made
+ */
+#define I5400_REVISION    " Ver: 1.0.0 " __DATE__
+
+#define EDAC_MOD_STR      "i5400_edac"
+
+#define i5400_printk(level, fmt, arg...) \
+       edac_printk(level, "i5400", fmt, ##arg)
+
+#define i5400_mc_printk(mci, level, fmt, arg...) \
+       edac_mc_chipset_printk(mci, level, "i5400", fmt, ##arg)
+
+/* Limits for i5400 */
+#define NUM_MTRS_PER_BRANCH    4
+#define CHANNELS_PER_BRANCH    2
+#define        MAX_CHANNELS            4
+#define MAX_DIMMS              (MAX_CHANNELS * 4)      /* Up to 4 DIMM's per channel */
+#define MAX_CSROWS             (MAX_DIMMS * 2)         /* max possible csrows per channel */
+
+/* Device 16,
+ * Function 0: System Address
+ * Function 1: Memory Branch Map, Control, Errors Register
+ * Function 2: FSB Error Registers
+ *
+ * All 3 functions of Device 16 (0,1,2) share the SAME DID and
+ * uses PCI_DEVICE_ID_INTEL_5400_ERR for device 16 (0,1,2),
+ * PCI_DEVICE_ID_INTEL_5400_FBD0 and PCI_DEVICE_ID_INTEL_5400_FBD1
+ * for device 21 (0,1).
+ */
+
+       /* OFFSETS for Function 0 */
+#define                AMBASE                  0x48 /* AMB Mem Mapped Reg Region Base */
+#define                MAXCH                   0x56 /* Max Channel Number */
+#define                MAXDIMMPERCH            0x57 /* Max DIMM PER Channel Number */
+
+       /* OFFSETS for Function 1 */
+#define                TOLM                    0x6C
+#define                REDMEMB                 0x7C
+#define                        REC_ECC_LOCATOR_ODD(x)  ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0]  indicate EVEN */
+#define                MIR0                    0x80
+#define                MIR1                    0x84
+#define                AMIR0                   0x8c
+#define                AMIR1                   0x90
+
+       /* Fatal error registers */
+#define                FERR_FAT_FBD            0x98    /* also called as FERR_FAT_FB_DIMM at datasheet */
+#define                        FERR_FAT_FBDCHAN (3<<28)        /* channel index where the highest-order error occurred */
+
+#define                NERR_FAT_FBD            0x9c
+#define                FERR_NF_FBD             0xa0    /* also called as FERR_NFAT_FB_DIMM at datasheet */
+
+       /* Non-fatal error register */
+#define                NERR_NF_FBD             0xa4
+
+       /* Enable error mask */
+#define                EMASK_FBD               0xa8
+
+#define                ERR0_FBD                0xac
+#define                ERR1_FBD                0xb0
+#define                ERR2_FBD                0xb4
+#define                MCERR_FBD               0xb8
+
+       /* No OFFSETS for Device 16 Function 2 */
+
+/*
+ * Device 21,
+ * Function 0: Memory Map Branch 0
+ *
+ * Device 22,
+ * Function 0: Memory Map Branch 1
+ */
+
+       /* OFFSETS for Function 0 */
+#define AMBPRESENT_0   0x64
+#define AMBPRESENT_1   0x66
+#define MTR0           0x80
+#define MTR1           0x82
+#define MTR2           0x84
+#define MTR3           0x86
+
+       /* OFFSETS for Function 1 */
+#define NRECFGLOG              0x74
+#define RECFGLOG               0x78
+#define NRECMEMA               0xbe
+#define NRECMEMB               0xc0
+#define NRECFB_DIMMA           0xc4
+#define NRECFB_DIMMB           0xc8
+#define NRECFB_DIMMC           0xcc
+#define NRECFB_DIMMD           0xd0
+#define NRECFB_DIMME           0xd4
+#define NRECFB_DIMMF           0xd8
+#define REDMEMA                        0xdC
+#define RECMEMA                        0xf0
+#define RECMEMB                        0xf4
+#define RECFB_DIMMA            0xf8
+#define RECFB_DIMMB            0xec
+#define RECFB_DIMMC            0xf0
+#define RECFB_DIMMD            0xf4
+#define RECFB_DIMME            0xf8
+#define RECFB_DIMMF            0xfC
+
+/*
+ * Error indicator bits and masks
+ * Error masks are according with Table 5-17 of i5400 datasheet
+ */
+
+enum error_mask {
+       EMASK_M1  = 1<<0,  /* Memory Write error on non-redundant retry */
+       EMASK_M2  = 1<<1,  /* Memory or FB-DIMM configuration CRC read error */
+       EMASK_M3  = 1<<2,  /* Reserved */
+       EMASK_M4  = 1<<3,  /* Uncorrectable Data ECC on Replay */
+       EMASK_M5  = 1<<4,  /* Aliased Uncorrectable Non-Mirrored Demand Data ECC */
+       EMASK_M6  = 1<<5,  /* Unsupported on i5400 */
+       EMASK_M7  = 1<<6,  /* Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */
+       EMASK_M8  = 1<<7,  /* Aliased Uncorrectable Patrol Data ECC */
+       EMASK_M9  = 1<<8,  /* Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC */
+       EMASK_M10 = 1<<9,  /* Unsupported on i5400 */
+       EMASK_M11 = 1<<10, /* Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC  */
+       EMASK_M12 = 1<<11, /* Non-Aliased Uncorrectable Patrol Data ECC */
+       EMASK_M13 = 1<<12, /* Memory Write error on first attempt */
+       EMASK_M14 = 1<<13, /* FB-DIMM Configuration Write error on first attempt */
+       EMASK_M15 = 1<<14, /* Memory or FB-DIMM configuration CRC read error */
+       EMASK_M16 = 1<<15, /* Channel Failed-Over Occurred */
+       EMASK_M17 = 1<<16, /* Correctable Non-Mirrored Demand Data ECC */
+       EMASK_M18 = 1<<17, /* Unsupported on i5400 */
+       EMASK_M19 = 1<<18, /* Correctable Resilver- or Spare-Copy Data ECC */
+       EMASK_M20 = 1<<19, /* Correctable Patrol Data ECC */
+       EMASK_M21 = 1<<20, /* FB-DIMM Northbound parity error on FB-DIMM Sync Status */
+       EMASK_M22 = 1<<21, /* SPD protocol Error */
+       EMASK_M23 = 1<<22, /* Non-Redundant Fast Reset Timeout */
+       EMASK_M24 = 1<<23, /* Refresh error */
+       EMASK_M25 = 1<<24, /* Memory Write error on redundant retry */
+       EMASK_M26 = 1<<25, /* Redundant Fast Reset Timeout */
+       EMASK_M27 = 1<<26, /* Correctable Counter Threshold Exceeded */
+       EMASK_M28 = 1<<27, /* DIMM-Spare Copy Completed */
+       EMASK_M29 = 1<<28, /* DIMM-Isolation Completed */
+};
+
+/*
+ * Names to translate bit error into something useful
+ */
+static const char *error_name[] = {
+       [0]  = "Memory Write error on non-redundant retry",
+       [1]  = "Memory or FB-DIMM configuration CRC read error",
+       /* Reserved */
+       [3]  = "Uncorrectable Data ECC on Replay",
+       [4]  = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
+       /* M6 Unsupported on i5400 */
+       [6]  = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
+       [7]  = "Aliased Uncorrectable Patrol Data ECC",
+       [8]  = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC",
+       /* M10 Unsupported on i5400 */
+       [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
+       [11] = "Non-Aliased Uncorrectable Patrol Data ECC",
+       [12] = "Memory Write error on first attempt",
+       [13] = "FB-DIMM Configuration Write error on first attempt",
+       [14] = "Memory or FB-DIMM configuration CRC read error",
+       [15] = "Channel Failed-Over Occurred",
+       [16] = "Correctable Non-Mirrored Demand Data ECC",
+       /* M18 Unsupported on i5400 */
+       [18] = "Correctable Resilver- or Spare-Copy Data ECC",
+       [19] = "Correctable Patrol Data ECC",
+       [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status",
+       [21] = "SPD protocol Error",
+       [22] = "Non-Redundant Fast Reset Timeout",
+       [23] = "Refresh error",
+       [24] = "Memory Write error on redundant retry",
+       [25] = "Redundant Fast Reset Timeout",
+       [26] = "Correctable Counter Threshold Exceeded",
+       [27] = "DIMM-Spare Copy Completed",
+       [28] = "DIMM-Isolation Completed",
+};
+
+/* Fatal errors */
+#define ERROR_FAT_MASK         (EMASK_M1 | \
+                                EMASK_M2 | \
+                                EMASK_M23)
+
+/* Correctable errors */
+#define ERROR_NF_CORRECTABLE   (EMASK_M27 | \
+                                EMASK_M20 | \
+                                EMASK_M19 | \
+                                EMASK_M18 | \
+                                EMASK_M17 | \
+                                EMASK_M16)
+#define ERROR_NF_DIMM_SPARE    (EMASK_M29 | \
+                                EMASK_M28)
+#define ERROR_NF_SPD_PROTOCOL  (EMASK_M22)
+#define ERROR_NF_NORTH_CRC     (EMASK_M21)
+
+/* Recoverable errors */
+#define ERROR_NF_RECOVERABLE   (EMASK_M26 | \
+                                EMASK_M25 | \
+                                EMASK_M24 | \
+                                EMASK_M15 | \
+                                EMASK_M14 | \
+                                EMASK_M13 | \
+                                EMASK_M12 | \
+                                EMASK_M11 | \
+                                EMASK_M9  | \
+                                EMASK_M8  | \
+                                EMASK_M7  | \
+                                EMASK_M5)
+
+/* uncorrectable errors */
+#define ERROR_NF_UNCORRECTABLE (EMASK_M4)
+
+/* mask to all non-fatal errors */
+#define ERROR_NF_MASK          (ERROR_NF_CORRECTABLE   | \
+                                ERROR_NF_UNCORRECTABLE | \
+                                ERROR_NF_RECOVERABLE   | \
+                                ERROR_NF_DIMM_SPARE    | \
+                                ERROR_NF_SPD_PROTOCOL  | \
+                                ERROR_NF_NORTH_CRC)
+
+/*
+ * Define error masks for the several registers
+ */
+
+/* Enable all fatal and non fatal errors */
+#define ENABLE_EMASK_ALL       (ERROR_FAT_MASK | ERROR_NF_MASK)
+
+/* mask for fatal error registers */
+#define FERR_FAT_MASK ERROR_FAT_MASK
+
+/* masks for non-fatal error register */
+static inline int to_nf_mask(unsigned int mask)
+{
+       return (mask & EMASK_M29) | (mask >> 3);
+};
+
+static inline int from_nf_ferr(unsigned int mask)
+{
+       return (mask & EMASK_M29) |             /* Bit 28 */
+              (mask & ((1 << 28) - 1) << 3);   /* Bits 0 to 27 */
+};
+
+#define FERR_NF_MASK           to_nf_mask(ERROR_NF_MASK)
+#define FERR_NF_CORRECTABLE    to_nf_mask(ERROR_NF_CORRECTABLE)
+#define FERR_NF_DIMM_SPARE     to_nf_mask(ERROR_NF_DIMM_SPARE)
+#define FERR_NF_SPD_PROTOCOL   to_nf_mask(ERROR_NF_SPD_PROTOCOL)
+#define FERR_NF_NORTH_CRC      to_nf_mask(ERROR_NF_NORTH_CRC)
+#define FERR_NF_RECOVERABLE    to_nf_mask(ERROR_NF_RECOVERABLE)
+#define FERR_NF_UNCORRECTABLE  to_nf_mask(ERROR_NF_UNCORRECTABLE)
+
+/* Defines to extract the vaious fields from the
+ *     MTRx - Memory Technology Registers
+ */
+#define MTR_DIMMS_PRESENT(mtr)         ((mtr) & (1 << 10))
+#define MTR_DIMMS_ETHROTTLE(mtr)       ((mtr) & (1 << 9))
+#define MTR_DRAM_WIDTH(mtr)            (((mtr) & (1 << 8)) ? 8 : 4)
+#define MTR_DRAM_BANKS(mtr)            (((mtr) & (1 << 6)) ? 8 : 4)
+#define MTR_DRAM_BANKS_ADDR_BITS(mtr)  ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2)
+#define MTR_DIMM_RANK(mtr)             (((mtr) >> 5) & 0x1)
+#define MTR_DIMM_RANK_ADDR_BITS(mtr)   (MTR_DIMM_RANK(mtr) ? 2 : 1)
+#define MTR_DIMM_ROWS(mtr)             (((mtr) >> 2) & 0x3)
+#define MTR_DIMM_ROWS_ADDR_BITS(mtr)   (MTR_DIMM_ROWS(mtr) + 13)
+#define MTR_DIMM_COLS(mtr)             ((mtr) & 0x3)
+#define MTR_DIMM_COLS_ADDR_BITS(mtr)   (MTR_DIMM_COLS(mtr) + 10)
+
+/* This applies to FERR_NF_FB-DIMM as well as FERR_FAT_FB-DIMM */
+static inline int extract_fbdchan_indx(u32 x)
+{
+       return (x>>28) & 0x3;
+}
+
+#ifdef CONFIG_EDAC_DEBUG
+/* MTR NUMROW */
+static const char *numrow_toString[] = {
+       "8,192 - 13 rows",
+       "16,384 - 14 rows",
+       "32,768 - 15 rows",
+       "65,536 - 16 rows"
+};
+
+/* MTR NUMCOL */
+static const char *numcol_toString[] = {
+       "1,024 - 10 columns",
+       "2,048 - 11 columns",
+       "4,096 - 12 columns",
+       "reserved"
+};
+#endif
+
+/* Device name and register DID (Device ID) */
+struct i5400_dev_info {
+       const char *ctl_name;   /* name for this device */
+       u16 fsb_mapping_errors; /* DID for the branchmap,control */
+};
+
+/* Table of devices attributes supported by this driver */
+static const struct i5400_dev_info i5400_devs[] = {
+       {
+               .ctl_name = "I5400",
+               .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_5400_ERR,
+       },
+};
+
+struct i5400_dimm_info {
+       int megabytes;          /* size, 0 means not present  */
+       int dual_rank;
+};
+
+/* driver private data structure */
+struct i5400_pvt {
+       struct pci_dev *system_address;         /* 16.0 */
+       struct pci_dev *branchmap_werrors;      /* 16.1 */
+       struct pci_dev *fsb_error_regs;         /* 16.2 */
+       struct pci_dev *branch_0;               /* 21.0 */
+       struct pci_dev *branch_1;               /* 22.0 */
+
+       u16 tolm;                               /* top of low memory */
+       u64 ambase;                             /* AMB BAR */
+
+       u16 mir0, mir1;
+
+       u16 b0_mtr[NUM_MTRS_PER_BRANCH];        /* Memory Technlogy Reg */
+       u16 b0_ambpresent0;                     /* Branch 0, Channel 0 */
+       u16 b0_ambpresent1;                     /* Brnach 0, Channel 1 */
+
+       u16 b1_mtr[NUM_MTRS_PER_BRANCH];        /* Memory Technlogy Reg */
+       u16 b1_ambpresent0;                     /* Branch 1, Channel 8 */
+       u16 b1_ambpresent1;                     /* Branch 1, Channel 1 */
+
+       /* DIMM information matrix, allocating architecture maximums */
+       struct i5400_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS];
+
+       /* Actual values for this controller */
+       int maxch;                              /* Max channels */
+       int maxdimmperch;                       /* Max DIMMs per channel */
+};
+
+/* I5400 MCH error information retrieved from Hardware */
+struct i5400_error_info {
+       /* These registers are always read from the MC */
+       u32 ferr_fat_fbd;       /* First Errors Fatal */
+       u32 nerr_fat_fbd;       /* Next Errors Fatal */
+       u32 ferr_nf_fbd;        /* First Errors Non-Fatal */
+       u32 nerr_nf_fbd;        /* Next Errors Non-Fatal */
+
+       /* These registers are input ONLY if there was a Recoverable Error */
+       u32 redmemb;            /* Recoverable Mem Data Error log B */
+       u16 recmema;            /* Recoverable Mem Error log A */
+       u32 recmemb;            /* Recoverable Mem Error log B */
+
+       /* These registers are input ONLY if there was a Non-Rec Error */
+       u16 nrecmema;           /* Non-Recoverable Mem log A */
+       u16 nrecmemb;           /* Non-Recoverable Mem log B */
+
+};
+
+/* note that nrec_rdwr changed from NRECMEMA to NRECMEMB between the 5000 and
+   5400 better to use an inline function than a macro in this case */
+static inline int nrec_bank(struct i5400_error_info *info)
+{
+       return ((info->nrecmema) >> 12) & 0x7;
+}
+static inline int nrec_rank(struct i5400_error_info *info)
+{
+       return ((info->nrecmema) >> 8) & 0xf;
+}
+static inline int nrec_buf_id(struct i5400_error_info *info)
+{
+       return ((info->nrecmema)) & 0xff;
+}
+static inline int nrec_rdwr(struct i5400_error_info *info)
+{
+       return (info->nrecmemb) >> 31;
+}
+/* This applies to both NREC and REC string so it can be used with nrec_rdwr
+   and rec_rdwr */
+static inline const char *rdwr_str(int rdwr)
+{
+       return rdwr ? "Write" : "Read";
+}
+static inline int nrec_cas(struct i5400_error_info *info)
+{
+       return ((info->nrecmemb) >> 16) & 0x1fff;
+}
+static inline int nrec_ras(struct i5400_error_info *info)
+{
+       return (info->nrecmemb) & 0xffff;
+}
+static inline int rec_bank(struct i5400_error_info *info)
+{
+       return ((info->recmema) >> 12) & 0x7;
+}
+static inline int rec_rank(struct i5400_error_info *info)
+{
+       return ((info->recmema) >> 8) & 0xf;
+}
+static inline int rec_rdwr(struct i5400_error_info *info)
+{
+       return (info->recmemb) >> 31;
+}
+static inline int rec_cas(struct i5400_error_info *info)
+{
+       return ((info->recmemb) >> 16) & 0x1fff;
+}
+static inline int rec_ras(struct i5400_error_info *info)
+{
+       return (info->recmemb) & 0xffff;
+}
+
+static struct edac_pci_ctl_info *i5400_pci;
+
+/*
+ *     i5400_get_error_info    Retrieve the hardware error information from
+ *                             the hardware and cache it in the 'info'
+ *                             structure
+ */
+static void i5400_get_error_info(struct mem_ctl_info *mci,
+                                struct i5400_error_info *info)
+{
+       struct i5400_pvt *pvt;
+       u32 value;
+
+       pvt = mci->pvt_info;
+
+       /* read in the 1st FATAL error register */
+       pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value);
+
+       /* Mask only the bits that the doc says are valid
+        */
+       value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK);
+
+       /* If there is an error, then read in the
+          NEXT FATAL error register and the Memory Error Log Register A
+        */
+       if (value & FERR_FAT_MASK) {
+               info->ferr_fat_fbd = value;
+
+               /* harvest the various error data we need */
+               pci_read_config_dword(pvt->branchmap_werrors,
+                               NERR_FAT_FBD, &info->nerr_fat_fbd);
+               pci_read_config_word(pvt->branchmap_werrors,
+                               NRECMEMA, &info->nrecmema);
+               pci_read_config_word(pvt->branchmap_werrors,
+                               NRECMEMB, &info->nrecmemb);
+
+               /* Clear the error bits, by writing them back */
+               pci_write_config_dword(pvt->branchmap_werrors,
+                               FERR_FAT_FBD, value);
+       } else {
+               info->ferr_fat_fbd = 0;
+               info->nerr_fat_fbd = 0;
+               info->nrecmema = 0;
+               info->nrecmemb = 0;
+       }
+
+       /* read in the 1st NON-FATAL error register */
+       pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value);
+
+       /* If there is an error, then read in the 1st NON-FATAL error
+        * register as well */
+       if (value & FERR_NF_MASK) {
+               info->ferr_nf_fbd = value;
+
+               /* harvest the various error data we need */
+               pci_read_config_dword(pvt->branchmap_werrors,
+                               NERR_NF_FBD, &info->nerr_nf_fbd);
+               pci_read_config_word(pvt->branchmap_werrors,
+                               RECMEMA, &info->recmema);
+               pci_read_config_dword(pvt->branchmap_werrors,
+                               RECMEMB, &info->recmemb);
+               pci_read_config_dword(pvt->branchmap_werrors,
+                               REDMEMB, &info->redmemb);
+
+               /* Clear the error bits, by writing them back */
+               pci_write_config_dword(pvt->branchmap_werrors,
+                               FERR_NF_FBD, value);
+       } else {
+               info->ferr_nf_fbd = 0;
+               info->nerr_nf_fbd = 0;
+               info->recmema = 0;
+               info->recmemb = 0;
+               info->redmemb = 0;
+       }
+}
+
+/*
+ * i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci,
+ *                                     struct i5400_error_info *info,
+ *                                     int handle_errors);
+ *
+ *     handle the Intel FATAL and unrecoverable errors, if any
+ */
+static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci,
+                                   struct i5400_error_info *info,
+                                   unsigned long allErrors)
+{
+       char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80];
+       int branch;
+       int channel;
+       int bank;
+       int buf_id;
+       int rank;
+       int rdwr;
+       int ras, cas;
+       int errnum;
+       char *type = NULL;
+
+       if (!allErrors)
+               return;         /* if no error, return now */
+
+       if (allErrors &  ERROR_FAT_MASK)
+               type = "FATAL";
+       else if (allErrors & FERR_NF_UNCORRECTABLE)
+               type = "NON-FATAL uncorrected";
+       else
+               type = "NON-FATAL recoverable";
+
+       /* ONLY ONE of the possible error bits will be set, as per the docs */
+
+       branch = extract_fbdchan_indx(info->ferr_fat_fbd);
+       channel = branch;
+
+       /* Use the NON-Recoverable macros to extract data */
+       bank = nrec_bank(info);
+       rank = nrec_rank(info);
+       buf_id = nrec_buf_id(info);
+       rdwr = nrec_rdwr(info);
+       ras = nrec_ras(info);
+       cas = nrec_cas(info);
+
+       debugf0("\t\tCSROW= %d  Channels= %d,%d  (Branch= %d "
+               "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n",
+               rank, channel, channel + 1, branch >> 1, bank,
+               buf_id, rdwr_str(rdwr), ras, cas);
+
+       /* Only 1 bit will be on */
+       errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+       /* Form out message */
+       snprintf(msg, sizeof(msg),
+                "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s "
+                "RAS=%d CAS=%d %s Err=0x%lx (%s))",
+                type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas,
+                type, allErrors, error_name[errnum]);
+
+       /* Call the helper to output message */
+       edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
+}
+
+/*
+ * i5400_process_fatal_error_info(struct mem_ctl_info *mci,
+ *                             struct i5400_error_info *info,
+ *                             int handle_errors);
+ *
+ *     handle the Intel NON-FATAL errors, if any
+ */
+static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci,
+                                       struct i5400_error_info *info)
+{
+       char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80];
+       unsigned long allErrors;
+       int branch;
+       int channel;
+       int bank;
+       int rank;
+       int rdwr;
+       int ras, cas;
+       int errnum;
+
+       /* mask off the Error bits that are possible */
+       allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK);
+       if (!allErrors)
+               return;         /* if no error, return now */
+
+       /* ONLY ONE of the possible error bits will be set, as per the docs */
+
+       if (allErrors & (ERROR_NF_UNCORRECTABLE | ERROR_NF_RECOVERABLE)) {
+               i5400_proccess_non_recoverable_info(mci, info, allErrors);
+               return;
+       }
+
+       /* Correctable errors */
+       if (allErrors & ERROR_NF_CORRECTABLE) {
+               debugf0("\tCorrected bits= 0x%lx\n", allErrors);
+
+               branch = extract_fbdchan_indx(info->ferr_nf_fbd);
+
+               channel = 0;
+               if (REC_ECC_LOCATOR_ODD(info->redmemb))
+                       channel = 1;
+
+               /* Convert channel to be based from zero, instead of
+                * from branch base of 0 */
+               channel += branch;
+
+               bank = rec_bank(info);
+               rank = rec_rank(info);
+               rdwr = rec_rdwr(info);
+               ras = rec_ras(info);
+               cas = rec_cas(info);
+
+               /* Only 1 bit will be on */
+               errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+               debugf0("\t\tCSROW= %d Channel= %d  (Branch %d "
+                       "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
+                       rank, channel, branch >> 1, bank,
+                       rdwr_str(rdwr), ras, cas);
+
+               /* Form out message */
+               snprintf(msg, sizeof(msg),
+                        "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s "
+                        "RAS=%d CAS=%d, CE Err=0x%lx (%s))",
+                        branch >> 1, bank, rdwr_str(rdwr), ras, cas,
+                        allErrors, error_name[errnum]);
+
+               /* Call the helper to output message */
+               edac_mc_handle_fbd_ce(mci, rank, channel, msg);
+
+               return;
+       }
+
+       /* Miscelaneous errors */
+       errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+       branch = extract_fbdchan_indx(info->ferr_nf_fbd);
+
+       i5400_mc_printk(mci, KERN_EMERG,
+                       "Non-Fatal misc error (Branch=%d Err=%#lx (%s))",
+                       branch >> 1, allErrors, error_name[errnum]);
+}
+
+/*
+ *     i5400_process_error_info        Process the error info that is
+ *     in the 'info' structure, previously retrieved from hardware
+ */
+static void i5400_process_error_info(struct mem_ctl_info *mci,
+                               struct i5400_error_info *info)
+{      u32 allErrors;
+
+       /* First handle any fatal errors that occurred */
+       allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK);
+       i5400_proccess_non_recoverable_info(mci, info, allErrors);
+
+       /* now handle any non-fatal errors that occurred */
+       i5400_process_nonfatal_error_info(mci, info);
+}
+
+/*
+ *     i5400_clear_error       Retrieve any error from the hardware
+ *                             but do NOT process that error.
+ *                             Used for 'clearing' out of previous errors
+ *                             Called by the Core module.
+ */
+static void i5400_clear_error(struct mem_ctl_info *mci)
+{
+       struct i5400_error_info info;
+
+       i5400_get_error_info(mci, &info);
+}
+
+/*
+ *     i5400_check_error       Retrieve and process errors reported by the
+ *                             hardware. Called by the Core module.
+ */
+static void i5400_check_error(struct mem_ctl_info *mci)
+{
+       struct i5400_error_info info;
+       debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+       i5400_get_error_info(mci, &info);
+       i5400_process_error_info(mci, &info);
+}
+
+/*
+ *     i5400_put_devices       'put' all the devices that we have
+ *                             reserved via 'get'
+ */
+static void i5400_put_devices(struct mem_ctl_info *mci)
+{
+       struct i5400_pvt *pvt;
+
+       pvt = mci->pvt_info;
+
+       /* Decrement usage count for devices */
+       pci_dev_put(pvt->branch_1);
+       pci_dev_put(pvt->branch_0);
+       pci_dev_put(pvt->fsb_error_regs);
+       pci_dev_put(pvt->branchmap_werrors);
+}
+
+/*
+ *     i5400_get_devices       Find and perform 'get' operation on the MCH's
+ *                     device/functions we want to reference for this driver
+ *
+ *                     Need to 'get' device 16 func 1 and func 2
+ */
+static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
+{
+       struct i5400_pvt *pvt;
+       struct pci_dev *pdev;
+
+       pvt = mci->pvt_info;
+       pvt->branchmap_werrors = NULL;
+       pvt->fsb_error_regs = NULL;
+       pvt->branch_0 = NULL;
+       pvt->branch_1 = NULL;
+
+       /* Attempt to 'get' the MCH register we want */
+       pdev = NULL;
+       while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) {
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
+               if (!pdev) {
+                       /* End of list, leave */
+                       i5400_printk(KERN_ERR,
+                               "'system address,Process Bus' "
+                               "device not found:"
+                               "vendor 0x%x device 0x%x ERR funcs "
+                               "(broken BIOS?)\n",
+                               PCI_VENDOR_ID_INTEL,
+                               PCI_DEVICE_ID_INTEL_5400_ERR);
+                       goto error;
+               }
+
+               /* Store device 16 funcs 1 and 2 */
+               switch (PCI_FUNC(pdev->devfn)) {
+               case 1:
+                       pvt->branchmap_werrors = pdev;
+                       break;
+               case 2:
+                       pvt->fsb_error_regs = pdev;
+                       break;
+               }
+       }
+
+       debugf1("System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
+               pci_name(pvt->system_address),
+               pvt->system_address->vendor, pvt->system_address->device);
+       debugf1("Branchmap, control and errors - PCI Bus ID: %s  %x:%x\n",
+               pci_name(pvt->branchmap_werrors),
+               pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device);
+       debugf1("FSB Error Regs - PCI Bus ID: %s  %x:%x\n",
+               pci_name(pvt->fsb_error_regs),
+               pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device);
+
+       pvt->branch_0 = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                      PCI_DEVICE_ID_INTEL_5400_FBD0, NULL);
+       if (!pvt->branch_0) {
+               i5400_printk(KERN_ERR,
+                       "MC: 'BRANCH 0' device not found:"
+                       "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
+                       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
+               goto error;
+       }
+
+       /* If this device claims to have more than 2 channels then
+        * fetch Branch 1's information
+        */
+       if (pvt->maxch < CHANNELS_PER_BRANCH)
+               return 0;
+
+       pvt->branch_1 = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                      PCI_DEVICE_ID_INTEL_5400_FBD1, NULL);
+       if (!pvt->branch_1) {
+               i5400_printk(KERN_ERR,
+                       "MC: 'BRANCH 1' device not found:"
+                       "vendor 0x%x device 0x%x Func 0 "
+                       "(broken BIOS?)\n",
+                       PCI_VENDOR_ID_INTEL,
+                       PCI_DEVICE_ID_INTEL_5400_FBD1);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       i5400_put_devices(mci);
+       return -ENODEV;
+}
+
+/*
+ *     determine_amb_present
+ *
+ *             the information is contained in NUM_MTRS_PER_BRANCH different
+ *             registers determining which of the NUM_MTRS_PER_BRANCH requires
+ *              knowing which channel is in question
+ *
+ *     2 branches, each with 2 channels
+ *             b0_ambpresent0 for channel '0'
+ *             b0_ambpresent1 for channel '1'
+ *             b1_ambpresent0 for channel '2'
+ *             b1_ambpresent1 for channel '3'
+ */
+static int determine_amb_present_reg(struct i5400_pvt *pvt, int channel)
+{
+       int amb_present;
+
+       if (channel < CHANNELS_PER_BRANCH) {
+               if (channel & 0x1)
+                       amb_present = pvt->b0_ambpresent1;
+               else
+                       amb_present = pvt->b0_ambpresent0;
+       } else {
+               if (channel & 0x1)
+                       amb_present = pvt->b1_ambpresent1;
+               else
+                       amb_present = pvt->b1_ambpresent0;
+       }
+
+       return amb_present;
+}
+
+/*
+ * determine_mtr(pvt, csrow, channel)
+ *
+ * return the proper MTR register as determine by the csrow and desired channel
+ */
+static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
+{
+       int mtr;
+       int n;
+
+       /* There is one MTR for each slot pair of FB-DIMMs,
+          Each slot may have one or two ranks (2 csrows),
+          Each slot pair may be at branch 0 or branch 1.
+          So, csrow should be divided by eight
+        */
+       n = csrow >> 3;
+
+       if (n >= NUM_MTRS_PER_BRANCH) {
+               debugf0("ERROR: trying to access an invalid csrow: %d\n",
+                       csrow);
+               return 0;
+       }
+
+       if (channel < CHANNELS_PER_BRANCH)
+               mtr = pvt->b0_mtr[n];
+       else
+               mtr = pvt->b1_mtr[n];
+
+       return mtr;
+}
+
+/*
+ */
+static void decode_mtr(int slot_row, u16 mtr)
+{
+       int ans;
+
+       ans = MTR_DIMMS_PRESENT(mtr);
+
+       debugf2("\tMTR%d=0x%x:  DIMMs are %s\n", slot_row, mtr,
+               ans ? "Present" : "NOT Present");
+       if (!ans)
+               return;
+
+       debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
+
+       debugf2("\t\tELECTRICAL THROTTLING is %s\n",
+               MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
+
+       debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
+       debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single");
+       debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]);
+       debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
+}
+
+static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel,
+                       struct i5400_dimm_info *dinfo)
+{
+       int mtr;
+       int amb_present_reg;
+       int addrBits;
+
+       mtr = determine_mtr(pvt, csrow, channel);
+       if (MTR_DIMMS_PRESENT(mtr)) {
+               amb_present_reg = determine_amb_present_reg(pvt, channel);
+
+               /* Determine if there is a DIMM present in this DIMM slot */
+               if (amb_present_reg & (1 << (csrow >> 1))) {
+                       dinfo->dual_rank = MTR_DIMM_RANK(mtr);
+
+                       if (!((dinfo->dual_rank == 0) &&
+                               ((csrow & 0x1) == 0x1))) {
+                               /* Start with the number of bits for a Bank
+                                * on the DRAM */
+                               addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
+                               /* Add thenumber of ROW bits */
+                               addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
+                               /* add the number of COLUMN bits */
+                               addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+
+                               addrBits += 6;  /* add 64 bits per DIMM */
+                               addrBits -= 20; /* divide by 2^^20 */
+                               addrBits -= 3;  /* 8 bits per bytes */
+
+                               dinfo->megabytes = 1 << addrBits;
+                       }
+               }
+       }
+}
+
+/*
+ *     calculate_dimm_size
+ *
+ *     also will output a DIMM matrix map, if debug is enabled, for viewing
+ *     how the DIMMs are populated
+ */
+static void calculate_dimm_size(struct i5400_pvt *pvt)
+{
+       struct i5400_dimm_info *dinfo;
+       int csrow, max_csrows;
+       char *p, *mem_buffer;
+       int space, n;
+       int channel;
+
+       /* ================= Generate some debug output ================= */
+       space = PAGE_SIZE;
+       mem_buffer = p = kmalloc(space, GFP_KERNEL);
+       if (p == NULL) {
+               i5400_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n",
+                       __FILE__, __func__);
+               return;
+       }
+
+       /* Scan all the actual CSROWS (which is # of DIMMS * 2)
+        * and calculate the information for each DIMM
+        * Start with the highest csrow first, to display it first
+        * and work toward the 0th csrow
+        */
+       max_csrows = pvt->maxdimmperch * 2;
+       for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
+
+               /* on an odd csrow, first output a 'boundary' marker,
+                * then reset the message buffer  */
+               if (csrow & 0x1) {
+                       n = snprintf(p, space, "---------------------------"
+                                       "--------------------------------");
+                       p += n;
+                       space -= n;
+                       debugf2("%s\n", mem_buffer);
+                       p = mem_buffer;
+                       space = PAGE_SIZE;
+               }
+               n = snprintf(p, space, "csrow %2d    ", csrow);
+               p += n;
+               space -= n;
+
+               for (channel = 0; channel < pvt->maxch; channel++) {
+                       dinfo = &pvt->dimm_info[csrow][channel];
+                       handle_channel(pvt, csrow, channel, dinfo);
+                       n = snprintf(p, space, "%4d MB   | ", dinfo->megabytes);
+                       p += n;
+                       space -= n;
+               }
+               debugf2("%s\n", mem_buffer);
+               p = mem_buffer;
+               space = PAGE_SIZE;
+       }
+
+       /* Output the last bottom 'boundary' marker */
+       n = snprintf(p, space, "---------------------------"
+                       "--------------------------------");
+       p += n;
+       space -= n;
+       debugf2("%s\n", mem_buffer);
+       p = mem_buffer;
+       space = PAGE_SIZE;
+
+       /* now output the 'channel' labels */
+       n = snprintf(p, space, "            ");
+       p += n;
+       space -= n;
+       for (channel = 0; channel < pvt->maxch; channel++) {
+               n = snprintf(p, space, "channel %d | ", channel);
+               p += n;
+               space -= n;
+       }
+
+       /* output the last message and free buffer */
+       debugf2("%s\n", mem_buffer);
+       kfree(mem_buffer);
+}
+
+/*
+ *     i5400_get_mc_regs       read in the necessary registers and
+ *                             cache locally
+ *
+ *                     Fills in the private data members
+ */
+static void i5400_get_mc_regs(struct mem_ctl_info *mci)
+{
+       struct i5400_pvt *pvt;
+       u32 actual_tolm;
+       u16 limit;
+       int slot_row;
+       int maxch;
+       int maxdimmperch;
+       int way0, way1;
+
+       pvt = mci->pvt_info;
+
+       pci_read_config_dword(pvt->system_address, AMBASE,
+                       (u32 *) &pvt->ambase);
+       pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32),
+                       ((u32 *) &pvt->ambase) + sizeof(u32));
+
+       maxdimmperch = pvt->maxdimmperch;
+       maxch = pvt->maxch;
+
+       debugf2("AMBASE= 0x%lx  MAXCH= %d  MAX-DIMM-Per-CH= %d\n",
+               (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch);
+
+       /* Get the Branch Map regs */
+       pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm);
+       pvt->tolm >>= 12;
+       debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm,
+               pvt->tolm);
+
+       actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28));
+       debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n",
+               actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28);
+
+       pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0);
+       pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1);
+
+       /* Get the MIR[0-1] regs */
+       limit = (pvt->mir0 >> 4) & 0x0fff;
+       way0 = pvt->mir0 & 0x1;
+       way1 = pvt->mir0 & 0x2;
+       debugf2("MIR0: limit= 0x%x  WAY1= %u  WAY0= %x\n", limit, way1, way0);
+       limit = (pvt->mir1 >> 4) & 0xfff;
+       way0 = pvt->mir1 & 0x1;
+       way1 = pvt->mir1 & 0x2;
+       debugf2("MIR1: limit= 0x%x  WAY1= %u  WAY0= %x\n", limit, way1, way0);
+
+       /* Get the set of MTR[0-3] regs by each branch */
+       for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) {
+               int where = MTR0 + (slot_row * sizeof(u32));
+
+               /* Branch 0 set of MTR registers */
+               pci_read_config_word(pvt->branch_0, where,
+                               &pvt->b0_mtr[slot_row]);
+
+               debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where,
+                       pvt->b0_mtr[slot_row]);
+
+               if (pvt->maxch < CHANNELS_PER_BRANCH) {
+                       pvt->b1_mtr[slot_row] = 0;
+                       continue;
+               }
+
+               /* Branch 1 set of MTR registers */
+               pci_read_config_word(pvt->branch_1, where,
+                               &pvt->b1_mtr[slot_row]);
+               debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, where,
+                       pvt->b1_mtr[slot_row]);
+       }
+
+       /* Read and dump branch 0's MTRs */
+       debugf2("\nMemory Technology Registers:\n");
+       debugf2("   Branch 0:\n");
+       for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++)
+               decode_mtr(slot_row, pvt->b0_mtr[slot_row]);
+
+       pci_read_config_word(pvt->branch_0, AMBPRESENT_0,
+                       &pvt->b0_ambpresent0);
+       debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0);
+       pci_read_config_word(pvt->branch_0, AMBPRESENT_1,
+                       &pvt->b0_ambpresent1);
+       debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1);
+
+       /* Only if we have 2 branchs (4 channels) */
+       if (pvt->maxch < CHANNELS_PER_BRANCH) {
+               pvt->b1_ambpresent0 = 0;
+               pvt->b1_ambpresent1 = 0;
+       } else {
+               /* Read and dump  branch 1's MTRs */
+               debugf2("   Branch 1:\n");
+               for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++)
+                       decode_mtr(slot_row, pvt->b1_mtr[slot_row]);
+
+               pci_read_config_word(pvt->branch_1, AMBPRESENT_0,
+                               &pvt->b1_ambpresent0);
+               debugf2("\t\tAMB-Branch 1-present0 0x%x:\n",
+                       pvt->b1_ambpresent0);
+               pci_read_config_word(pvt->branch_1, AMBPRESENT_1,
+                               &pvt->b1_ambpresent1);
+               debugf2("\t\tAMB-Branch 1-present1 0x%x:\n",
+                       pvt->b1_ambpresent1);
+       }
+
+       /* Go and determine the size of each DIMM and place in an
+        * orderly matrix */
+       calculate_dimm_size(pvt);
+}
+
+/*
+ *     i5400_init_csrows       Initialize the 'csrows' table within
+ *                             the mci control structure with the
+ *                             addressing of memory.
+ *
+ *     return:
+ *             0       success
+ *             1       no actual memory found on this MC
+ */
+static int i5400_init_csrows(struct mem_ctl_info *mci)
+{
+       struct i5400_pvt *pvt;
+       struct csrow_info *p_csrow;
+       int empty, channel_count;
+       int max_csrows;
+       int mtr;
+       int csrow_megs;
+       int channel;
+       int csrow;
+
+       pvt = mci->pvt_info;
+
+       channel_count = pvt->maxch;
+       max_csrows = pvt->maxdimmperch * 2;
+
+       empty = 1;              /* Assume NO memory */
+
+       for (csrow = 0; csrow < max_csrows; csrow++) {
+               p_csrow = &mci->csrows[csrow];
+
+               p_csrow->csrow_idx = csrow;
+
+               /* use branch 0 for the basis */
+               mtr = determine_mtr(pvt, csrow, 0);
+
+               /* if no DIMMS on this row, continue */
+               if (!MTR_DIMMS_PRESENT(mtr))
+                       continue;
+
+               /* FAKE OUT VALUES, FIXME */
+               p_csrow->first_page = 0 + csrow * 20;
+               p_csrow->last_page = 9 + csrow * 20;
+               p_csrow->page_mask = 0xFFF;
+
+               p_csrow->grain = 8;
+
+               csrow_megs = 0;
+               for (channel = 0; channel < pvt->maxch; channel++)
+                       csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
+
+               p_csrow->nr_pages = csrow_megs << 8;
+
+               /* Assume DDR2 for now */
+               p_csrow->mtype = MEM_FB_DDR2;
+
+               /* ask what device type on this row */
+               if (MTR_DRAM_WIDTH(mtr))
+                       p_csrow->dtype = DEV_X8;
+               else
+                       p_csrow->dtype = DEV_X4;
+
+               p_csrow->edac_mode = EDAC_S8ECD8ED;
+
+               empty = 0;
+       }
+
+       return empty;
+}
+
+/*
+ *     i5400_enable_error_reporting
+ *                     Turn on the memory reporting features of the hardware
+ */
+static void i5400_enable_error_reporting(struct mem_ctl_info *mci)
+{
+       struct i5400_pvt *pvt;
+       u32 fbd_error_mask;
+
+       pvt = mci->pvt_info;
+
+       /* Read the FBD Error Mask Register */
+       pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD,
+                       &fbd_error_mask);
+
+       /* Enable with a '0' */
+       fbd_error_mask &= ~(ENABLE_EMASK_ALL);
+
+       pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD,
+                       fbd_error_mask);
+}
+
+/*
+ * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels)
+ *
+ *     ask the device how many channels are present and how many CSROWS
+ *      as well
+ */
+static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev,
+                                       int *num_dimms_per_channel,
+                                       int *num_channels)
+{
+       u8 value;
+
+       /* Need to retrieve just how many channels and dimms per channel are
+        * supported on this memory controller
+        */
+       pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
+       *num_dimms_per_channel = (int)value * 2;
+
+       pci_read_config_byte(pdev, MAXCH, &value);
+       *num_channels = (int)value;
+}
+
+/*
+ *     i5400_probe1    Probe for ONE instance of device to see if it is
+ *                     present.
+ *     return:
+ *             0 for FOUND a device
+ *             < 0 for error code
+ */
+static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
+{
+       struct mem_ctl_info *mci;
+       struct i5400_pvt *pvt;
+       int num_channels;
+       int num_dimms_per_channel;
+       int num_csrows;
+
+       if (dev_idx >= ARRAY_SIZE(i5400_devs))
+               return -EINVAL;
+
+       debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
+               __func__,
+               pdev->bus->number,
+               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+       /* We only are looking for func 0 of the set */
+       if (PCI_FUNC(pdev->devfn) != 0)
+               return -ENODEV;
+
+       /* Ask the devices for the number of CSROWS and CHANNELS so
+        * that we can calculate the memory resources, etc
+        *
+        * The Chipset will report what it can handle which will be greater
+        * or equal to what the motherboard manufacturer will implement.
+        *
+        * As we don't have a motherboard identification routine to determine
+        * actual number of slots/dimms per channel, we thus utilize the
+        * resource as specified by the chipset. Thus, we might have
+        * have more DIMMs per channel than actually on the mobo, but this
+        * allows the driver to support upto the chipset max, without
+        * some fancy mobo determination.
+        */
+       i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
+                                       &num_channels);
+       num_csrows = num_dimms_per_channel * 2;
+
+       debugf0("MC: %s(): Number of - Channels= %d  DIMMS= %d  CSROWS= %d\n",
+               __func__, num_channels, num_dimms_per_channel, num_csrows);
+
+       /* allocate a new MC control structure */
+       mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
+
+       if (mci == NULL)
+               return -ENOMEM;
+
+       debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+       mci->dev = &pdev->dev;  /* record ptr  to the generic device */
+
+       pvt = mci->pvt_info;
+       pvt->system_address = pdev;     /* Record this device in our private */
+       pvt->maxch = num_channels;
+       pvt->maxdimmperch = num_dimms_per_channel;
+
+       /* 'get' the pci devices we want to reserve for our use */
+       if (i5400_get_devices(mci, dev_idx))
+               goto fail0;
+
+       /* Time to get serious */
+       i5400_get_mc_regs(mci); /* retrieve the hardware registers */
+
+       mci->mc_idx = 0;
+       mci->mtype_cap = MEM_FLAG_FB_DDR2;
+       mci->edac_ctl_cap = EDAC_FLAG_NONE;
+       mci->edac_cap = EDAC_FLAG_NONE;
+       mci->mod_name = "i5400_edac.c";
+       mci->mod_ver = I5400_REVISION;
+       mci->ctl_name = i5400_devs[dev_idx].ctl_name;
+       mci->dev_name = pci_name(pdev);
+       mci->ctl_page_to_phys = NULL;
+
+       /* Set the function pointer to an actual operation function */
+       mci->edac_check = i5400_check_error;
+
+       /* initialize the MC control structure 'csrows' table
+        * with the mapping and control information */
+       if (i5400_init_csrows(mci)) {
+               debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n"
+                       "    because i5400_init_csrows() returned nonzero "
+                       "value\n");
+               mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
+       } else {
+               debugf1("MC: Enable error reporting now\n");
+               i5400_enable_error_reporting(mci);
+       }
+
+       /* add this new MC control structure to EDAC's list of MCs */
+       if (edac_mc_add_mc(mci)) {
+               debugf0("MC: " __FILE__
+                       ": %s(): failed edac_mc_add_mc()\n", __func__);
+               /* FIXME: perhaps some code should go here that disables error
+                * reporting if we just enabled it
+                */
+               goto fail1;
+       }
+
+       i5400_clear_error(mci);
+
+       /* allocating generic PCI control info */
+       i5400_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
+       if (!i5400_pci) {
+               printk(KERN_WARNING
+                       "%s(): Unable to create PCI control\n",
+                       __func__);
+               printk(KERN_WARNING
+                       "%s(): PCI error report via EDAC not setup\n",
+                       __func__);
+       }
+
+       return 0;
+
+       /* Error exit unwinding stack */
+fail1:
+
+       i5400_put_devices(mci);
+
+fail0:
+       edac_mc_free(mci);
+       return -ENODEV;
+}
+
+/*
+ *     i5400_init_one  constructor for one instance of device
+ *
+ *     returns:
+ *             negative on error
+ *             count (>= 0)
+ */
+static int __devinit i5400_init_one(struct pci_dev *pdev,
+                               const struct pci_device_id *id)
+{
+       int rc;
+
+       debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+       /* wake up device */
+       rc = pci_enable_device(pdev);
+       if (rc == -EIO)
+               return rc;
+
+       /* now probe and enable the device */
+       return i5400_probe1(pdev, id->driver_data);
+}
+
+/*
+ *     i5400_remove_one        destructor for one instance of device
+ *
+ */
+static void __devexit i5400_remove_one(struct pci_dev *pdev)
+{
+       struct mem_ctl_info *mci;
+
+       debugf0(__FILE__ ": %s()\n", __func__);
+
+       if (i5400_pci)
+               edac_pci_release_generic_ctl(i5400_pci);
+
+       mci = edac_mc_del_mc(&pdev->dev);
+       if (!mci)
+               return;
+
+       /* retrieve references to resources, and free those resources */
+       i5400_put_devices(mci);
+
+       edac_mc_free(mci);
+}
+
+/*
+ *     pci_device_id   table for which devices we are looking for
+ *
+ *     The "E500P" device is the first device supported.
+ */
+static const struct pci_device_id i5400_pci_tbl[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)},
+       {0,}                    /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i5400_pci_tbl);
+
+/*
+ *     i5400_driver    pci_driver structure for this module
+ *
+ */
+static struct pci_driver i5400_driver = {
+       .name = "i5400_edac",
+       .probe = i5400_init_one,
+       .remove = __devexit_p(i5400_remove_one),
+       .id_table = i5400_pci_tbl,
+};
+
+/*
+ *     i5400_init              Module entry function
+ *                     Try to initialize this module for its devices
+ */
+static int __init i5400_init(void)
+{
+       int pci_rc;
+
+       debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
+       pci_rc = pci_register_driver(&i5400_driver);
+
+       return (pci_rc < 0) ? pci_rc : 0;
+}
+
+/*
+ *     i5400_exit()    Module exit function
+ *                     Unregister the driver
+ */
+static void __exit i5400_exit(void)
+{
+       debugf2("MC: " __FILE__ ": %s()\n", __func__);
+       pci_unregister_driver(&i5400_driver);
+}
+
+module_init(i5400_init);
+module_exit(i5400_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Woodard <woodard@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - "
+                  I5400_REVISION);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index ebb037b78758f5f86f06abba1613121f8195d858..b2d83b95033d382c3d2818c56533287ff4d77d67 100644 (file)
@@ -311,9 +311,7 @@ static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
        }
 
        /* cache is irrelevant for PCI bus reads/writes */
-       window = ioremap_nocache(pci_resource_start(dev, 0),
-                                pci_resource_len(dev, 0));
-
+       window = pci_ioremap_bar(dev, 0);
        if (window == NULL) {
                i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
                        __func__);
index 0cfcb2d075a0620228092f741970b525702319a7..853ef37ec00662a894a7d6caa6c889823b8a0ce8 100644 (file)
@@ -630,27 +630,22 @@ static int mpc85xx_l2_err_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc85xx_l2_err_of_match[] = {
-       {
-        .compatible = "fsl,8540-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,8541-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,8544-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,8548-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,8555-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,8568-l2-cache-controller",
-        },
-       {
-        .compatible = "fsl,mpc8572-l2-cache-controller",
-        },
+/* deprecate the fsl,85.. forms in the future, 2.6.30? */
+       { .compatible = "fsl,8540-l2-cache-controller", },
+       { .compatible = "fsl,8541-l2-cache-controller", },
+       { .compatible = "fsl,8544-l2-cache-controller", },
+       { .compatible = "fsl,8548-l2-cache-controller", },
+       { .compatible = "fsl,8555-l2-cache-controller", },
+       { .compatible = "fsl,8568-l2-cache-controller", },
+       { .compatible = "fsl,mpc8536-l2-cache-controller", },
+       { .compatible = "fsl,mpc8540-l2-cache-controller", },
+       { .compatible = "fsl,mpc8541-l2-cache-controller", },
+       { .compatible = "fsl,mpc8544-l2-cache-controller", },
+       { .compatible = "fsl,mpc8548-l2-cache-controller", },
+       { .compatible = "fsl,mpc8555-l2-cache-controller", },
+       { .compatible = "fsl,mpc8560-l2-cache-controller", },
+       { .compatible = "fsl,mpc8568-l2-cache-controller", },
+       { .compatible = "fsl,mpc8572-l2-cache-controller", },
        {},
 };
 
@@ -967,27 +962,22 @@ static int mpc85xx_mc_err_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc85xx_mc_err_of_match[] = {
-       {
-        .compatible = "fsl,8540-memory-controller",
-        },
-       {
-        .compatible = "fsl,8541-memory-controller",
-        },
-       {
-        .compatible = "fsl,8544-memory-controller",
-        },
-       {
-        .compatible = "fsl,8548-memory-controller",
-        },
-       {
-        .compatible = "fsl,8555-memory-controller",
-        },
-       {
-        .compatible = "fsl,8568-memory-controller",
-        },
-       {
-        .compatible = "fsl,mpc8572-memory-controller",
-        },
+/* deprecate the fsl,85.. forms in the future, 2.6.30? */
+       { .compatible = "fsl,8540-memory-controller", },
+       { .compatible = "fsl,8541-memory-controller", },
+       { .compatible = "fsl,8544-memory-controller", },
+       { .compatible = "fsl,8548-memory-controller", },
+       { .compatible = "fsl,8555-memory-controller", },
+       { .compatible = "fsl,8568-memory-controller", },
+       { .compatible = "fsl,mpc8536-memory-controller", },
+       { .compatible = "fsl,mpc8540-memory-controller", },
+       { .compatible = "fsl,mpc8541-memory-controller", },
+       { .compatible = "fsl,mpc8544-memory-controller", },
+       { .compatible = "fsl,mpc8548-memory-controller", },
+       { .compatible = "fsl,mpc8555-memory-controller", },
+       { .compatible = "fsl,mpc8560-memory-controller", },
+       { .compatible = "fsl,mpc8568-memory-controller", },
+       { .compatible = "fsl,mpc8572-memory-controller", },
        {},
 };
 
index 78b989d202a35e3d0c46b05b9267c762c5e7b6cc..d76adfea5df7c78bb6421a327f417ae3ed210fd6 100644 (file)
@@ -468,8 +468,8 @@ const char *dmi_get_system_info(int field)
 EXPORT_SYMBOL(dmi_get_system_info);
 
 /**
- *     dmi_name_in_serial -    Check if string is in the DMI product serial
- *                             information.
+ * dmi_name_in_serial - Check if string is in the DMI product serial information
+ * @str: string to check for
  */
 int dmi_name_in_serial(const char *str)
 {
@@ -585,6 +585,8 @@ EXPORT_SYMBOL_GPL(dmi_walk);
 
 /**
  * dmi_match - compare a string to the dmi field (if exists)
+ * @f: DMI field identifier
+ * @str: string to compare the DMI field to
  *
  * Returns true if the requested field equals to the str (including NULL).
  */
index 48f49d93d249d8155fbdc1973310fab28319e6f3..3d2565441b3691786c373a2ef49922aa743de737 100644 (file)
@@ -95,7 +95,7 @@ config GPIO_MAX732X
          number for these GPIOs.
 
 config GPIO_PCA953X
-       tristate "PCA953x, PCA955x, and MAX7310 I/O ports"
+       tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
        depends on I2C
        help
          Say yes here to provide access to several register-oriented
@@ -104,9 +104,10 @@ config GPIO_PCA953X
 
          4 bits:       pca9536, pca9537
 
-         8 bits:       max7310, pca9534, pca9538, pca9554, pca9557
+         8 bits:       max7310, pca9534, pca9538, pca9554, pca9557,
+                       tca6408
 
-         16 bits:      pca9535, pca9539, pca9555
+         16 bits:      pca9535, pca9539, pca9555, tca6416
 
          This driver can also be built as a module.  If so, the module
          will be called pca953x.
index 9ceeb89f1325ea776bf47c1e89fbcb5b81b8eeec..37f35388a2aeb7094b559bfde1a851159e9ae59f 100644 (file)
@@ -33,7 +33,12 @@ static const struct i2c_device_id pca953x_id[] = {
        { "pca9554", 8, },
        { "pca9555", 16, },
        { "pca9557", 8, },
+
        { "max7310", 8, },
+       { "pca6107", 8, },
+       { "tca6408", 8, },
+       { "tca6416", 16, },
+       /* NYET:  { "tca6424", 24, }, */
        { }
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
@@ -47,9 +52,6 @@ struct pca953x_chip {
        struct gpio_chip gpio_chip;
 };
 
-/* NOTE:  we can't currently rely on fault codes to come from SMBus
- * calls, so we map all errors to EIO here and return zero otherwise.
- */
 static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
 {
        int ret;
@@ -61,7 +63,7 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
 
        if (ret < 0) {
                dev_err(&chip->client->dev, "failed writing register\n");
-               return -EIO;
+               return ret;
        }
 
        return 0;
@@ -78,7 +80,7 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
 
        if (ret < 0) {
                dev_err(&chip->client->dev, "failed reading register\n");
-               return -EIO;
+               return ret;
        }
 
        *val = (uint16_t)ret;
index 37d3eec8730afe3f1a6f48b920cdb4ac3678d2aa..afad14792141116898c6291288616b23e9308a36 100644 (file)
@@ -202,37 +202,6 @@ static int twl4030_get_gpio_datain(int gpio)
        return ret;
 }
 
-/*
- * Configure debounce timing value for a GPIO pin on TWL4030
- */
-int twl4030_set_gpio_debounce(int gpio, int enable)
-{
-       u8 d_bnk = gpio >> 3;
-       u8 d_msk = BIT(gpio & 0x7);
-       u8 reg = 0;
-       u8 base = 0;
-       int ret = 0;
-
-       if (unlikely((gpio >= TWL4030_GPIO_MAX)
-               || !(gpio_usage_count & BIT(gpio))))
-               return -EPERM;
-
-       base = REG_GPIO_DEBEN1 + d_bnk;
-       mutex_lock(&gpio_lock);
-       ret = gpio_twl4030_read(base);
-       if (ret >= 0) {
-               if (enable)
-                       reg = ret | d_msk;
-               else
-                       reg = ret & ~d_msk;
-
-               ret = gpio_twl4030_write(base, reg);
-       }
-       mutex_unlock(&gpio_lock);
-       return ret;
-}
-EXPORT_SYMBOL(twl4030_set_gpio_debounce);
-
 /*----------------------------------------------------------------------*/
 
 static int twl_request(struct gpio_chip *chip, unsigned offset)
@@ -405,6 +374,23 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
                                REG_GPIOPUPDCTR1, 5);
 }
 
+static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+{
+       u8              message[4];
+
+       /* 30 msec of debouncing is always used for MMC card detect,
+        * and is optional for everything else.
+        */
+       message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+       debounce >>= 8;
+       message[2] = (debounce & 0xff);
+       debounce >>= 8;
+       message[3] = (debounce & 0x03);
+
+       return twl4030_i2c_write(TWL4030_MODULE_GPIO, message,
+                               REG_GPIO_DEBEN1, 3);
+}
+
 static int gpio_twl4030_remove(struct platform_device *pdev);
 
 static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
@@ -439,6 +425,12 @@ no_irqs:
                                pdata->pullups, pdata->pulldowns,
                                ret);
 
+       ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+       if (ret)
+               dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+                               pdata->debounce, pdata->mmc_cd,
+                               ret);
+
        twl_gpiochip.base = pdata->gpio_base;
        twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
        twl_gpiochip.dev = &pdev->dev;
index 3733e36d135ed2700e221fb6609a0b8809c481c5..b06a53715853af03df4717108106a72c1effdba5 100644 (file)
@@ -183,6 +183,10 @@ int drm_stub_open(struct inode *inode, struct file *filp)
 
        old_fops = filp->f_op;
        filp->f_op = fops_get(&dev->driver->fops);
+       if (filp->f_op == NULL) {
+               filp->f_op = old_fops;
+               goto out;
+       }
        if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
                fops_put(filp->f_op);
                filp->f_op = fops_get(old_fops);
index 66107b4dc12a23531eb7d0908f3c6f967fd9ce23..1852f27bac51fbd9a37a6abe07fe10b50b9b7a6c 100644 (file)
@@ -204,8 +204,6 @@ I2C_CLIENT_INSMOD_1(adt7462);
 #define MASK_AND_SHIFT(value, prefix)  \
        (((value) & prefix##_MASK) >> prefix##_SHIFT)
 
-#define ROUND_DIV(x, divisor)  (((x) + ((divisor) / 2)) / (divisor))
-
 struct adt7462_data {
        struct device           *hwmon_dev;
        struct attribute_group  attrs;
@@ -840,7 +838,7 @@ static ssize_t set_temp_min(struct device *dev,
        if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000) + 64;
+       temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -878,7 +876,7 @@ static ssize_t set_temp_max(struct device *dev,
        if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000) + 64;
+       temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -943,7 +941,7 @@ static ssize_t set_volt_max(struct device *dev,
                return -EINVAL;
 
        temp *= 1000; /* convert mV to uV */
-       temp = ROUND_DIV(temp, x);
+       temp = DIV_ROUND_CLOSEST(temp, x);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -985,7 +983,7 @@ static ssize_t set_volt_min(struct device *dev,
                return -EINVAL;
 
        temp *= 1000; /* convert mV to uV */
-       temp = ROUND_DIV(temp, x);
+       temp = DIV_ROUND_CLOSEST(temp, x);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -1250,7 +1248,7 @@ static ssize_t set_pwm_hyst(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 15);
 
        /* package things up */
@@ -1337,7 +1335,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000) + 64;
+       temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
index 1311a595147e17a136fbe5dbe1b81ebaa635acfe..633e1a1e9d79843f1d8feebbb276e737903b685f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/log2.h>
+#include <linux/kthread.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
@@ -74,6 +75,7 @@ I2C_CLIENT_INSMOD_1(adt7470);
 #define ADT7470_REG_PWM12_CFG                  0x68
 #define                ADT7470_PWM2_AUTO_MASK          0x40
 #define                ADT7470_PWM1_AUTO_MASK          0x80
+#define                ADT7470_PWM_AUTO_MASK           0xC0
 #define ADT7470_REG_PWM34_CFG                  0x69
 #define                ADT7470_PWM3_AUTO_MASK          0x40
 #define                ADT7470_PWM4_AUTO_MASK          0x80
@@ -128,8 +130,11 @@ I2C_CLIENT_INSMOD_1(adt7470);
 /* How often do we reread sensor limit values? (In jiffies) */
 #define LIMIT_REFRESH_INTERVAL (60 * HZ)
 
-/* sleep 1s while gathering temperature data */
-#define TEMP_COLLECTION_TIME   1000
+/* Wait at least 200ms per sensor for 10 sensors */
+#define TEMP_COLLECTION_TIME   2000
+
+/* auto update thing won't fire more than every 2s */
+#define AUTO_UPDATE_INTERVAL   2000
 
 /* datasheet says to divide this number by the fan reading to get fan rpm */
 #define FAN_PERIOD_TO_RPM(x)   ((90000 * 60) / (x))
@@ -137,8 +142,6 @@ I2C_CLIENT_INSMOD_1(adt7470);
 #define FAN_PERIOD_INVALID     65535
 #define FAN_DATA_VALID(x)      ((x) && (x) != FAN_PERIOD_INVALID)
 
-#define ROUND_DIV(x, divisor)  (((x) + ((divisor) / 2)) / (divisor))
-
 struct adt7470_data {
        struct device           *hwmon_dev;
        struct attribute_group  attrs;
@@ -148,6 +151,9 @@ struct adt7470_data {
        unsigned long           sensors_last_updated;   /* In jiffies */
        unsigned long           limits_last_updated;    /* In jiffies */
 
+       int                     num_temp_sensors;       /* -1 = probe */
+       int                     temperatures_probed;
+
        s8                      temp[ADT7470_TEMP_COUNT];
        s8                      temp_min[ADT7470_TEMP_COUNT];
        s8                      temp_max[ADT7470_TEMP_COUNT];
@@ -163,6 +169,10 @@ struct adt7470_data {
        u8                      pwm_min[ADT7470_PWM_COUNT];
        s8                      pwm_tmin[ADT7470_PWM_COUNT];
        u8                      pwm_auto_temp[ADT7470_PWM_COUNT];
+
+       struct task_struct      *auto_update;
+       struct completion       auto_update_stop;
+       unsigned int            auto_update_interval;
 };
 
 static int adt7470_probe(struct i2c_client *client,
@@ -220,40 +230,126 @@ static void adt7470_init_client(struct i2c_client *client)
        }
 }
 
-static struct adt7470_data *adt7470_update_device(struct device *dev)
+/* Probe for temperature sensors.  Assumes lock is held */
+static int adt7470_read_temperatures(struct i2c_client *client,
+                                    struct adt7470_data *data)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct adt7470_data *data = i2c_get_clientdata(client);
-       unsigned long local_jiffies = jiffies;
-       u8 cfg;
+       unsigned long res;
        int i;
+       u8 cfg, pwm[4], pwm_cfg[2];
 
-       mutex_lock(&data->lock);
-       if (time_before(local_jiffies, data->sensors_last_updated +
-               SENSOR_REFRESH_INTERVAL)
-               && data->sensors_valid)
-               goto no_sensor_update;
+       /* save pwm[1-4] config register */
+       pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0));
+       pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2));
+
+       /* set manual pwm to whatever it is set to now */
+       for (i = 0; i < ADT7470_FAN_COUNT; i++)
+               pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i));
+
+       /* put pwm in manual mode */
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0),
+               pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK));
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2),
+               pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK));
+
+       /* write pwm control to whatever it was */
+       for (i = 0; i < ADT7470_FAN_COUNT; i++)
+               i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]);
 
        /* start reading temperature sensors */
        cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
        cfg |= 0x80;
        i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
 
-       /*
-        * Delay is 200ms * number of tmp05 sensors.  Too bad
-        * there's no way to figure out how many are connected.
-        * For now, assume 1s will work.
-        */
-       msleep(TEMP_COLLECTION_TIME);
+       /* Delay is 200ms * number of temp sensors. */
+       res = msleep_interruptible((data->num_temp_sensors >= 0 ?
+                                   data->num_temp_sensors * 200 :
+                                   TEMP_COLLECTION_TIME));
 
        /* done reading temperature sensors */
        cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
        cfg &= ~0x80;
        i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
 
-       for (i = 0; i < ADT7470_TEMP_COUNT; i++)
+       /* restore pwm[1-4] config registers */
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
+
+       if (res) {
+               printk(KERN_ERR "ha ha, interrupted");
+               return -EAGAIN;
+       }
+
+       /* Only count fans if we have to */
+       if (data->num_temp_sensors >= 0)
+               return 0;
+
+       for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
                data->temp[i] = i2c_smbus_read_byte_data(client,
                                                ADT7470_TEMP_REG(i));
+               if (data->temp[i])
+                       data->num_temp_sensors = i + 1;
+       }
+       data->temperatures_probed = 1;
+       return 0;
+}
+
+static int adt7470_update_thread(void *p)
+{
+       struct i2c_client *client = p;
+       struct adt7470_data *data = i2c_get_clientdata(client);
+
+       while (!kthread_should_stop()) {
+               mutex_lock(&data->lock);
+               adt7470_read_temperatures(client, data);
+               mutex_unlock(&data->lock);
+               if (kthread_should_stop())
+                       break;
+               msleep_interruptible(data->auto_update_interval);
+       }
+
+       complete_all(&data->auto_update_stop);
+       return 0;
+}
+
+static struct adt7470_data *adt7470_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adt7470_data *data = i2c_get_clientdata(client);
+       unsigned long local_jiffies = jiffies;
+       u8 cfg;
+       int i;
+       int need_sensors = 1;
+       int need_limits = 1;
+
+       /*
+        * Figure out if we need to update the shadow registers.
+        * Lockless means that we may occasionally report out of
+        * date data.
+        */
+       if (time_before(local_jiffies, data->sensors_last_updated +
+                       SENSOR_REFRESH_INTERVAL) &&
+           data->sensors_valid)
+               need_sensors = 0;
+
+       if (time_before(local_jiffies, data->limits_last_updated +
+                       LIMIT_REFRESH_INTERVAL) &&
+           data->limits_valid)
+               need_limits = 0;
+
+       if (!need_sensors && !need_limits)
+               return data;
+
+       mutex_lock(&data->lock);
+       if (!need_sensors)
+               goto no_sensor_update;
+
+       if (!data->temperatures_probed)
+               adt7470_read_temperatures(client, data);
+       else
+               for (i = 0; i < ADT7470_TEMP_COUNT; i++)
+                       data->temp[i] = i2c_smbus_read_byte_data(client,
+                                               ADT7470_TEMP_REG(i));
 
        for (i = 0; i < ADT7470_FAN_COUNT; i++)
                data->fan[i] = adt7470_read_word_data(client,
@@ -302,9 +398,7 @@ static struct adt7470_data *adt7470_update_device(struct device *dev)
        data->sensors_valid = 1;
 
 no_sensor_update:
-       if (time_before(local_jiffies, data->limits_last_updated +
-               LIMIT_REFRESH_INTERVAL)
-               && data->limits_valid)
+       if (!need_limits)
                goto out;
 
        for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
@@ -338,6 +432,66 @@ out:
        return data;
 }
 
+static ssize_t show_auto_update_interval(struct device *dev,
+                                        struct device_attribute *devattr,
+                                        char *buf)
+{
+       struct adt7470_data *data = adt7470_update_device(dev);
+       return sprintf(buf, "%d\n", data->auto_update_interval);
+}
+
+static ssize_t set_auto_update_interval(struct device *dev,
+                                       struct device_attribute *devattr,
+                                       const char *buf,
+                                       size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adt7470_data *data = i2c_get_clientdata(client);
+       long temp;
+
+       if (strict_strtol(buf, 10, &temp))
+               return -EINVAL;
+
+       temp = SENSORS_LIMIT(temp, 0, 60000);
+
+       mutex_lock(&data->lock);
+       data->auto_update_interval = temp;
+       mutex_unlock(&data->lock);
+
+       return count;
+}
+
+static ssize_t show_num_temp_sensors(struct device *dev,
+                                    struct device_attribute *devattr,
+                                    char *buf)
+{
+       struct adt7470_data *data = adt7470_update_device(dev);
+       return sprintf(buf, "%d\n", data->num_temp_sensors);
+}
+
+static ssize_t set_num_temp_sensors(struct device *dev,
+                                   struct device_attribute *devattr,
+                                   const char *buf,
+                                   size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adt7470_data *data = i2c_get_clientdata(client);
+       long temp;
+
+       if (strict_strtol(buf, 10, &temp))
+               return -EINVAL;
+
+       temp = SENSORS_LIMIT(temp, -1, 10);
+
+       mutex_lock(&data->lock);
+       data->num_temp_sensors = temp;
+       if (temp < 0)
+               data->temperatures_probed = 0;
+       mutex_unlock(&data->lock);
+
+       return count;
+}
+
 static ssize_t show_temp_min(struct device *dev,
                             struct device_attribute *devattr,
                             char *buf)
@@ -360,7 +514,7 @@ static ssize_t set_temp_min(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -394,7 +548,7 @@ static ssize_t set_temp_max(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -671,7 +825,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -804,6 +958,10 @@ static ssize_t show_alarm(struct device *dev,
 }
 
 static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL);
+static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors,
+                  set_num_temp_sensors);
+static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO,
+                  show_auto_update_interval, set_auto_update_interval);
 
 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
                    set_temp_max, 0);
@@ -976,6 +1134,8 @@ static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
 static struct attribute *adt7470_attr[] =
 {
        &dev_attr_alarm_mask.attr,
+       &dev_attr_num_temp_sensors.attr,
+       &dev_attr_auto_update_interval.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,
@@ -1108,6 +1268,9 @@ static int adt7470_probe(struct i2c_client *client,
                goto exit;
        }
 
+       data->num_temp_sensors = -1;
+       data->auto_update_interval = AUTO_UPDATE_INTERVAL;
+
        i2c_set_clientdata(client, data);
        mutex_init(&data->lock);
 
@@ -1127,8 +1290,16 @@ static int adt7470_probe(struct i2c_client *client,
                goto exit_remove;
        }
 
+       init_completion(&data->auto_update_stop);
+       data->auto_update = kthread_run(adt7470_update_thread, client,
+                                       dev_name(data->hwmon_dev));
+       if (IS_ERR(data->auto_update))
+               goto exit_unregister;
+
        return 0;
 
+exit_unregister:
+       hwmon_device_unregister(data->hwmon_dev);
 exit_remove:
        sysfs_remove_group(&client->dev.kobj, &data->attrs);
 exit_free:
@@ -1141,6 +1312,8 @@ static int adt7470_remove(struct i2c_client *client)
 {
        struct adt7470_data *data = i2c_get_clientdata(client);
 
+       kthread_stop(data->auto_update);
+       wait_for_completion(&data->auto_update_stop);
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &data->attrs);
        kfree(data);
index 18aa30866a6c53deccb0dc5eeda470dd9b5efd1d..0a6ce2367b42ae62bf2644a30bd2b5a739be2df4 100644 (file)
@@ -129,8 +129,6 @@ I2C_CLIENT_INSMOD_1(adt7473);
 #define FAN_PERIOD_INVALID     65535
 #define FAN_DATA_VALID(x)      ((x) && (x) != FAN_PERIOD_INVALID)
 
-#define ROUND_DIV(x, divisor)  (((x) + ((divisor) / 2)) / (divisor))
-
 struct adt7473_data {
        struct device           *hwmon_dev;
        struct attribute_group  attrs;
@@ -459,7 +457,7 @@ static ssize_t set_temp_min(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = encode_temp(data->temp_twos_complement, temp);
 
        mutex_lock(&data->lock);
@@ -495,7 +493,7 @@ static ssize_t set_temp_max(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = encode_temp(data->temp_twos_complement, temp);
 
        mutex_lock(&data->lock);
@@ -720,7 +718,7 @@ static ssize_t set_temp_tmax(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = encode_temp(data->temp_twos_complement, temp);
 
        mutex_lock(&data->lock);
@@ -756,7 +754,7 @@ static ssize_t set_temp_tmin(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = encode_temp(data->temp_twos_complement, temp);
 
        mutex_lock(&data->lock);
index 086c2a5cef0bcdfeae7de4cf4fba665b6745134d..dca47a591baf325eabce346ae115ed747efd7c53 100644 (file)
@@ -131,6 +131,10 @@ static const char* temperature_sensors_sets[][36] = {
 /* Set 14: iMac 6,1 */
        { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
          "TO0P", "Tp0P", NULL },
+/* Set 15: MacBook Air 2,1 */
+       { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
+         "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
+         "Ts0S", NULL },
 };
 
 /* List of keys used to read/write fan speeds */
@@ -1301,11 +1305,17 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
        { .accelerometer = 0, .light = 0, .temperature_set = 13 },
 /* iMac 6: light sensor only, temperature set 14 */
        { .accelerometer = 0, .light = 0, .temperature_set = 14 },
+/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 15 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
  * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
 static __initdata struct dmi_system_id applesmc_whitelist[] = {
+       { applesmc_dmi_match, "Apple MacBook Air 2", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
+               &applesmc_dmi_data[15]},
        { applesmc_dmi_match, "Apple MacBook Air", {
          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
index 537d9fb2ff88b2f046bc8f1f22d95e6e606d4987..a36363312f2ff5116ef5557ae19fe7176455b68a 100644 (file)
@@ -40,7 +40,7 @@
 
 static inline u16 extract_value(const char *data, int offset)
 {
-       return be16_to_cpup((u16 *)&data[offset]);
+       return be16_to_cpup((__be16 *)&data[offset]);
 }
 
 #define TEMP_SENSOR            1
index 4ee85fcf9aaf024acff74aa94d48d1f8e5e94fcb..3f9503867e6b48da6f8c1e0718399693b5f9020b 100644 (file)
@@ -511,6 +511,13 @@ config BLK_DEV_PIIX
          This allows the kernel to change PIO, DMA and UDMA speeds and to
          configure the chip to optimum performance.
 
+config BLK_DEV_IT8172
+       tristate "IT8172 IDE support"
+       select BLK_DEV_IDEDMA_PCI
+       help
+         This driver adds support for the IDE controller on the
+         IT8172 System Controller.
+
 config BLK_DEV_IT8213
        tristate "IT8213 IDE support"
        select BLK_DEV_IDEDMA_PCI
index 410728992e6a65d72b1c4e946d7b91487481953b..c2b9c93f009511f5b6f6780f0bfd9e8199a28e7e 100644 (file)
@@ -47,6 +47,7 @@ obj-$(CONFIG_BLK_DEV_SC1200)          += sc1200.o
 obj-$(CONFIG_BLK_DEV_CY82C693)         += cy82c693.o
 obj-$(CONFIG_BLK_DEV_DELKIN)           += delkin_cb.o
 obj-$(CONFIG_BLK_DEV_HPT366)           += hpt366.o
+obj-$(CONFIG_BLK_DEV_IT8172)           += it8172.o
 obj-$(CONFIG_BLK_DEV_IT8213)           += it8213.o
 obj-$(CONFIG_BLK_DEV_IT821X)           += it821x.o
 obj-$(CONFIG_BLK_DEV_JMICRON)          += jmicron.o
index 4142c698e0d3da9fda2db897edf8228fdd8bba12..4485b9c6f0e68bc8c5b28f26652d133f54b7b1df 100644 (file)
@@ -83,7 +83,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
 
 static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        struct ide_host *host   = pci_get_drvdata(dev);
        struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
@@ -111,7 +111,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
 
 static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        struct ide_host *host   = pci_get_drvdata(dev);
        struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
index 45d2356bb7254ff1fb9f96d71e6c7e1661e4bf18..66f43083408b4762c940525b2348bde4a67c4fd3 100644 (file)
@@ -68,7 +68,7 @@ static struct pci_dev *isa_dev;
 
 static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
        int s_time = t->setup, a_time = t->active, c_time = t->cycle;
@@ -150,7 +150,7 @@ static u8 ali_udma_filter(ide_drive_t *drive)
 
 static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 speed1               = speed;
        u8 unit                 = drive->dn & 1;
@@ -198,7 +198,7 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
 static int ali15x3_dma_setup(ide_drive_t *drive)
 {
        if (m5229_revision < 0xC2 && drive->media != ide_disk) {
-               if (rq_data_dir(drive->hwif->hwgroup->rq))
+               if (rq_data_dir(drive->hwif->rq))
                        return 1;       /* try PIO instead of DMA */
        }
        return ide_dma_setup(drive);
@@ -490,8 +490,6 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
        if (ide_allocate_dma_engine(hwif))
                return -1;
 
-       hwif->dma_ops = &sff_dma_ops;
-
        return 0;
 }
 
@@ -511,6 +509,7 @@ static const struct ide_dma_ops ali_dma_ops = {
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_port_info ali15x3_chipset __devinitdata = {
@@ -519,6 +518,7 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
        .init_hwif      = init_hwif_ali15x3,
        .init_dma       = init_dma_ali15x3,
        .port_ops       = &ali_port_ops,
+       .dma_ops        = &sff_dma_ops,
        .pio_mask       = ATA_PIO5,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index c6bcd3014a29ec7891b3e11543cd6195ff30e985..69660a431cd9890f707c87d7e7a38f3429e643de 100644 (file)
@@ -82,7 +82,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+       ide_drive_t *peer = ide_get_pair_dev(drive);
        struct ide_timing t, p;
        int T, UT;
        u8 udma_mask = hwif->ultra_mask;
@@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
 
        ide_timing_compute(drive, speed, &t, T, UT);
 
-       if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+       if (peer) {
                ide_timing_compute(peer, peer->current_speed, &p, T, UT);
                ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
        }
index 0ec8fd1e4dcb3ae37d3fb98966bc936f534fa0d0..79a2dfed8eb7b600603f68b8468c4ca2e7393a43 100644 (file)
@@ -212,8 +212,8 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
 static int auide_build_dmatable(ide_drive_t *drive)
 {
        int i, iswrite, count = 0;
-       ide_hwif_t *hwif = HWIF(drive);
-       struct request *rq = HWGROUP(drive)->rq;
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq = hwif->rq;
        _auide_hwif *ahwif = &auide_hwif;
        struct scatterlist *sg;
 
@@ -286,7 +286,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
 
 static int auide_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
 
        if (hwif->sg_nents) {
                ide_destroy_dmatable(drive);
@@ -309,8 +309,8 @@ static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 }
 
 static int auide_dma_setup(ide_drive_t *drive)
-{              
-       struct request *rq = HWGROUP(drive)->rq;
+{
+       struct request *rq = drive->hwif->rq;
 
        if (!auide_build_dmatable(drive)) {
                ide_map_sg(drive, rq);
@@ -502,7 +502,6 @@ static const struct ide_tp_ops au1xxx_tp_ops = {
        .exec_command           = ide_exec_command,
        .read_status            = ide_read_status,
        .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
 
        .set_irq                = ide_set_irq,
 
index e4306647d00d6782e8db72d40d82827bb085044f..8890276fef7fbfaa3d163c9c9856421e025d11ee 100644 (file)
@@ -467,11 +467,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
         * so we merge the timings, using the slowest value for each timing.
         */
        if (index > 1) {
-               ide_hwif_t *hwif = drive->hwif;
-               ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
+               ide_drive_t *peer = ide_get_pair_dev(drive);
                unsigned int mate = index ^ 1;
 
-               if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+               if (peer) {
                        if (setup_count < setup_counts[mate])
                                setup_count = setup_counts[mate];
                        if (active_count < active_counts[mate])
index 3623bf013bcfde7a2249d743091317da7bd87bad..2f9688d87ecdc5eb192c67588bbcd51ea8094a41 100644 (file)
@@ -115,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_
  */
 static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        struct ide_timing *t    = ide_timing_find_mode(XFER_PIO_0 + pio);
        unsigned int cycle_time;
@@ -138,10 +138,12 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
         * the slowest address setup timing ourselves.
         */
        if (hwif->channel) {
-               ide_drive_t *drives = hwif->drives;
+               ide_drive_t *pair = ide_get_pair_dev(drive);
 
                drive->drive_data = setup_count;
-               setup_count = max(drives[0].drive_data, drives[1].drive_data);
+
+               if (pair)
+                       setup_count = max_t(u8, setup_count, pair->drive_data);
        }
 
        if (setup_count > 5)            /* shouldn't actually happen... */
@@ -180,7 +182,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 unit                 = drive->dn & 0x01;
        u8 regU = 0, pciU       = hwif->channel ? UDIDETCR1 : UDIDETCR0;
@@ -226,7 +228,7 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 
 static int cmd648_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        unsigned long base      = hwif->dma_base - (hwif->channel * 8);
        int err                 = ide_dma_end(drive);
        u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
@@ -242,7 +244,7 @@ static int cmd648_dma_end(ide_drive_t *drive)
 
 static int cmd64x_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
        u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
@@ -259,7 +261,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
 
 static int cmd648_dma_test_irq(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        unsigned long base      = hwif->dma_base - (hwif->channel * 8);
        u8 irq_mask             = hwif->channel ? MRDMODE_INTR_CH1 :
                                                  MRDMODE_INTR_CH0;
@@ -282,7 +284,7 @@ static int cmd648_dma_test_irq(ide_drive_t *drive)
 
 static int cmd64x_dma_test_irq(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
        u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
@@ -313,7 +315,7 @@ static int cmd64x_dma_test_irq(ide_drive_t *drive)
 
 static int cmd646_1_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        u8 dma_stat = 0, dma_cmd = 0;
 
        drive->waiting_for_dma = 0;
@@ -383,6 +385,7 @@ static const struct ide_dma_ops cmd64x_dma_ops = {
        .dma_test_irq           = cmd64x_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_dma_ops cmd646_rev1_dma_ops = {
@@ -394,6 +397,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = {
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_dma_ops cmd648_dma_ops = {
@@ -405,6 +409,7 @@ static const struct ide_dma_ops cmd648_dma_ops = {
        .dma_test_irq           = cmd648_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
index 5efb467f8fa0009fa257e9e6a41de1afa3e3f630..d003bec56ff9f51c7c5839e83e79e317b9608eac 100644 (file)
@@ -59,7 +59,7 @@ static struct pio_clocks cs5520_pio_clocks[]={
 
 static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
        int controller = drive->dn > 1 ? 1 : 0;
 
index d37baf8ecc5fd54adc2645883b93721bd72da00b..74fc5401f407cbe06bfa1ee99c48b627c1072e25 100644 (file)
@@ -203,7 +203,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
 
 static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        pio_clocks_t pclk;
        unsigned int addrCtrl;
index 39d500d84b07ee7b42fe80b22513558dad70ee50..a5ba820d69bbbeaa6dfb4e47d523599be78d7335 100644 (file)
@@ -70,7 +70,6 @@ static const struct ide_tp_ops falconide_tp_ops = {
        .exec_command           = ide_exec_command,
        .read_status            = ide_read_status,
        .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
 
        .set_irq                = ide_set_irq,
 
index b18e10d99d2e461de8560f571edb0bc77b0c9e59..3eb9b5c63a0f4a3a4c67facb6e7687a465f69936 100644 (file)
@@ -626,7 +626,7 @@ static struct hpt_info *hpt3xx_get_info(struct device *dev)
 
 static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
        u8 mask                 = hwif->ultra_mask;
 
@@ -665,7 +665,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 
 static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
 
        switch (info->chip_type) {
@@ -743,7 +743,7 @@ static void hpt3xx_quirkproc(ide_drive_t *drive)
 
 static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev  *dev    = to_pci_dev(hwif->dev);
        struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
 
@@ -788,7 +788,7 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
 
 static void hpt370_clear_engine(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
 
        pci_write_config_byte(dev, hwif->select_data, 0x37);
@@ -797,7 +797,7 @@ static void hpt370_clear_engine(ide_drive_t *drive)
 
 static void hpt370_irq_timeout(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u16 bfifo               = 0;
        u8  dma_cmd;
@@ -822,7 +822,7 @@ static void hpt370_dma_start(ide_drive_t *drive)
 
 static int hpt370_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
 
        if (dma_stat & 0x01) {
@@ -844,7 +844,7 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
 /* returns 1 if DMA IRQ issued, 0 otherwise */
 static int hpt374_dma_test_irq(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u16 bfifo               = 0;
        u8  dma_stat;
@@ -865,7 +865,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
 
 static int hpt374_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 mcr  = 0, mcr_addr   = hwif->select_data;
        u8 bwsr = 0, mask       = hwif->channel ? 0x02 : 0x01;
@@ -927,7 +927,7 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
 
 static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
 {
-       hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
+       hpt3xxn_set_clock(drive->hwif, rq_data_dir(rq) ? 0x23 : 0x21);
 }
 
 /**
@@ -1349,8 +1349,6 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
        if (ide_allocate_dma_engine(hwif))
                return -1;
 
-       hwif->dma_ops = &sff_dma_ops;
-
        return 0;
 }
 
@@ -1426,6 +1424,7 @@ static const struct ide_dma_ops hpt37x_dma_ops = {
        .dma_test_irq           = hpt374_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_dma_ops hpt370_dma_ops = {
@@ -1437,6 +1436,7 @@ static const struct ide_dma_ops hpt370_dma_ops = {
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = hpt370_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_dma_ops hpt36x_dma_ops = {
@@ -1448,6 +1448,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = hpt366_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
index 81f70caeb40f1a1394f1ec25023635e26b8a70f3..97a35c667aee73e1127052680559b5376e156dff 100644 (file)
@@ -166,7 +166,7 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
  */
 static void icside_maskproc(ide_drive_t *drive, int mask)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct expansion_card *ec = ECARD_DEV(hwif->dev);
        struct icside_state *state = ecard_get_drvdata(ec);
        unsigned long flags;
@@ -284,7 +284,7 @@ static void icside_dma_host_set(ide_drive_t *drive, int on)
 
 static int icside_dma_end(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct expansion_card *ec = ECARD_DEV(hwif->dev);
 
        drive->waiting_for_dma = 0;
@@ -299,7 +299,7 @@ static int icside_dma_end(ide_drive_t *drive)
 
 static void icside_dma_start(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct expansion_card *ec = ECARD_DEV(hwif->dev);
 
        /* We can not enable DMA on both channels simultaneously. */
@@ -309,10 +309,10 @@ static void icside_dma_start(ide_drive_t *drive)
 
 static int icside_dma_setup(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct expansion_card *ec = ECARD_DEV(hwif->dev);
        struct icside_state *state = ecard_get_drvdata(ec);
-       struct request *rq = hwif->hwgroup->rq;
+       struct request *rq = hwif->rq;
        unsigned int dma_mode;
 
        if (rq_data_dir(rq))
@@ -362,7 +362,7 @@ static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
 
 static int icside_dma_test_irq(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct expansion_card *ec = ECARD_DEV(hwif->dev);
        struct icside_state *state = ecard_get_drvdata(ec);
 
index fd4a364330507893a59e09e8fc17a4009a4d0b84..2f9e941968d6741aca594f08c639ad4afc054a3f 100644 (file)
@@ -218,7 +218,7 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
  */
 static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
 {
-       ide_hwif_t      *hwif = HWIF(drive);
+       ide_hwif_t      *hwif = drive->hwif;
        int              port;
        acpi_handle      drive_handle;
 
@@ -263,7 +263,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
        acpi_status                     status;
        struct acpi_buffer              output;
        union acpi_object               *out_obj;
-       ide_hwif_t                      *hwif = HWIF(drive);
+       ide_hwif_t                      *hwif = drive->hwif;
        struct device                   *dev = hwif->gendev.parent;
        int                             err = -ENODEV;
        int                             port;
@@ -641,7 +641,8 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
  */
 void ide_acpi_set_state(ide_hwif_t *hwif, int on)
 {
-       int unit;
+       ide_drive_t *drive;
+       int i;
 
        if (ide_noacpi || ide_noacpi_psx)
                return;
@@ -655,9 +656,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
        /* channel first and then drives for power on and verse versa for power off */
        if (on)
                acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
-       for (unit = 0; unit < MAX_DRIVES; ++unit) {
-               ide_drive_t *drive = &hwif->drives[unit];
 
+       ide_port_for_each_dev(i, drive, hwif) {
                if (!drive->acpidata->obj_handle)
                        drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
 
@@ -711,15 +711,13 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
         * for both drives, regardless whether they are connected
         * or not.
         */
-       hwif->drives[0].acpidata = &hwif->acpidata->master;
-       hwif->drives[1].acpidata = &hwif->acpidata->slave;
+       hwif->devices[0]->acpidata = &hwif->acpidata->master;
+       hwif->devices[1]->acpidata = &hwif->acpidata->slave;
 
        /*
         * Send IDENTIFY for each drive
         */
-       for (i = 0; i < MAX_DRIVES; i++) {
-               drive = &hwif->drives[i];
-
+       ide_port_for_each_dev(i, drive, hwif) {
                memset(drive->acpidata, 0, sizeof(*drive->acpidata));
 
                if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
@@ -744,9 +742,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
        ide_acpi_get_timing(hwif);
        ide_acpi_push_timing(hwif);
 
-       for (i = 0; i < MAX_DRIVES; i++) {
-               drive = &hwif->drives[i];
-
+       ide_port_for_each_dev(i, drive, hwif) {
                if (drive->dev_flags & IDE_DFLAG_PRESENT)
                        /* Execute ACPI startup code */
                        ide_acpi_exec_tfs(drive);
index e8688c0f8645858707bc439b3ec4f42dc252b153..e96c012605982754f9a55926395ad49121e5b78a 100644 (file)
@@ -243,7 +243,7 @@ EXPORT_SYMBOL_GPL(ide_retry_pc);
 
 int ide_cd_expiry(ide_drive_t *drive)
 {
-       struct request *rq = HWGROUP(drive)->rq;
+       struct request *rq = drive->hwif->rq;
        unsigned long wait = 0;
 
        debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]);
@@ -294,7 +294,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
 {
        struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
+       struct request *rq = hwif->rq;
        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        xfer_func_t *xferfunc;
        unsigned int timeout, temp;
@@ -491,7 +491,7 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
 {
        struct ide_atapi_pc *uninitialized_var(pc);
        ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
+       struct request *rq = hwif->rq;
        ide_expiry_t *expiry;
        unsigned int timeout;
        int cmd_len;
@@ -549,7 +549,10 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
        }
 
        /* Set the interrupt routine */
-       ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+       ide_set_handler(drive,
+                       (dev_is_idecd(drive) ? drive->irq_handler
+                                            : ide_pc_intr),
+                       timeout, expiry);
 
        /* Begin DMA, if necessary */
        if (dev_is_idecd(drive)) {
@@ -580,7 +583,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
 
        if (dev_is_idecd(drive)) {
                tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
-               bcount = ide_cd_get_xferlen(hwif->hwgroup->rq);
+               bcount = ide_cd_get_xferlen(hwif->rq);
                expiry = ide_cd_expiry;
                timeout = ATAPI_WAIT_PC;
 
index 1a7410f882494907b3568d0263c917a0af73d2fa..cae69372cf45c81e51bbe14b57aa08e3f3466f94 100644 (file)
@@ -239,7 +239,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
 
 static void cdrom_end_request(ide_drive_t *drive, int uptodate)
 {
-       struct request *rq = HWGROUP(drive)->rq;
+       struct request *rq = drive->hwif->rq;
        int nsectors = rq->hard_cur_sectors;
 
        ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
@@ -306,8 +306,7 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
        ide_hwif_t *hwif = drive->hwif;
-       ide_hwgroup_t *hwgroup = hwif->hwgroup;
-       struct request *rq = hwgroup->rq;
+       struct request *rq = hwif->rq;
        int stat, err, sense_key;
 
        /* check for errors */
@@ -502,7 +501,7 @@ end_request:
                blkdev_dequeue_request(rq);
                spin_unlock_irqrestore(q->queue_lock, flags);
 
-               hwgroup->rq = NULL;
+               hwif->rq = NULL;
 
                cdrom_queue_request_sense(drive, rq->sense, rq);
        } else
@@ -511,106 +510,6 @@ end_request:
        return 1;
 }
 
-static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *);
-static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-
-/*
- * Set up the device registers for transferring a packet command on DEV,
- * expecting to later transfer XFERLEN bytes.  HANDLER is the routine
- * which actually transfers the command to the drive.  If this is a
- * drq_interrupt device, this routine will arrange for HANDLER to be
- * called when the interrupt from the drive arrives.  Otherwise, HANDLER
- * will be called immediately after the drive is prepared for the transfer.
- */
-static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
-       int xferlen;
-
-       xferlen = ide_cd_get_xferlen(rq);
-
-       ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
-
-       /* FIXME: for Virtual DMA we must check harder */
-       if (drive->dma)
-               drive->dma = !hwif->dma_ops->dma_setup(drive);
-
-       /* set up the controller registers */
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
-                          xferlen, drive->dma);
-
-       if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
-               /* waiting for CDB interrupt, not DMA yet. */
-               if (drive->dma)
-                       drive->waiting_for_dma = 0;
-
-               /* packet command */
-               ide_execute_command(drive, ATA_CMD_PACKET,
-                                   cdrom_transfer_packet_command,
-                                   ATAPI_WAIT_PC, ide_cd_expiry);
-               return ide_started;
-       } else {
-               ide_execute_pkt_cmd(drive);
-
-               return cdrom_transfer_packet_command(drive);
-       }
-}
-
-/*
- * Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device
- * registers must have already been prepared by cdrom_start_packet_command.
- * HANDLER is the interrupt handler to call when the command completes or
- * there's data ready.
- */
-#define ATAPI_MIN_CDB_BYTES 12
-static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
-       int cmd_len;
-       ide_startstop_t startstop;
-
-       ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
-
-       if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
-               /*
-                * Here we should have been called after receiving an interrupt
-                * from the device.  DRQ should how be set.
-                */
-
-               /* check for errors */
-               if (cdrom_decode_status(drive, ATA_DRQ, NULL))
-                       return ide_stopped;
-
-               /* ok, next interrupt will be DMA interrupt */
-               if (drive->dma)
-                       drive->waiting_for_dma = 1;
-       } else {
-               /* otherwise, we must wait for DRQ to get set */
-               if (ide_wait_stat(&startstop, drive, ATA_DRQ,
-                                 ATA_BUSY, WAIT_READY))
-                       return startstop;
-       }
-
-       /* arm the interrupt handler */
-       ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, ide_cd_expiry);
-
-       /* ATAPI commands get padded out to 12 bytes minimum */
-       cmd_len = COMMAND_SIZE(rq->cmd[0]);
-       if (cmd_len < ATAPI_MIN_CDB_BYTES)
-               cmd_len = ATAPI_MIN_CDB_BYTES;
-
-       /* send the command to the device */
-       hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
-
-       /* start the DMA if need be */
-       if (drive->dma)
-               hwif->dma_ops->dma_start(drive);
-
-       return ide_started;
-}
-
 /*
  * Check the contents of the interrupt reason register from the cdrom
  * and attempt to recover if there are problems.  Returns  0 if everything's
@@ -854,8 +753,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       ide_hwgroup_t *hwgroup = hwif->hwgroup;
-       struct request *rq = hwgroup->rq;
+       struct request *rq = hwif->rq;
        xfer_func_t *xferfunc;
        ide_expiry_t *expiry = NULL;
        int dma_error = 0, dma, stat, thislen, uptodate = 0;
@@ -1061,7 +959,7 @@ end_request:
                if (blk_end_request(rq, 0, dlen))
                        BUG();
 
-               hwgroup->rq = NULL;
+               hwif->rq = NULL;
        } else {
                if (!uptodate)
                        rq->cmd_flags |= REQ_FAILED;
@@ -1183,7 +1081,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                return ide_stopped;
        }
 
-       return cdrom_start_packet_command(drive);
+       return ide_issue_pc(drive);
 }
 
 /*
@@ -1916,7 +1814,7 @@ static void ide_cd_release(struct kref *kref)
 
 static int ide_cd_probe(ide_drive_t *);
 
-static ide_driver_t ide_cdrom_driver = {
+static struct ide_driver ide_cdrom_driver = {
        .gen_driver = {
                .owner          = THIS_MODULE,
                .name           = "ide-cdrom",
@@ -1927,7 +1825,6 @@ static ide_driver_t ide_cdrom_driver = {
        .version                = IDECD_VERSION,
        .do_request             = ide_cd_do_request,
        .end_request            = ide_end_request,
-       .error                  = __ide_error,
 #ifdef CONFIG_IDE_PROC_FS
        .proc_entries           = ide_cd_proc_entries,
        .proc_devsets           = ide_cd_proc_devsets,
@@ -2082,6 +1979,7 @@ static int ide_cd_probe(ide_drive_t *drive)
        }
 
        drive->debug_mask = debug_mask;
+       drive->irq_handler = cdrom_newpc_intr;
 
        info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
        if (info == NULL) {
index bf676b26218129eca95bab9d676e8229e0e1fa0b..ac40d6cb90a240725ae40d661e428e27ebc36aef 100644 (file)
 
 /* Structure of a MSF cdrom address. */
 struct atapi_msf {
-       byte reserved;
-       byte minute;
-       byte second;
-       byte frame;
+       u8 reserved;
+       u8 minute;
+       u8 second;
+       u8 frame;
 };
 
 /* Space to hold the disk TOC. */
 #define MAX_TRACKS 99
 struct atapi_toc_header {
        unsigned short toc_length;
-       byte first_track;
-       byte last_track;
+       u8 first_track;
+       u8 last_track;
 };
 
 struct atapi_toc_entry {
-       byte reserved1;
+       u8 reserved1;
 #if defined(__BIG_ENDIAN_BITFIELD)
-       __u8 adr     : 4;
-       __u8 control : 4;
+       u8 adr     : 4;
+       u8 control : 4;
 #elif defined(__LITTLE_ENDIAN_BITFIELD)
-       __u8 control : 4;
-       __u8 adr     : 4;
+       u8 control : 4;
+       u8 adr     : 4;
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
-       byte track;
-       byte reserved2;
+       u8 track;
+       u8 reserved2;
        union {
                unsigned lba;
                struct atapi_msf msf;
@@