]> err.no Git - linux-2.6/commitdiff
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 00:22:43 +0000 (17:22 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 00:22:43 +0000 (17:22 -0700)
669 files changed:
Documentation/IPMI.txt
Documentation/RCU/NMI-RCU.txt [new file with mode: 0644]
Documentation/cdrom/sonycd535
Documentation/cpusets.txt
Documentation/dcdbas.txt [new file with mode: 0644]
Documentation/dell_rbu.txt [new file with mode: 0644]
Documentation/dvb/bt8xx.txt
Documentation/exception.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/relayfs.txt [new file with mode: 0644]
Documentation/i386/boot.txt
Documentation/kernel-parameters.txt
Documentation/power/swsusp.txt
Documentation/power/video.txt
Documentation/sonypi.txt
MAINTAINERS
arch/alpha/Kconfig
arch/alpha/kernel/time.c
arch/arm/Kconfig
arch/arm/boot/compressed/head-sharpsl.S
arch/arm/configs/omap_h2_1610_defconfig
arch/arm/kernel/time.c
arch/arm/mach-footbridge/Kconfig
arch/arm/mach-iop3xx/iop321-time.c
arch/arm/mach-iop3xx/iop331-time.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-omap1/irq.c
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/corgi_lcd.c [new file with mode: 0644]
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/mach-anubis.c [new file with mode: 0644]
arch/arm/mach-s3c2410/pm-simtec.c
arch/arm/mach-s3c2410/time.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c [new file with mode: 0644]
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/mux.c
arch/arm/plat-omap/ocpi.c
arch/arm/plat-omap/pm.c
arch/arm/plat-omap/sleep.S
arch/arm/plat-omap/sram-fn.S [new file with mode: 0644]
arch/arm/plat-omap/sram.c [new file with mode: 0644]
arch/arm/plat-omap/sram.h [new file with mode: 0644]
arch/arm/plat-omap/usb.c
arch/arm26/Kconfig
arch/arm26/Makefile
arch/arm26/kernel/time.c
arch/cris/arch-v10/kernel/time.c
arch/cris/kernel/time.c
arch/frv/kernel/time.c
arch/h8300/kernel/time.c
arch/i386/Kconfig
arch/i386/boot/setup.S
arch/i386/boot/tools/build.c
arch/i386/kernel/dmi_scan.c
arch/i386/kernel/entry.S
arch/i386/kernel/io_apic.c
arch/i386/kernel/kprobes.c
arch/i386/kernel/nmi.c
arch/i386/kernel/setup.c
arch/i386/kernel/time.c
arch/i386/kernel/timers/timer_hpet.c
arch/i386/kernel/traps.c
arch/i386/kernel/vmlinux.lds.S
arch/i386/mach-default/topology.c
arch/i386/mm/discontig.c
arch/i386/mm/fault.c
arch/i386/mm/init.c
arch/i386/oprofile/init.c
arch/i386/oprofile/nmi_int.c
arch/i386/oprofile/nmi_timer_int.c
arch/ia64/Kconfig
arch/ia64/hp/sim/simserial.c
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/Makefile
arch/ia64/kernel/domain.c [deleted file]
arch/ia64/kernel/irq.c
arch/ia64/kernel/jprobes.S
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/traps.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/lib/flush.S
arch/ia64/mm/fault.c
arch/ia64/sn/kernel/io_init.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/sn/pci/tioca_provider.c
arch/m32r/kernel/time.c
arch/m68k/Kconfig
arch/m68k/bvme6000/rtc.c
arch/m68k/kernel/time.c
arch/m68k/mvme16x/rtc.c
arch/m68knommu/kernel/time.c
arch/mips/Kconfig
arch/mips/kernel/linux32.c
arch/mips/kernel/sysirix.c
arch/mips/kernel/time.c
arch/mips/sgi-ip27/ip27-timer.c
arch/parisc/Kconfig
arch/parisc/kernel/time.c
arch/ppc/Kconfig
arch/ppc/kernel/time.c
arch/ppc/syslib/ocp.c
arch/ppc64/Kconfig
arch/ppc64/Makefile
arch/ppc64/kernel/kprobes.c
arch/ppc64/kernel/misc.S
arch/ppc64/kernel/pSeries_reconfig.c
arch/ppc64/kernel/sys_ppc32.c
arch/ppc64/kernel/time.c
arch/ppc64/kernel/traps.c
arch/ppc64/kernel/vmlinux.lds.S
arch/ppc64/mm/fault.c
arch/s390/kernel/time.c
arch/sh/Kconfig
arch/sh/kernel/time.c
arch/sh64/kernel/time.c
arch/sparc/Kconfig
arch/sparc/kernel/pcic.c
arch/sparc/kernel/time.c
arch/sparc64/Kconfig
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/sunos_ioctl32.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/time.c
arch/sparc64/kernel/vmlinux.lds.S
arch/sparc64/mm/fault.c
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
arch/um/Makefile-i386
arch/um/include/common-offsets.h
arch/um/include/um_uaccess.h
arch/um/kernel/mem.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/elf_aux.c
arch/um/sys-i386/kernel-offsets.c
arch/um/sys-x86_64/kernel-offsets.c
arch/v850/kernel/time.c
arch/x86_64/Kconfig
arch/x86_64/boot/setup.S
arch/x86_64/boot/tools/build.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/genapic.c
arch/x86_64/kernel/genapic_cluster.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/kprobes.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/mm/fault.c
arch/x86_64/mm/numa.c
arch/xtensa/kernel/time.c
crypto/cipher.c
drivers/base/firmware_class.c
drivers/block/Kconfig
drivers/block/aoe/aoedev.c
drivers/block/cfq-iosched.c
drivers/block/deadline-iosched.c
drivers/block/genhd.c
drivers/block/ll_rw_blk.c
drivers/char/Kconfig
drivers/char/digi1.h
drivers/char/digiFep1.h
drivers/char/epca.c
drivers/char/epca.h
drivers/char/hpet.c
drivers/char/ipmi/ipmi_bt_sm.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_kcs_sm.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_smic_sm.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/mbcs.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/sonypi.c
drivers/char/tpm/tpm_atmel.c
drivers/char/tty_io.c
drivers/char/vt.c
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/dcdbas.c [new file with mode: 0644]
drivers/firmware/dcdbas.h [new file with mode: 0644]
drivers/firmware/dell_rbu.c [new file with mode: 0644]
drivers/i2c/chips/isp1301_omap.c
drivers/ieee1394/nodemgr.c
drivers/infiniband/core/sysfs.c
drivers/input/evdev.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/fm801-gp.c
drivers/input/gameport/ns558.c
drivers/input/input.c
drivers/input/joystick/a3d.c
drivers/input/joystick/adi.c
drivers/input/joystick/analog.c
drivers/input/joystick/cobra.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip.c
drivers/input/joystick/grip_mp.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/interact.c
drivers/input/joystick/sidewinder.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/turbografx.c
drivers/input/keyboard/corgikbd.c
drivers/input/mouse/psmouse-base.c
drivers/input/serio/serport.c
drivers/input/touchscreen/corgi_ts.c
drivers/isdn/hisax/hisax.h
drivers/isdn/i4l/isdn_v110.c
drivers/md/dm-io.c
drivers/md/dm.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/video/Makefile
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/bt819.c
drivers/media/video/bt856.c
drivers/media/video/indycam.c [new file with mode: 0644]
drivers/media/video/indycam.h [new file with mode: 0644]
drivers/media/video/meye.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa7185.c
drivers/media/video/saa7191.c [new file with mode: 0644]
drivers/media/video/saa7191.h [new file with mode: 0644]
drivers/media/video/vino.c
drivers/media/video/vino.h
drivers/misc/Kconfig
drivers/misc/ibmasm/uart.c
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
drivers/mmc/mmc_sysfs.c
drivers/mmc/pxamci.c
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
drivers/mtd/nand/nand_base.c
drivers/net/3c59x.c
drivers/net/arcnet/arcnet.c
drivers/net/hamachi.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/smsc-ircc2.h
drivers/net/s2io.c
drivers/net/smc91x.h
drivers/parport/parport_pc.c
drivers/pci/msi.c
drivers/pci/msi.h
drivers/pcmcia/topic.h
drivers/pcmcia/yenta_socket.c
drivers/pcmcia/yenta_socket.h
drivers/pnp/card.c
drivers/pnp/driver.c
drivers/pnp/isapnp/core.c
drivers/pnp/manager.c
drivers/pnp/pnpacpi/core.c
drivers/pnp/pnpacpi/pnpacpi.h
drivers/pnp/pnpacpi/rsparser.c
drivers/pnp/pnpbios/core.c
drivers/pnp/pnpbios/pnpbios.h
drivers/pnp/pnpbios/proc.c
drivers/pnp/pnpbios/rsparser.c
drivers/pnp/quirks.c
drivers/pnp/support.c
drivers/scsi/NCR5380.c
drivers/scsi/NCR53c406a.c
drivers/scsi/sata_qstor.c
drivers/serial/68328serial.c
drivers/serial/68360serial.c
drivers/serial/crisv10.c
drivers/serial/icom.c
drivers/serial/mcfserial.c
drivers/serial/serial_lh7a40x.c
drivers/usb/atm/usbatm.c
drivers/usb/core/hcd.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/input/acecad.c
drivers/usb/input/itmtouch.c
drivers/usb/input/pid.c
drivers/video/backlight/Makefile
drivers/video/backlight/locomolcd.c [new file with mode: 0644]
drivers/video/q40fb.c
drivers/video/w100fb.c
drivers/video/w100fb.h
fs/Kconfig
fs/Makefile
fs/bio.c
fs/buffer.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/compat.c
fs/cramfs/inode.c
fs/ext2/super.c
fs/ext3/super.c
fs/fat/dir.c
fs/file_table.c
fs/freevxfs/vxfs_super.c
fs/hfs/bnode.c
fs/hfs/catalog.c
fs/hfs/dir.c
fs/hfs/hfs.h
fs/hfs/hfs_fs.h
fs/hfs/inode.c
fs/hfs/mdb.c
fs/hfs/super.c
fs/hfs/trans.c
fs/hfsplus/bnode.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/options.c
fs/hfsplus/super.c
fs/hostfs/hostfs.h
fs/inode.c
fs/inotify.c
fs/jbd/checkpoint.c
fs/jbd/commit.c
fs/jbd/journal.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jffs/inode-v23.c
fs/jffs2/file.c
fs/jfs/jfs_filsys.h
fs/jfs/super.c
fs/namei.c
fs/namespace.c
fs/nfsd/export.c
fs/nfsd/nfs4idmap.c
fs/open.c
fs/pipe.c
fs/proc/base.c
fs/proc/generic.c
fs/read_write.c
fs/reiserfs/journal.c
fs/relayfs/Makefile [new file with mode: 0644]
fs/relayfs/buffers.c [new file with mode: 0644]
fs/relayfs/buffers.h [new file with mode: 0644]
fs/relayfs/inode.c [new file with mode: 0644]
fs/relayfs/relay.c [new file with mode: 0644]
fs/relayfs/relay.h [new file with mode: 0644]
fs/ufs/balloc.c
fs/ufs/ialloc.c
fs/ufs/truncate.c
fs/umsdos/notes [deleted file]
fs/xattr.c
include/asm-alpha/auxvec.h [new file with mode: 0644]
include/asm-alpha/elf.h
include/asm-alpha/fcntl.h
include/asm-alpha/futex.h [new file with mode: 0644]
include/asm-alpha/hdreg.h [deleted file]
include/asm-alpha/uaccess.h
include/asm-arm/arch-omap/board-h4.h
include/asm-arm/arch-omap/board-innovator.h
include/asm-arm/arch-omap/board-perseus2.h
include/asm-arm/arch-omap/board-voiceblue.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/cpu.h
include/asm-arm/arch-omap/debug-macro.S
include/asm-arm/arch-omap/dma.h
include/asm-arm/arch-omap/dmtimer.h [new file with mode: 0644]
include/asm-arm/arch-omap/dsp.h [new file with mode: 0644]
include/asm-arm/arch-omap/dsp_common.h [new file with mode: 0644]
include/asm-arm/arch-omap/entry-macro.S
include/asm-arm/arch-omap/gpio.h
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-omap/mtd-xip.h [new file with mode: 0644]
include/asm-arm/arch-omap/mux.h
include/asm-arm/arch-omap/omap1510.h
include/asm-arm/arch-omap/omap16xx.h
include/asm-arm/arch-omap/omap24xx.h [new file with mode: 0644]
include/asm-arm/arch-omap/omap730.h
include/asm-arm/arch-omap/pm.h
include/asm-arm/arch-omap/serial.h [new file with mode: 0644]
include/asm-arm/arch-omap/uncompress.h
include/asm-arm/arch-pxa/corgi.h
include/asm-arm/arch-pxa/mmc.h
include/asm-arm/arch-s3c2410/anubis-cpld.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/anubis-irq.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/anubis-map.h [new file with mode: 0644]
include/asm-arm/auxvec.h [new file with mode: 0644]
include/asm-arm/fcntl.h
include/asm-arm/futex.h [new file with mode: 0644]
include/asm-arm/hdreg.h [deleted file]
include/asm-arm/uaccess.h
include/asm-arm26/auxvec.h [new file with mode: 0644]
include/asm-arm26/fcntl.h
include/asm-arm26/futex.h [new file with mode: 0644]
include/asm-arm26/hdreg.h [deleted file]
include/asm-arm26/uaccess.h
include/asm-cris/auxvec.h [new file with mode: 0644]
include/asm-cris/fcntl.h
include/asm-cris/futex.h [new file with mode: 0644]
include/asm-cris/irq.h
include/asm-cris/uaccess.h
include/asm-frv/auxvec.h [new file with mode: 0644]
include/asm-frv/fcntl.h
include/asm-frv/futex.h [new file with mode: 0644]
include/asm-frv/uaccess.h
include/asm-generic/fcntl.h [new file with mode: 0644]
include/asm-generic/hdreg.h [deleted file]
include/asm-generic/sections.h
include/asm-generic/unaligned.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/auxvec.h [new file with mode: 0644]
include/asm-h8300/fcntl.h
include/asm-h8300/futex.h [new file with mode: 0644]
include/asm-h8300/hdreg.h [deleted file]
include/asm-h8300/uaccess.h
include/asm-i386/auxvec.h [new file with mode: 0644]
include/asm-i386/elf.h
include/asm-i386/fcntl.h
include/asm-i386/futex.h [new file with mode: 0644]
include/asm-i386/hdreg.h [deleted file]
include/asm-i386/uaccess.h
include/asm-ia64/auxvec.h [new file with mode: 0644]
include/asm-ia64/compat.h
include/asm-ia64/elf.h
include/asm-ia64/fcntl.h
include/asm-ia64/futex.h [new file with mode: 0644]
include/asm-ia64/hdreg.h [deleted file]
include/asm-ia64/hw_irq.h
include/asm-ia64/irq.h
include/asm-ia64/kprobes.h
include/asm-ia64/processor.h
include/asm-ia64/topology.h
include/asm-ia64/uaccess.h
include/asm-m32r/auxvec.h [new file with mode: 0644]
include/asm-m32r/fcntl.h
include/asm-m32r/futex.h [new file with mode: 0644]
include/asm-m32r/hdreg.h [deleted file]
include/asm-m32r/uaccess.h
include/asm-m68k/auxvec.h [new file with mode: 0644]
include/asm-m68k/fcntl.h
include/asm-m68k/futex.h [new file with mode: 0644]
include/asm-m68k/hdreg.h [deleted file]
include/asm-m68k/uaccess.h
include/asm-m68knommu/auxvec.h [new file with mode: 0644]
include/asm-m68knommu/futex.h [new file with mode: 0644]
include/asm-m68knommu/hdreg.h [deleted file]
include/asm-m68knommu/uaccess.h
include/asm-mips/auxvec.h [new file with mode: 0644]
include/asm-mips/compat.h
include/asm-mips/fcntl.h
include/asm-mips/futex.h [new file with mode: 0644]
include/asm-mips/hdreg.h [deleted file]
include/asm-mips/uaccess.h
include/asm-parisc/auxvec.h [new file with mode: 0644]
include/asm-parisc/compat.h
include/asm-parisc/fcntl.h
include/asm-parisc/futex.h [new file with mode: 0644]
include/asm-parisc/hdreg.h [deleted file]
include/asm-parisc/irq.h
include/asm-parisc/uaccess.h
include/asm-powerpc/fcntl.h [new file with mode: 0644]
include/asm-ppc/auxvec.h [new file with mode: 0644]
include/asm-ppc/elf.h
include/asm-ppc/fcntl.h [deleted file]
include/asm-ppc/futex.h [new file with mode: 0644]
include/asm-ppc/ibm_ocp.h
include/asm-ppc/irq.h
include/asm-ppc/uaccess.h
include/asm-ppc64/auxvec.h [new file with mode: 0644]
include/asm-ppc64/compat.h
include/asm-ppc64/elf.h
include/asm-ppc64/fcntl.h [deleted file]
include/asm-ppc64/futex.h [new file with mode: 0644]
include/asm-ppc64/irq.h
include/asm-ppc64/kprobes.h
include/asm-ppc64/memory.h
include/asm-ppc64/processor.h
include/asm-ppc64/uaccess.h
include/asm-s390/auxvec.h [new file with mode: 0644]
include/asm-s390/compat.h
include/asm-s390/fcntl.h
include/asm-s390/futex.h [new file with mode: 0644]
include/asm-s390/uaccess.h
include/asm-sh/auxvec.h [new file with mode: 0644]
include/asm-sh/fcntl.h
include/asm-sh/futex.h [new file with mode: 0644]
include/asm-sh/hdreg.h [deleted file]
include/asm-sh/uaccess.h
include/asm-sh64/auxvec.h [new file with mode: 0644]
include/asm-sh64/fcntl.h
include/asm-sh64/futex.h [new file with mode: 0644]
include/asm-sh64/hdreg.h [deleted file]
include/asm-sh64/uaccess.h
include/asm-sparc/auxvec.h [new file with mode: 0644]
include/asm-sparc/fcntl.h
include/asm-sparc/futex.h [new file with mode: 0644]
include/asm-sparc/hdreg.h [deleted file]
include/asm-sparc/uaccess.h
include/asm-sparc64/auxvec.h [new file with mode: 0644]
include/asm-sparc64/compat.h
include/asm-sparc64/fcntl.h
include/asm-sparc64/futex.h [new file with mode: 0644]
include/asm-sparc64/hdreg.h [deleted file]
include/asm-sparc64/uaccess.h
include/asm-um/auxvec.h [new file with mode: 0644]
include/asm-um/futex.h [new file with mode: 0644]
include/asm-um/hdreg.h [deleted file]
include/asm-v850/auxvec.h [new file with mode: 0644]
include/asm-v850/fcntl.h
include/asm-v850/futex.h [new file with mode: 0644]
include/asm-v850/uaccess.h
include/asm-x86_64/auxvec.h [new file with mode: 0644]
include/asm-x86_64/compat.h
include/asm-x86_64/fcntl.h
include/asm-x86_64/futex.h [new file with mode: 0644]
include/asm-x86_64/hdreg.h [deleted file]
include/asm-x86_64/processor.h
include/asm-x86_64/uaccess.h
include/asm-xtensa/auxvec.h [new file with mode: 0644]
include/asm-xtensa/fcntl.h
include/asm-xtensa/hdreg.h [deleted file]
include/linux/auxvec.h [new file with mode: 0644]
include/linux/bio.h
include/linux/compat.h
include/linux/cpuset.h
include/linux/dcache.h
include/linux/dmi.h
include/linux/elf.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/firmware.h
include/linux/fs.h
include/linux/futex.h
include/linux/gfp.h
include/linux/inotify.h
include/linux/input.h
include/linux/ioctl32.h
include/linux/ipmi.h
include/linux/irq.h
include/linux/isdn.h
include/linux/jbd.h
include/linux/kprobes.h
include/linux/linkage.h
include/linux/mmc/card.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/protocol.h
include/linux/msg.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_core.h
include/linux/netfilter_ipv4/ip_nat_rule.h
include/linux/pipe_fs_i.h
include/linux/pnp.h
include/linux/ptrace.h
include/linux/relayfs_fs.h [new file with mode: 0644]
include/linux/sched.h
include/linux/sem.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/sonypi.h
include/linux/sunrpc/cache.h
include/linux/sysctl.h
include/linux/time.h
include/linux/timex.h
include/linux/topology.h
include/net/ax25.h
include/sound/core.h
include/video/w100fb.h
init/main.c
ipc/compat.c
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/Makefile
kernel/acct.c
kernel/cpuset.c
kernel/futex.c
kernel/intermodule.c
kernel/irq/handle.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/kprobes.c
kernel/module.c
kernel/params.c
kernel/posix-timers.c
kernel/power/Kconfig
kernel/power/pm.c
kernel/power/swsusp.c
kernel/printk.c
kernel/ptrace.c
kernel/resource.c
kernel/sched.c
kernel/signal.c
kernel/softlockup.c [new file with mode: 0644]
kernel/sys.c
kernel/timer.c
kernel/workqueue.c
lib/Kconfig.debug
lib/radix-tree.c
mm/mmap.c
mm/oom_kill.c
mm/page_alloc.c
mm/readahead.c
mm/shmem.c
mm/slab.c
mm/vmscan.c
net/ax25/af_ax25.c
net/ax25/ax25_addr.c
net/ax25/ax25_route.c
net/ax25/ax25_uid.c
net/core/sock.c
net/ipv4/ip_fragment.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ip_conntrack_amanda.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_ftp.c
net/ipv4/netfilter/ip_conntrack_irc.c
net/ipv4/netfilter/ip_conntrack_netbios_ns.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_conntrack_tftp.c
net/ipv4/netfilter/ip_nat_rule.c
net/ipv4/netfilter/ip_nat_standalone.c
net/netfilter/nfnetlink_queue.c
net/netlink/af_netlink.c
net/netrom/af_netrom.c
net/netrom/nr_route.c
net/packet/af_packet.c
net/rose/af_rose.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/socket.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/stats.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
scripts/kallsyms.c
scripts/ver_linux
sound/arm/Makefile
sound/arm/aaci.c
sound/arm/aaci.h
sound/core/memory.c
sound/isa/Kconfig
sound/oss/os.h
sound/pci/ali5451/ali5451.c

index 84d3d4d10c175943a86f12bd735694be19529eb7..bf1cf98d2a275b878d9e32378028b52d01ae8048 100644 (file)
@@ -605,12 +605,13 @@ is in the ipmi_poweroff module.  When the system requests a powerdown,
 it will send the proper IPMI commands to do this.  This is supported on
 several platforms.
 
-There is a module parameter named "poweroff_control" that may either be zero
-(do a power down) or 2 (do a power cycle, power the system off, then power
-it on in a few seconds).  Setting ipmi_poweroff.poweroff_control=x will do
-the same thing on the kernel command line.  The parameter is also available
-via the proc filesystem in /proc/ipmi/poweroff_control.  Note that if the
-system does not support power cycling, it will always to the power off.
+There is a module parameter named "poweroff_powercycle" that may
+either be zero (do a power down) or non-zero (do a power cycle, power
+the system off, then power it on in a few seconds).  Setting
+ipmi_poweroff.poweroff_control=x will do the same thing on the kernel
+command line.  The parameter is also available via the proc filesystem
+in /proc/sys/dev/ipmi/poweroff_powercycle.  Note that if the system
+does not support power cycling, it will always do the power off.
 
 Note that if you have ACPI enabled, the system will prefer using ACPI to
 power off.
diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt
new file mode 100644 (file)
index 0000000..d0634a5
--- /dev/null
@@ -0,0 +1,112 @@
+Using RCU to Protect Dynamic NMI Handlers
+
+
+Although RCU is usually used to protect read-mostly data structures,
+it is possible to use RCU to provide dynamic non-maskable interrupt
+handlers, as well as dynamic irq handlers.  This document describes
+how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
+work in "arch/i386/oprofile/nmi_timer_int.c" and in
+"arch/i386/kernel/traps.c".
+
+The relevant pieces of code are listed below, each followed by a
+brief explanation.
+
+       static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
+       {
+               return 0;
+       }
+
+The dummy_nmi_callback() function is a "dummy" NMI handler that does
+nothing, but returns zero, thus saying that it did nothing, allowing
+the NMI handler to take the default machine-specific action.
+
+       static nmi_callback_t nmi_callback = dummy_nmi_callback;
+
+This nmi_callback variable is a global function pointer to the current
+NMI handler.
+
+       fastcall void do_nmi(struct pt_regs * regs, long error_code)
+       {
+               int cpu;
+
+               nmi_enter();
+
+               cpu = smp_processor_id();
+               ++nmi_count(cpu);
+
+               if (!rcu_dereference(nmi_callback)(regs, cpu))
+                       default_do_nmi(regs);
+
+               nmi_exit();
+       }
+
+The do_nmi() function processes each NMI.  It first disables preemption
+in the same way that a hardware irq would, then increments the per-CPU
+count of NMIs.  It then invokes the NMI handler stored in the nmi_callback
+function pointer.  If this handler returns zero, do_nmi() invokes the
+default_do_nmi() function to handle a machine-specific NMI.  Finally,
+preemption is restored.
+
+Strictly speaking, rcu_dereference() is not needed, since this code runs
+only on i386, which does not need rcu_dereference() anyway.  However,
+it is a good documentation aid, particularly for anyone attempting to
+do something similar on Alpha.
+
+Quick Quiz:  Why might the rcu_dereference() be necessary on Alpha,
+            given that the code referenced by the pointer is read-only?
+
+
+Back to the discussion of NMI and RCU...
+
+       void set_nmi_callback(nmi_callback_t callback)
+       {
+               rcu_assign_pointer(nmi_callback, callback);
+       }
+
+The set_nmi_callback() function registers an NMI handler.  Note that any
+data that is to be used by the callback must be initialized up -before-
+the call to set_nmi_callback().  On architectures that do not order
+writes, the rcu_assign_pointer() ensures that the NMI handler sees the
+initialized values.
+
+       void unset_nmi_callback(void)
+       {
+               rcu_assign_pointer(nmi_callback, dummy_nmi_callback);
+       }
+
+This function unregisters an NMI handler, restoring the original
+dummy_nmi_handler().  However, there may well be an NMI handler
+currently executing on some other CPU.  We therefore cannot free
+up any data structures used by the old NMI handler until execution
+of it completes on all other CPUs.
+
+One way to accomplish this is via synchronize_sched(), perhaps as
+follows:
+
+       unset_nmi_callback();
+       synchronize_sched();
+       kfree(my_nmi_data);
+
+This works because synchronize_sched() blocks until all CPUs complete
+any preemption-disabled segments of code that they were executing.
+Since NMI handlers disable preemption, synchronize_sched() is guaranteed
+not to return until all ongoing NMI handlers exit.  It is therefore safe
+to free up the handler's data as soon as synchronize_sched() returns.
+
+
+Answer to Quick Quiz
+
+       Why might the rcu_dereference() be necessary on Alpha, given
+       that the code referenced by the pointer is read-only?
+
+       Answer: The caller to set_nmi_callback() might well have
+               initialized some data that is to be used by the
+               new NMI handler.  In this case, the rcu_dereference()
+               would be needed, because otherwise a CPU that received
+               an NMI just after the new handler was set might see
+               the pointer to the new NMI handler, but the old
+               pre-initialized version of the handler's data.
+
+               More important, the rcu_dereference() makes it clear
+               to someone reading the code that the pointer is being
+               protected by RCU.
index 59581a4b302af8573bfb31487ecaff50ff292905..b81e109970aa837d66e01d298c76c1f5e298c6f5 100644 (file)
@@ -68,7 +68,8 @@ it a better device citizen.  Further thanks to Joel Katz
 Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
 to make the driver work with the older CDU-510/515 series, and
 Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
-the verify_area() checks were ignoring the results of said checks.
+the verify_area() checks were ignoring the results of said checks
+(note: verify_area() has since been replaced by access_ok()).
 
 (Acknowledgments from Ron Jeppesen in the 0.3 release:)
 Thanks to Corey Minyard who wrote the original CDU-31A driver on which
index ad944c06031294cc35265d82ecf2a8fcc12586de..47f4114fbf545459efbdad232392d93357eb6968 100644 (file)
@@ -60,6 +60,18 @@ all of the cpus in the system. This removes any overhead due to
 load balancing code trying to pull tasks outside of the cpu exclusive
 cpuset only to be prevented by the tasks' cpus_allowed mask.
 
+A cpuset that is mem_exclusive restricts kernel allocations for
+page, buffer and other data commonly shared by the kernel across
+multiple users.  All cpusets, whether mem_exclusive or not, restrict
+allocations of memory for user space.  This enables configuring a
+system so that several independent jobs can share common kernel
+data, such as file system pages, while isolating each jobs user
+allocation in its own cpuset.  To do this, construct a large
+mem_exclusive cpuset to hold all the jobs, and construct child,
+non-mem_exclusive cpusets for each individual job.  Only a small
+amount of typical kernel memory, such as requests from interrupt
+handlers, is allowed to be taken outside even a mem_exclusive cpuset.
+
 User level code may create and destroy cpusets by name in the cpuset
 virtual file system, manage the attributes and permissions of these
 cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
diff --git a/Documentation/dcdbas.txt b/Documentation/dcdbas.txt
new file mode 100644 (file)
index 0000000..e1c52e2
--- /dev/null
@@ -0,0 +1,91 @@
+Overview
+
+The Dell Systems Management Base Driver provides a sysfs interface for
+systems management software such as Dell OpenManage to perform system
+management interrupts and host control actions (system power cycle or
+power off after OS shutdown) on certain Dell systems.
+
+Dell OpenManage requires this driver on the following Dell PowerEdge systems:
+300, 1300, 1400, 400SC, 500SC, 1500SC, 1550, 600SC, 1600SC, 650, 1655MC,
+700, and 750.  Other Dell software such as the open source libsmbios project
+is expected to make use of this driver, and it may include the use of this
+driver on other Dell systems.
+
+The Dell libsmbios project aims towards providing access to as much BIOS
+information as possible.  See http://linux.dell.com/libsmbios/main/ for
+more information about the libsmbios project.
+
+
+System Management Interrupt
+
+On some Dell systems, systems management software must access certain
+management information via a system management interrupt (SMI).  The SMI data
+buffer must reside in 32-bit address space, and the physical address of the
+buffer is required for the SMI.  The driver maintains the memory required for
+the SMI and provides a way for the application to generate the SMI.
+The driver creates the following sysfs entries for systems management
+software to perform these system management interrupts:
+
+/sys/devices/platform/dcdbas/smi_data
+/sys/devices/platform/dcdbas/smi_data_buf_phys_addr
+/sys/devices/platform/dcdbas/smi_data_buf_size
+/sys/devices/platform/dcdbas/smi_request
+
+Systems management software must perform the following steps to execute
+a SMI using this driver:
+
+1) Lock smi_data.
+2) Write system management command to smi_data.
+3) Write "1" to smi_request to generate a calling interface SMI or
+   "2" to generate a raw SMI.
+4) Read system management command response from smi_data.
+5) Unlock smi_data.
+
+
+Host Control Action
+
+Dell OpenManage supports a host control feature that allows the administrator
+to perform a power cycle or power off of the system after the OS has finished
+shutting down.  On some Dell systems, this host control feature requires that
+a driver perform a SMI after the OS has finished shutting down.
+
+The driver creates the following sysfs entries for systems management software
+to schedule the driver to perform a power cycle or power off host control
+action after the system has finished shutting down:
+
+/sys/devices/platform/dcdbas/host_control_action
+/sys/devices/platform/dcdbas/host_control_smi_type
+/sys/devices/platform/dcdbas/host_control_on_shutdown
+
+Dell OpenManage performs the following steps to execute a power cycle or
+power off host control action using this driver:
+
+1) Write host control action to be performed to host_control_action.
+2) Write type of SMI that driver needs to perform to host_control_smi_type.
+3) Write "1" to host_control_on_shutdown to enable host control action.
+4) Initiate OS shutdown.
+   (Driver will perform host control SMI when it is notified that the OS
+   has finished shutting down.)
+
+
+Host Control SMI Type
+
+The following table shows the value to write to host_control_smi_type to
+perform a power cycle or power off host control action:
+
+PowerEdge System    Host Control SMI Type
+----------------    ---------------------
+      300             HC_SMITYPE_TYPE1
+     1300             HC_SMITYPE_TYPE1
+     1400             HC_SMITYPE_TYPE2
+      500SC           HC_SMITYPE_TYPE2
+     1500SC           HC_SMITYPE_TYPE2
+     1550             HC_SMITYPE_TYPE2
+      600SC           HC_SMITYPE_TYPE2
+     1600SC           HC_SMITYPE_TYPE2
+      650             HC_SMITYPE_TYPE2
+     1655MC           HC_SMITYPE_TYPE2
+      700             HC_SMITYPE_TYPE3
+      750             HC_SMITYPE_TYPE3
+
+
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
new file mode 100644 (file)
index 0000000..bcfa5c3
--- /dev/null
@@ -0,0 +1,74 @@
+Purpose:
+Demonstrate the usage of the new open sourced rbu (Remote BIOS Update) driver
+for updating BIOS images on Dell servers and desktops.
+
+Scope:
+This document discusses the functionality of the rbu driver only.
+It does not cover the support needed from aplications to enable the BIOS to
+update itself with the image downloaded in to the memory.
+
+Overview:
+This driver works with Dell OpenManage or Dell Update Packages for updating
+the BIOS on Dell servers (starting from servers sold since 1999), desktops
+and notebooks (starting from those sold in 2005).
+Please go to  http://support.dell.com register and you can find info on
+OpenManage and Dell Update packages (DUP).
+
+Dell_RBU driver supports BIOS update using the monilothic image and packetized
+image methods. In case of moniolithic the driver allocates a contiguous chunk
+of physical pages having the BIOS image. In case of packetized the app
+using the driver breaks the image in to packets of fixed sizes and the driver
+would place each packet in contiguous physical memory. The driver also
+maintains a link list of packets for reading them back.
+If the dell_rbu driver is unloaded all the allocated memory is freed.
+
+The rbu driver needs to have an application which will inform the BIOS to
+enable the update in the next system reboot.
+
+The user should not unload the rbu driver after downloading the BIOS image
+or updating.
+
+The driver load creates the following directories under the /sys file system.
+/sys/class/firmware/dell_rbu/loading
+/sys/class/firmware/dell_rbu/data
+/sys/devices/platform/dell_rbu/image_type
+/sys/devices/platform/dell_rbu/data
+
+The driver supports two types of update mechanism; monolithic and packetized.
+These update mechanism depends upon the BIOS currently running on the system.
+Most of the Dell systems support a monolithic update where the BIOS image is
+copied to a single contiguous block of physical memory.
+In case of packet mechanism the single memory can be broken in smaller chuks
+of contiguous memory and the BIOS image is scattered in these packets.
+
+By default the driver uses monolithic memory for the update type. This can be
+changed to contiguous during the driver load time by specifying the load
+parameter image_type=packet.  This can also be changed later as below
+echo packet > /sys/devices/platform/dell_rbu/image_type
+
+Do the steps below to download the BIOS image.
+1) echo 1 > /sys/class/firmware/dell_rbu/loading
+2) cp bios_image.hdr /sys/class/firmware/dell_rbu/data
+3) echo 0 > /sys/class/firmware/dell_rbu/loading
+
+The /sys/class/firmware/dell_rbu/ entries will remain till the following is
+done.
+echo -1 > /sys/class/firmware/dell_rbu/loading
+
+Until this step is completed the drivr cannot be unloaded.
+
+Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
+read back the image downloaded. This is useful in case of packet update
+mechanism where the above steps 1,2,3 will repeated for every packet.
+By reading the /sys/devices/platform/dell_rbu/data file all packet data
+downloaded can be verified in a single file.
+The packets are arranged in this file one after the other in a FIFO order.
+
+NOTE:
+This driver requires a patch for firmware_class.c which has the addition
+of request_firmware_nowait_nohotplug function to wortk
+Also after updating the BIOS image an user mdoe application neeeds to execute
+code which message the BIOS update request to the BIOS. So on the next reboot
+the BIOS knows about the new image downloaded and it updates it self.
+Also don't unload the rbu drive if the image has to be updated.
+
index e6b8d05bc08d1b3d95c213a29023fbdd73802ff7..4b8c326c6aac91fcd0d04db82b12114850376c52 100644 (file)
@@ -16,7 +16,7 @@ Enable the following options:
 "Device drivers" => "Multimedia devices"
  => "Video For Linux" => "BT848 Video For Linux"
 "Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
- => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
+ => "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards"
 
 3) Loading Modules, described by two approaches
 ===============================================
index f1d436993eb156831f50a4ab32619f79929dbc02..3cb39ade290eae9d3e3046cfb04fe340e601d5b9 100644 (file)
@@ -7,7 +7,7 @@ To protect itself the kernel has to verify this address.
 
 In older versions of Linux this was done with the 
 int verify_area(int type, const void * addr, unsigned long size) 
-function.
+function (which has since been replaced by access_ok()).
 
 This function verified that the memory area starting at address 
 addr and of size size was accessible for the operation specified 
index 363909056e46f0c41b865977659bc599577b3de3..2e0a01b21fe040503243c963a65f8411e795961b 100644 (file)
@@ -51,14 +51,6 @@ Who: Adrian Bunk <bunk@stusta.de>
 
 ---------------------------
 
-What:  register_ioctl32_conversion() / unregister_ioctl32_conversion()
-When:  April 2005
-Why:   Replaced by ->compat_ioctl in file_operations and other method
-       vecors.
-Who:   Andi Kleen <ak@muc.de>, Christoph Hellwig <hch@lst.de>
-
----------------------------
-
 What:  RCU API moves to EXPORT_SYMBOL_GPL
 When:  April 2006
 Files: include/linux/rcupdate.h, kernel/rcupdate.c
@@ -74,14 +66,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
 
 ---------------------------
 
-What:  remove verify_area()
-When:  July 2006
-Files: Various uaccess.h headers.
-Why:   Deprecated and redundant. access_ok() should be used instead.
-Who:   Jesper Juhl <juhl-lkml@dif.dk>
-
----------------------------
-
 What:  IEEE1394 Audio and Music Data Transmission Protocol driver,
        Connection Management Procedures driver
 When:  November 2005
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
new file mode 100644 (file)
index 0000000..d24e1b0
--- /dev/null
@@ -0,0 +1,362 @@
+
+relayfs - a high-speed data relay filesystem
+============================================
+
+relayfs is a filesystem designed to provide an efficient mechanism for
+tools and facilities to relay large and potentially sustained streams
+of data from kernel space to user space.
+
+The main abstraction of relayfs is the 'channel'.  A channel consists
+of a set of per-cpu kernel buffers each represented by a file in the
+relayfs filesystem.  Kernel clients write into a channel using
+efficient write functions which automatically log to the current cpu's
+channel buffer.  User space applications mmap() the per-cpu files and
+retrieve the data as it becomes available.
+
+The format of the data logged into the channel buffers is completely
+up to the relayfs client; relayfs does however provide hooks which
+allow clients to impose some stucture on the buffer data.  Nor does
+relayfs implement any form of data filtering - this also is left to
+the client.  The purpose is to keep relayfs as simple as possible.
+
+This document provides an overview of the relayfs API.  The details of
+the function parameters are documented along with the functions in the
+filesystem code - please see that for details.
+
+Semantics
+=========
+
+Each relayfs channel has one buffer per CPU, each buffer has one or
+more sub-buffers. Messages are written to the first sub-buffer until
+it is too full to contain a new message, in which case it it is
+written to the next (if available).  Messages are never split across
+sub-buffers.  At this point, userspace can be notified so it empties
+the first sub-buffer, while the kernel continues writing to the next.
+
+When notified that a sub-buffer is full, the kernel knows how many
+bytes of it are padding i.e. unused.  Userspace can use this knowledge
+to copy only valid data.
+
+After copying it, userspace can notify the kernel that a sub-buffer
+has been consumed.
+
+relayfs can operate in a mode where it will overwrite data not yet
+collected by userspace, and not wait for it to consume it.
+
+relayfs itself does not provide for communication of such data between
+userspace and kernel, allowing the kernel side to remain simple and not
+impose a single interface on userspace. It does provide a separate
+helper though, described below.
+
+klog, relay-app & librelay
+==========================
+
+relayfs itself is ready to use, but to make things easier, two
+additional systems are provided.  klog is a simple wrapper to make
+writing formatted text or raw data to a channel simpler, regardless of
+whether a channel to write into exists or not, or whether relayfs is
+compiled into the kernel or is configured as a module.  relay-app is
+the kernel counterpart of userspace librelay.c, combined these two
+files provide glue to easily stream data to disk, without having to
+bother with housekeeping.  klog and relay-app can be used together,
+with klog providing high-level logging functions to the kernel and
+relay-app taking care of kernel-user control and disk-logging chores.
+
+It is possible to use relayfs without relay-app & librelay, but you'll
+have to implement communication between userspace and kernel, allowing
+both to convey the state of buffers (full, empty, amount of padding).
+
+klog, relay-app and librelay can be found in the relay-apps tarball on
+http://relayfs.sourceforge.net
+
+The relayfs user space API
+==========================
+
+relayfs implements basic file operations for user space access to
+relayfs channel buffer data.  Here are the file operations that are
+available and some comments regarding their behavior:
+
+open()  enables user to open an _existing_ buffer.
+
+mmap()  results in channel buffer being mapped into the caller's
+        memory space. Note that you can't do a partial mmap - you must
+        map the entire file, which is NRBUF * SUBBUFSIZE.
+
+read()  read the contents of a channel buffer.  The bytes read are
+        'consumed' by the reader i.e. they won't be available again
+        to subsequent reads.  If the channel is being used in
+        no-overwrite mode (the default), it can be read at any time
+        even if there's an active kernel writer.  If the channel is
+        being used in overwrite mode and there are active channel
+        writers, results may be unpredictable - users should make
+        sure that all logging to the channel has ended before using
+        read() with overwrite mode.
+
+poll()  POLLIN/POLLRDNORM/POLLERR supported.  User applications are
+        notified when sub-buffer boundaries are crossed.
+
+close() decrements the channel buffer's refcount.  When the refcount
+       reaches 0 i.e. when no process or kernel client has the buffer
+       open, the channel buffer is freed.
+
+
+In order for a user application to make use of relayfs files, the
+relayfs filesystem must be mounted.  For example,
+
+       mount -t relayfs relayfs /mnt/relay
+
+NOTE:  relayfs doesn't need to be mounted for kernel clients to create
+       or use channels - it only needs to be mounted when user space
+       applications need access to the buffer data.
+
+
+The relayfs kernel API
+======================
+
+Here's a summary of the API relayfs provides to in-kernel clients:
+
+
+  channel management functions:
+
+    relay_open(base_filename, parent, subbuf_size, n_subbufs,
+               callbacks)
+    relay_close(chan)
+    relay_flush(chan)
+    relay_reset(chan)
+    relayfs_create_dir(name, parent)
+    relayfs_remove_dir(dentry)
+
+  channel management typically called on instigation of userspace:
+
+    relay_subbufs_consumed(chan, cpu, subbufs_consumed)
+
+  write functions:
+
+    relay_write(chan, data, length)
+    __relay_write(chan, data, length)
+    relay_reserve(chan, length)
+
+  callbacks:
+
+    subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
+    buf_mapped(buf, filp)
+    buf_unmapped(buf, filp)
+
+  helper functions:
+
+    relay_buf_full(buf)
+    subbuf_start_reserve(buf, length)
+
+
+Creating a channel
+------------------
+
+relay_open() is used to create a channel, along with its per-cpu
+channel buffers.  Each channel buffer will have an associated file
+created for it in the relayfs filesystem, which can be opened and
+mmapped from user space if desired.  The files are named
+basename0...basenameN-1 where N is the number of online cpus, and by
+default will be created in the root of the filesystem.  If you want a
+directory structure to contain your relayfs files, you can create it
+with relayfs_create_dir() and pass the parent directory to
+relay_open().  Clients are responsible for cleaning up any directory
+structure they create when the channel is closed - use
+relayfs_remove_dir() for that.
+
+The total size of each per-cpu buffer is calculated by multiplying the
+number of sub-buffers by the sub-buffer size passed into relay_open().
+The idea behind sub-buffers is that they're basically an extension of
+double-buffering to N buffers, and they also allow applications to
+easily implement random-access-on-buffer-boundary schemes, which can
+be important for some high-volume applications.  The number and size
+of sub-buffers is completely dependent on the application and even for
+the same application, different conditions will warrant different
+values for these parameters at different times.  Typically, the right
+values to use are best decided after some experimentation; in general,
+though, it's safe to assume that having only 1 sub-buffer is a bad
+idea - you're guaranteed to either overwrite data or lose events
+depending on the channel mode being used.
+
+Channel 'modes'
+---------------
+
+relayfs channels can be used in either of two modes - 'overwrite' or
+'no-overwrite'.  The mode is entirely determined by the implementation
+of the subbuf_start() callback, as described below.  In 'overwrite'
+mode, also known as 'flight recorder' mode, writes continuously cycle
+around the buffer and will never fail, but will unconditionally
+overwrite old data regardless of whether it's actually been consumed.
+In no-overwrite mode, writes will fail i.e. data will be lost, if the
+number of unconsumed sub-buffers equals the total number of
+sub-buffers in the channel.  It should be clear that if there is no
+consumer or if the consumer can't consume sub-buffers fast enought,
+data will be lost in either case; the only difference is whether data
+is lost from the beginning or the end of a buffer.
+
+As explained above, a relayfs channel is made of up one or more
+per-cpu channel buffers, each implemented as a circular buffer
+subdivided into one or more sub-buffers.  Messages are written into
+the current sub-buffer of the channel's current per-cpu buffer via the
+write functions described below.  Whenever a message can't fit into
+the current sub-buffer, because there's no room left for it, the
+client is notified via the subbuf_start() callback that a switch to a
+new sub-buffer is about to occur.  The client uses this callback to 1)
+initialize the next sub-buffer if appropriate 2) finalize the previous
+sub-buffer if appropriate and 3) return a boolean value indicating
+whether or not to actually go ahead with the sub-buffer switch.
+
+To implement 'no-overwrite' mode, the userspace client would provide
+an implementation of the subbuf_start() callback something like the
+following:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+                       void *prev_subbuf,
+                       unsigned int prev_padding)
+{
+       if (prev_subbuf)
+               *((unsigned *)prev_subbuf) = prev_padding;
+
+       if (relay_buf_full(buf))
+               return 0;
+
+       subbuf_start_reserve(buf, sizeof(unsigned int));
+
+       return 1;
+}
+
+If the current buffer is full i.e. all sub-buffers remain unconsumed,
+the callback returns 0 to indicate that the buffer switch should not
+occur yet i.e. until the consumer has had a chance to read the current
+set of ready sub-buffers.  For the relay_buf_full() function to make
+sense, the consumer is reponsible for notifying relayfs when
+sub-buffers have been consumed via relay_subbufs_consumed().  Any
+subsequent attempts to write into the buffer will again invoke the
+subbuf_start() callback with the same parameters; only when the
+consumer has consumed one or more of the ready sub-buffers will
+relay_buf_full() return 0, in which case the buffer switch can
+continue.
+
+The implementation of the subbuf_start() callback for 'overwrite' mode
+would be very similar:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+                       void *prev_subbuf,
+                       unsigned int prev_padding)
+{
+       if (prev_subbuf)
+               *((unsigned *)prev_subbuf) = prev_padding;
+
+       subbuf_start_reserve(buf, sizeof(unsigned int));
+
+       return 1;
+}
+
+In this case, the relay_buf_full() check is meaningless and the
+callback always returns 1, causing the buffer switch to occur
+unconditionally.  It's also meaningless for the client to use the
+relay_subbufs_consumed() function in this mode, as it's never
+consulted.
+
+The default subbuf_start() implementation, used if the client doesn't
+define any callbacks, or doesn't define the subbuf_start() callback,
+implements the simplest possible 'no-overwrite' mode i.e. it does
+nothing but return 0.
+
+Header information can be reserved at the beginning of each sub-buffer
+by calling the subbuf_start_reserve() helper function from within the
+subbuf_start() callback.  This reserved area can be used to store
+whatever information the client wants.  In the example above, room is
+reserved in each sub-buffer to store the padding count for that
+sub-buffer.  This is filled in for the previous sub-buffer in the
+subbuf_start() implementation; the padding value for the previous
+sub-buffer is passed into the subbuf_start() callback along with a
+pointer to the previous sub-buffer, since the padding value isn't
+known until a sub-buffer is filled.  The subbuf_start() callback is
+also called for the first sub-buffer when the channel is opened, to
+give the client a chance to reserve space in it.  In this case the
+previous sub-buffer pointer passed into the callback will be NULL, so
+the client should check the value of the prev_subbuf pointer before
+writing into the previous sub-buffer.
+
+Writing to a channel
+--------------------
+
+kernel clients write data into the current cpu's channel buffer using
+relay_write() or __relay_write().  relay_write() is the main logging
+function - it uses local_irqsave() to protect the buffer and should be
+used if you might be logging from interrupt context.  If you know
+you'll never be logging from interrupt context, you can use
+__relay_write(), which only disables preemption.  These functions
+don't return a value, so you can't determine whether or not they
+failed - the assumption is that you wouldn't want to check a return
+value in the fast logging path anyway, and that they'll always succeed
+unless the buffer is full and no-overwrite mode is being used, in
+which case you can detect a failed write in the subbuf_start()
+callback by calling the relay_buf_full() helper function.
+
+relay_reserve() is used to reserve a slot in a channel buffer which
+can be written to later.  This would typically be used in applications
+that need to write directly into a channel buffer without having to
+stage data in a temporary buffer beforehand.  Because the actual write
+may not happen immediately after the slot is reserved, applications
+using relay_reserve() can keep a count of the number of bytes actually
+written, either in space reserved in the sub-buffers themselves or as
+a separate array.  See the 'reserve' example in the relay-apps tarball
+at http://relayfs.sourceforge.net for an example of how this can be
+done.  Because the write is under control of the client and is
+separated from the reserve, relay_reserve() doesn't protect the buffer
+at all - it's up to the client to provide the appropriate
+synchronization when using relay_reserve().
+
+Closing a channel
+-----------------
+
+The client calls relay_close() when it's finished using the channel.
+The channel and its associated buffers are destroyed when there are no
+longer any references to any of the channel buffers.  relay_flush()
+forces a sub-buffer switch on all the channel buffers, and can be used
+to finalize and process the last sub-buffers before the channel is
+closed.
+
+Misc
+----
+
+Some applications may want to keep a channel around and re-use it
+rather than open and close a new channel for each use.  relay_reset()
+can be used for this purpose - it resets a channel to its initial
+state without reallocating channel buffer memory or destroying
+existing mappings.  It should however only be called when it's safe to
+do so i.e. when the channel isn't currently being written to.
+
+Finally, there are a couple of utility callbacks that can be used for
+different purposes.  buf_mapped() is called whenever a channel buffer
+is mmapped from user space and buf_unmapped() is called when it's
+unmapped.  The client can use this notification to trigger actions
+within the kernel application, such as enabling/disabling logging to
+the channel.
+
+
+Resources
+=========
+
+For news, example code, mailing list, etc. see the relayfs homepage:
+
+    http://relayfs.sourceforge.net
+
+
+Credits
+=======
+
+The ideas and specs for relayfs came about as a result of discussions
+on tracing involving the following:
+
+Michel Dagenais                <michel.dagenais@polymtl.ca>
+Richard Moore          <richardj_moore@uk.ibm.com>
+Bob Wisniewski         <bob@watson.ibm.com>
+Karim Yaghmour         <karim@opersys.com>
+Tom Zanussi            <zanussi@us.ibm.com>
+
+Also thanks to Hubertus Franke for a lot of useful suggestions and bug
+reports.
index 1c48f0eba6fb79121c08dc95a6a9b05441f9f0e8..10312bebe55de0b063e59b28f2781a7f7001f8b4 100644 (file)
@@ -2,7 +2,7 @@
                     ----------------------------
 
                    H. Peter Anvin <hpa@zytor.com>
-                       Last update 2002-01-01
+                       Last update 2005-09-02
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -34,6 +34,8 @@ Protocol 2.02:        (Kernel 2.4.0-test3-pre3) New command line protocol.
 Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
                initrd address available to the bootloader.
 
+Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
+
 
 **** MEMORY LAYOUT
 
@@ -103,10 +105,9 @@ The header looks like:
 Offset Proto   Name            Meaning
 /Size
 
-01F1/1 ALL     setup_sects     The size of the setup in sectors
+01F1/1 ALL(1   setup_sects     The size of the setup in sectors
 01F2/2 ALL     root_flags      If set, the root is mounted readonly
-01F4/2 ALL     syssize         DO NOT USE - for bootsect.S use only
-01F6/2 ALL     swap_dev        DO NOT USE - obsolete
+01F4/4 2.04+(2 syssize         The size of the 32-bit code in 16-byte paras
 01F8/2 ALL     ram_size        DO NOT USE - for bootsect.S use only
 01FA/2 ALL     vid_mode        Video mode control
 01FC/2 ALL     root_dev        Default root device number
@@ -129,8 +130,12 @@ Offset     Proto   Name            Meaning
 0228/4 2.02+   cmd_line_ptr    32-bit pointer to the kernel command line
 022C/4 2.03+   initrd_addr_max Highest legal initrd address
 
-For backwards compatibility, if the setup_sects field contains 0, the
-real value is 4.
+(1) For backwards compatibility, if the setup_sects field contains 0, the
+    real value is 4.
+
+(2) For boot protocol prior to 2.04, the upper two bytes of the syssize
+    field are unusable, which means the size of a bzImage kernel
+    cannot be determined.
 
 If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
 the boot protocol version is "old".  Loading an old kernel, the
@@ -230,12 +235,16 @@ loader to communicate with the kernel.  Some of its options are also
 relevant to the boot loader itself, see "special command line options"
 below.
 
-The kernel command line is a null-terminated string up to 255
-characters long, plus the final null.
+The kernel command line is a null-terminated string currently up to
+255 characters long, plus the final null.  A string that is too long
+will be automatically truncated by the kernel, a boot loader may allow
+a longer command line to be passed to permit future kernels to extend
+this limit.
 
 If the boot protocol version is 2.02 or later, the address of the
 kernel command line is given by the header field cmd_line_ptr (see
-above.)
+above.)  This address can be anywhere between the end of the setup
+heap and 0xA0000.
 
 If the protocol version is *not* 2.02 or higher, the kernel
 command line is entered using the following protocol:
@@ -255,7 +264,7 @@ command line is entered using the following protocol:
 **** SAMPLE BOOT CONFIGURATION
 
 As a sample configuration, assume the following layout of the real
-mode segment:
+mode segment (this is a typical, and recommended layout):
 
        0x0000-0x7FFF   Real mode kernel
        0x8000-0x8FFF   Stack and heap
@@ -312,9 +321,9 @@ Such a boot loader should enter the following fields in the header:
 
 **** LOADING THE REST OF THE KERNEL
 
-The non-real-mode kernel starts at offset (setup_sects+1)*512 in the
-kernel file (again, if setup_sects == 0 the real value is 4.)  It
-should be loaded at address 0x10000 for Image/zImage kernels and
+The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
+in the kernel file (again, if setup_sects == 0 the real value is 4.)
+It should be loaded at address 0x10000 for Image/zImage kernels and
 0x100000 for bzImage kernels.
 
 The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
index 3d5cd7a09b2fc1aa56b6c197ee8d35df7116ec4d..d2f0c67ba1fb01e419966178138629048d2202bb 100644 (file)
@@ -1174,6 +1174,11 @@ running once the system is up.
                        New name for the ramdisk parameter.
                        See Documentation/ramdisk.txt.
 
+       rdinit=         [KNL]
+                       Format: <full_path>
+                       Run specified binary instead of /init from the ramdisk,
+                       used for early userspace startup. See initrd.
+
        reboot=         [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
                        Format: <reboot_mode>[,<reboot_mode2>[,...]]
                        See arch/*/kernel/reboot.c.
index ddf907fbcc0570ba3acf83ae87a8d702e637871b..b0d50840788ebf80fd478ac9db3e8ef841716e26 100644 (file)
@@ -1,22 +1,20 @@
-From kernel/suspend.c:
+Some warnings, first.
 
  * BIG FAT WARNING *********************************************************
  *
- * If you have unsupported (*) devices using DMA...
- *                             ...say goodbye to your data.
- *
  * If you touch anything on disk between suspend and resume...
  *                             ...kiss your data goodbye.
  *
- * If your disk driver does not support suspend... (IDE does)
- *                             ...you'd better find out how to get along
- *                                without your data.
- *
- * If you change kernel command line between suspend and resume...
- *                             ...prepare for nasty fsck or worse.
+ * If you do resume from initrd after your filesystems are mounted...
+ *                             ...bye bye root partition.
+ *                     [this is actually same case as above]
  *
- * If you change your hardware while system is suspended...
- *                             ...well, it was not good idea.
+ * If you have unsupported (*) devices using DMA, you may have some
+ * problems. If your disk driver does not support suspend... (IDE does),
+ * it may cause some problems, too. If you change kernel command line
+ * between suspend and resume, it may do something wrong. If you change
+ * your hardware while system is suspended... well, it was not good idea;
+ * but it will probably only crash.
  *
  * (*) suspend/resume support is needed to make it safe.
 
@@ -30,6 +28,13 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
 
+Encrypted suspend image:
+------------------------
+If you want to store your suspend image encrypted with a temporary
+key to prevent data gathering after resume you must compile
+crypto and the aes algorithm into the kernel - modules won't work
+as they cannot be loaded at resume time.
+
 
 Article about goals and implementation of Software Suspend for Linux
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -85,11 +90,6 @@ resume.
 You have your server on UPS. Power died, and UPS is indicating 30
 seconds to failure. What do you do? Suspend to disk.
 
-Ethernet card in your server died. You want to replace it. Your
-server is not hotplug capable. What do you do? Suspend to disk,
-replace ethernet card, resume. If you are fast your users will not
-even see broken connections.
-
 
 Q: Maybe I'm missing something, but why don't the regular I/O paths work?
 
@@ -117,31 +117,6 @@ Q: Does linux support ACPI S4?
 
 A: Yes. That's what echo platform > /sys/power/disk does.
 
-Q: My machine doesn't work with ACPI. How can I use swsusp than ?
-
-A: Do a reboot() syscall with right parameters. Warning: glibc gets in
-its way, so check with strace:
-
-reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 0xd000fce2)
-
-(Thanks to Peter Osterlund:)
-
-#include <unistd.h>
-#include <syscall.h>
-
-#define LINUX_REBOOT_MAGIC1     0xfee1dead
-#define LINUX_REBOOT_MAGIC2     672274793
-#define LINUX_REBOOT_CMD_SW_SUSPEND     0xD000FCE2
-
-int main()
-{
-    syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-            LINUX_REBOOT_CMD_SW_SUSPEND, 0);
-    return 0;
-}
-
-Also /sys/ interface should be still present.
-
 Q: What is 'suspend2'?
 
 A: suspend2 is 'Software Suspend 2', a forked implementation of
@@ -312,9 +287,45 @@ system is shut down or suspended. Additionally use the encrypted
 suspend image to prevent sensitive data from being stolen after
 resume.
 
-Q: Why we cannot suspend to a swap file?
+Q: Why can't we suspend to a swap file?
 
 A: Because accessing swap file needs the filesystem mounted, and
 filesystem might do something wrong (like replaying the journal)
-during mount. [Probably could be solved by modifying every filesystem
-to support some kind of "really read-only!" option. Patches welcome.]
+during mount.
+
+There are few ways to get that fixed:
+
+1) Probably could be solved by modifying every filesystem to support
+some kind of "really read-only!" option. Patches welcome.
+
+2) suspend2 gets around that by storing absolute positions in on-disk
+image (and blocksize), with resume parameter pointing directly to
+suspend header.
+
+Q: Is there a maximum system RAM size that is supported by swsusp?
+
+A: It should work okay with highmem.
+
+Q: Does swsusp (to disk) use only one swap partition or can it use
+multiple swap partitions (aggregate them into one logical space)?
+
+A: Only one swap partition, sorry.
+
+Q: If my application(s) causes lots of memory & swap space to be used
+(over half of the total system RAM), is it correct that it is likely
+to be useless to try to suspend to disk while that app is running?
+
+A: No, it should work okay, as long as your app does not mlock()
+it. Just prepare big enough swap partition.
+
+Q: What information is usefull for debugging suspend-to-disk problems?
+
+A: Well, last messages on the screen are always useful. If something
+is broken, it is usually some kernel driver, therefore trying with as
+little as possible modules loaded helps a lot. I also prefer people to
+suspend from console, preferably without X running. Booting with
+init=/bin/bash, then swapon and starting suspend sequence manually
+usually does the trick. Then it is good idea to try with latest
+vanilla kernel.
+
+
index 1a44e8acb54cff7575abe6ad0e90b57416474ddd..526d6dd267ea8e38f319c30de9f6accf2967327f 100644 (file)
@@ -120,6 +120,7 @@ IBM ThinkPad T42p (2373-GTG)        s3_bios (2)
 IBM TP X20                     ??? (*)
 IBM TP X30                     s3_bios (2)
 IBM TP X31 / Type 2672-XXH      none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
+IBM TP X32                     none (1), but backlight is on and video is trashed after long suspend
 IBM Thinkpad X40 Type 2371-7JG  s3_bios,s3_mode (4)
 Medion MD4220                  ??? (*)
 Samsung P35                    vbetool needed (6)
index 0f3b2405d09edf30c1f0251ce4c7e51d63e960f1..c1237a9255055635475552c519f8199303789c8e 100644 (file)
@@ -99,6 +99,7 @@ statically linked into the kernel). Those options are:
                                SONYPI_MEYE_MASK                0x0400
                                SONYPI_MEMORYSTICK_MASK         0x0800
                                SONYPI_BATTERY_MASK             0x1000
+                               SONYPI_WIRELESS_MASK            0x2000
 
        useinput:       if set (which is the default) two input devices are
                        created, one which interprets the jogdial events as
@@ -137,6 +138,15 @@ Bugs:
          speed handling etc). Use ACPI instead of APM if it works on your
          laptop.
 
+       - sonypi lacks the ability to distinguish between certain key
+         events on some models.
+
+       - some models with the nvidia card (geforce go 6200 tc) uses a
+         different way to adjust the backlighting of the screen. There
+         is a userspace utility to adjust the brightness on those models,
+         which can be downloaded from
+         http://www.acc.umu.se/~erikw/program/smartdimmer-0.1.tar.bz2
+
        - since all development was done by reverse engineering, there is
          _absolutely no guarantee_ that this driver will not crash your
          laptop. Permanently.
index 7e1f67130a16d595d2a7f5879dce0469993de085..2af78e965dd724e6c4a18277092497a6ab38a2e3 100644 (file)
@@ -202,13 +202,6 @@ P: Colin Leroy
 M:     colin@colino.net
 S:     Maintained
 
-ADVANSYS SCSI DRIVER
-P:     Bob Frey
-M:     linux@advansys.com
-W:     http://www.advansys.com/linux.html
-L:     linux-scsi@vger.kernel.org
-S:     Maintained
-
 AEDSP16 DRIVER
 P:     Riccardo Facchetti
 M:     fizban@tin.it
@@ -696,6 +689,11 @@ M: dz@debian.org
 W:     http://www.debian.org/~dz/i8k/
 S:     Maintained
 
+DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
+P:     Doug Warzecha
+M:     Douglas_Warzecha@dell.com
+S:     Maintained
+
 DEVICE-MAPPER
 P:     Alasdair Kergon
 L:     dm-devel@redhat.com
@@ -879,7 +877,7 @@ S:  Maintained
 
 FILESYSTEMS (VFS and infrastructure)
 P:     Alexander Viro
-M:     viro@parcelfarce.linux.theplanet.co.uk
+M:     viro@zeniv.linux.org.uk
 S:     Maintained
 
 FIRMWARE LOADER (request_firmware)
@@ -1967,7 +1965,6 @@ S:        Supported
 
 ROCKETPORT DRIVER
 P:     Comtrol Corp.
-M:     support@comtrol.com
 W:     http://www.comtrol.com
 S:     Maintained
 
index 189d5eababa8d15708e15e354e0eb372d5e7fad1..786491f9ceb2c072ae6108615211b1bf3d95306c 100644 (file)
@@ -479,6 +479,9 @@ config EISA
        depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       def_bool y
+
 config SMP
        bool "Symmetric multi-processing support"
        depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
index 8226c5cd788ccb142c3676727fb06161cc5cc574..67be50b7d80afba730e18746ad8e8ac63acc6068 100644 (file)
@@ -149,7 +149,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0
+       if (ntp_synced()
            && xtime.tv_sec > state.last_rtc_update + 660
            && xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
            && xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -502,10 +502,7 @@ do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
 
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
index 68dfdba71d74126512efcd4996282ffce11b63a4..0f2899b4159dfb4f12c4cc2d69f411dd9d88e0af 100644 (file)
@@ -64,6 +64,9 @@ config GENERIC_CALIBRATE_DELAY
 config GENERIC_BUST_SPINLOCK
        bool
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+
 config GENERIC_ISA_DMA
        bool
 
@@ -150,6 +153,7 @@ config ARCH_RPC
        select ARCH_ACORN
        select FIQ
        select TIMER_ACORN
+       select ARCH_MAY_HAVE_PC_FDC
        help
          On the Acorn Risc-PC, Linux can support the internal IDE disk and
          CD-ROM interface, serial and parallel port, and the floppy drive.
index d6bf8a2b090d833f6c16e5fa2e81d89c490497c2..59ad69640d6bde4e26cb8b41279ca32aa1b47c65 100644 (file)
@@ -7,7 +7,8 @@
  * so we have to figure out the machine for ourselves...
  *
  * Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
- * and Husky (SL-C760).
+ * Husky (SL-C760), Tosa (SL-C6000), Spitz (SL-C3000),
+ * Akita (SL-C1000) and Borzoi (SL-C3100).
  *
  */
 
 
 __SharpSL_start:
 
+/* Check for TC6393 - if found we have a Tosa */
+       ldr     r7, .TOSAID
+       mov     r1, #0x10000000         @ Base address of TC6393 chip
+       mov     r6, #0x03
+       ldrh    r3, [r1, #8]            @ Load TC6393XB Revison: This is 0x0003
+       cmp     r6, r3
+       beq     .SHARPEND               @ Success -> tosa
+
+/* Check for pxa270 - if found, branch */
+       mrc p15, 0, r4, c0, c0          @ Get Processor ID
+       and     r4, r4, #0xffffff00
+       ldr     r3, .PXA270ID
+       cmp     r4, r3
+       beq     .PXA270
+
+/* Check for w100 - if not found we have a Poodle */
        ldr     r1, .W100ADDR           @ Base address of w100 chip + regs offset
 
        mov r6, #0x31                   @ Load Magic Init value
@@ -30,7 +47,7 @@ __SharpSL_start:
        mov r5, #0x3000
 .W100LOOP:
        subs r5, r5, #1
-    bne .W100LOOP
+       bne .W100LOOP
        mov r6, #0x30                   @ Load 2nd Magic Init value
        str     r6, [r1, #0x280]        @ to SCRATCH_UMSK
 
@@ -40,45 +57,52 @@ __SharpSL_start:
        cmp     r6, r3
        bne     .SHARPEND                       @ We have no w100 - Poodle
 
-       mrc p15, 0, r6, c0, c0  @ Get Processor ID
-       and     r6, r6, #0xffffff00
+/* Check for pxa250 - if found we have a Corgi */
        ldr     r7, .CORGIID
        ldr     r3, .PXA255ID
-       cmp     r6, r3
+       cmp     r4, r3
        blo     .SHARPEND                       @ We have a PXA250 - Corgi
 
-       mov     r1, #0x0c000000         @ Base address of NAND chip
-       ldrb    r3, [r1, #24]   @ Load FLASHCTL
-       bic     r3, r3, #0x11           @ SET NCE
-       orr     r3, r3, #0x0a           @ SET CLR + FLWP
-       strb    r3, [r1, #24]   @ Save to FLASHCTL
-       mov     r2, #0x90               @ Command "readid"
-       strb    r2, [r1, #20]   @ Save to FLASHIO
-       bic     r3, r3, #2                      @ CLR CLE
-       orr     r3, r3, #4                      @ SET ALE
-       strb    r3, [r1, #24]   @ Save to FLASHCTL
-       mov             r2, #0                  @ Address 0x00
-       strb    r2, [r1, #20]   @ Save to FLASHIO
-       bic     r3, r3, #4                      @ CLR ALE
-       strb    r3, [r1, #24]   @ Save to FLASHCTL
-.SHARP1:
-       ldrb    r3, [r1, #24]   @ Load FLASHCTL
-       tst     r3, #32                         @ Is chip ready?
-       beq     .SHARP1
-       ldrb    r2, [r1, #20]   @ NAND Manufacturer ID
-       ldrb    r3, [r1, #20]   @ NAND Chip ID
+/* Check for 64MiB flash - if found we have a Shepherd */
+       bl      get_flash_ids
        ldr     r7, .SHEPHERDID
        cmp     r3, #0x76                       @ 64MiB flash
        beq     .SHARPEND                       @ We have Shepherd
+
+/* Must be a Husky */
        ldr     r7, .HUSKYID            @ Must be Husky
        b .SHARPEND
 
+.PXA270:
+/* Check for 16MiB flash - if found we have Spitz */
+       bl      get_flash_ids
+       ldr     r7, .SPITZID
+       cmp     r3, #0x73                       @ 16MiB flash
+       beq     .SHARPEND                       @ We have Spitz
+
+/* Check for a second SCOOP chip - if found we have Borzoi */
+       ldr     r1, .SCOOP2ADDR
+       ldr     r7, .BORZOIID
+       mov     r6, #0x0140
+       strh    r6, [r1]
+       ldrh    r6, [r1]
+       cmp     r6, #0x0140
+       beq     .SHARPEND                       @ We have Borzoi
+
+/* Must be Akita */
+       ldr     r7, .AKITAID
+       b       .SHARPEND                       @ We have Borzoi
+
 .PXA255ID:
        .word   0x69052d00              @ PXA255 Processor ID
+.PXA270ID:
+       .word   0x69054100              @ PXA270 Processor ID
 .W100ID:
        .word   0x57411002              @ w100 Chip ID
 .W100ADDR:
        .word   0x08010000              @ w100 Chip ID Reg Address
+.SCOOP2ADDR:
+       .word   0x08800040
 .POODLEID:
        .word   MACH_TYPE_POODLE
 .CORGIID:
@@ -87,6 +111,41 @@ __SharpSL_start:
        .word   MACH_TYPE_SHEPHERD
 .HUSKYID:
        .word   MACH_TYPE_HUSKY
-.SHARPEND:
+.TOSAID:
+       .word   MACH_TYPE_TOSA
+.SPITZID:
+       .word   MACH_TYPE_SPITZ
+.AKITAID:
+       .word   MACH_TYPE_AKITA
+.BORZOIID:
+       .word   MACH_TYPE_BORZOI
 
+/*
+ * Return: r2 - NAND Manufacturer ID
+ *         r3 - NAND Chip ID
+ * Corrupts: r1
+ */
+get_flash_ids:
+       mov     r1, #0x0c000000         @ Base address of NAND chip
+       ldrb    r3, [r1, #24]           @ Load FLASHCTL
+       bic     r3, r3, #0x11           @ SET NCE
+       orr     r3, r3, #0x0a           @ SET CLR + FLWP
+       strb    r3, [r1, #24]           @ Save to FLASHCTL
+       mov     r2, #0x90               @ Command "readid"
+       strb    r2, [r1, #20]           @ Save to FLASHIO
+       bic     r3, r3, #2              @ CLR CLE
+       orr     r3, r3, #4              @ SET ALE
+       strb    r3, [r1, #24]           @ Save to FLASHCTL
+       mov     r2, #0                  @ Address 0x00
+       strb    r2, [r1, #20]           @ Save to FLASHIO
+       bic     r3, r3, #4              @ CLR ALE
+       strb    r3, [r1, #24]           @ Save to FLASHCTL
+.fids1:
+       ldrb    r3, [r1, #24]           @ Load FLASHCTL
+       tst     r3, #32                 @ Is chip ready?
+       beq     .fids1
+       ldrb    r2, [r1, #20]           @ NAND Manufacturer ID
+       ldrb    r3, [r1, #20]           @ NAND Chip ID
+       mov     pc, lr
 
+.SHARPEND:
index 24955263b0968b06b17809bb363da489bf667b48..4198677cd394c81cebbd5eb068e82fb4fc02e9fa 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Fri Jul  8 04:49:34 2005
+# Linux kernel version: 2.6.13
+# Mon Sep  5 18:07:12 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -102,9 +102,11 @@ CONFIG_OMAP_MUX_WARNINGS=y
 # CONFIG_OMAP_MPU_TIMER is not set
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_32K_TIMER_HZ=128
+# CONFIG_OMAP_DM_TIMER is not set
 CONFIG_OMAP_LL_DEBUG_UART1=y
 # CONFIG_OMAP_LL_DEBUG_UART2 is not set
 # CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
 
 #
 # OMAP Core Type
@@ -166,7 +168,6 @@ CONFIG_ISA_DMA_API=y
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 CONFIG_PREEMPT=y
 CONFIG_NO_IDLE_HZ=y
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -230,91 +231,82 @@ CONFIG_PM=y
 # CONFIG_APM is not set
 
 #
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
+# Networking
 #
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_NET=y
 
 #
-# User Modules And Translation Layers
+# Networking options
 #
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
 
 #
-# RAM/ROM/Flash chip drivers
+# SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
-# Mapping drivers for chip access
+# Network testing
 #
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 
 #
-# Self-contained MTD device drivers
+# Device Drivers
 #
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
 
 #
-# Disk-On-Chip Device Drivers
+# Generic Driver Options
 #
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
-# NAND Flash Device Drivers
+# Memory Technology Devices (MTD)
 #
-# CONFIG_MTD_NAND is not set
+# CONFIG_MTD is not set
 
 #
 # Parallel port support
@@ -403,72 +395,8 @@ CONFIG_SCSI_PROC_FS=y
 #
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
+# Network device support
 #
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -518,6 +446,8 @@ CONFIG_SLIP_COMPRESSED=y
 # CONFIG_SLIP_MODE_SLIP6 is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -615,77 +545,15 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 #
 # I2C support
 #
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
+CONFIG_ISP1301_OMAP=y
 
 #
-# Hardware Sensors Chip support
+# Hardware Monitoring support
 #
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-CONFIG_ISP1301_OMAP=y
-CONFIG_TPS65010=y
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -756,15 +624,9 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
 # CONFIG_SOUND_AD1980 is not set
 
 #
@@ -810,6 +672,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 
 #
 # XFS support
@@ -817,6 +680,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -857,15 +721,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=2
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
 CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -1007,4 +862,3 @@ CONFIG_CRYPTO_DES=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
index 8880482dcbffd4dbbfb20ea98def232de3b439d1..69449a818dccecd78ac290032124c9998e746d4a 100644 (file)
@@ -102,7 +102,7 @@ static unsigned long next_rtc_update;
  */
 static inline void do_set_rtc(void)
 {
-       if (time_status & STA_UNSYNC || set_rtc == NULL)
+       if (!ntp_synced() || set_rtc == NULL)
                return;
 
        if (next_rtc_update &&
@@ -292,10 +292,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 324d9edeec38f3e1dc70cff7248705e0837429ea..bdd257921cfbe639cd0adfb8c30c4febd79487cc 100644 (file)
@@ -87,6 +87,7 @@ config FOOTBRIDGE_ADDIN
 
 # EBSA285 board in either host or addin mode
 config ARCH_EBSA285
+       select ARCH_MAY_HAVE_PC_FDC
        bool
 
 endif
index d53af16695023d16f7867b74c35b56c2dfa952cc..0039793b694a20cd63da8930386a5ba3c6cbf9d1 100644 (file)
@@ -60,7 +60,7 @@ static unsigned long iop321_gettimeoffset(void)
        /*
         * Now convert them to usec.
         */
-       usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+       usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
 
        return usec;
 }
index 1a6d9d661e4b8ee851ef0867be104309eebe917f..8eddfac7e2b046450d74a6074837b9f73e0fff1b 100644 (file)
@@ -58,7 +58,7 @@ static unsigned long iop331_gettimeoffset(void)
        /*
         * Now convert them to usec.
         */
-       usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+       usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
 
        return usec;
 }
index 781d10ae00b7dfc5771fd28d99eab154a8de1706..098c817a7fb82a8e6fc7f38c24757ec620f6e47e 100644 (file)
@@ -382,7 +382,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
 static struct irqchip ixp2000_GPIO_irq_chip = {
        .ack            = ixp2000_GPIO_irq_mask_ack,
        .mask           = ixp2000_GPIO_irq_mask,
-       .unmask         = ixp2000_GPIO_irq_unmask
+       .unmask         = ixp2000_GPIO_irq_unmask,
        .set_type       = ixp2000_GPIO_irq_type,
 };
 
index 0422e906cc9a64e4ff11d43e866049a72ba52cd0..52ad11328e961225465a6e461b5aa8d564039a45 100644 (file)
@@ -179,17 +179,17 @@ static void ixp4xx_irq_level_unmask(unsigned int irq)
 }
 
 static struct irqchip ixp4xx_irq_level_chip = {
-       .ack    = ixp4xx_irq_mask,
-       .mask   = ixp4xx_irq_mask,
-       .unmask = ixp4xx_irq_level_unmask,
-       .type   = ixp4xx_set_irq_type
+       .ack            = ixp4xx_irq_mask,
+       .mask           = ixp4xx_irq_mask,
+       .unmask         = ixp4xx_irq_level_unmask,
+       .set_type       = ixp4xx_set_irq_type,
 };
 
 static struct irqchip ixp4xx_irq_edge_chip = {
-       .ack    = ixp4xx_irq_ack,
-       .mask   = ixp4xx_irq_mask,
-       .unmask = ixp4xx_irq_unmask,
-       .type   = ixp4xx_set_irq_type
+       .ack            = ixp4xx_irq_ack,
+       .mask           = ixp4xx_irq_mask,
+       .unmask         = ixp4xx_irq_unmask,
+       .set_type       = ixp4xx_set_irq_type,
 };
 
 static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
index a11b6d807352ccf93add9b87dae0069f204d6bc3..afd5d67e4ae73625e25a88bcf93ef79b34323602 100644 (file)
@@ -165,10 +165,10 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
 #endif
 
 static struct irqchip omap_irq_chip = {
-       .ack    = omap_mask_ack_irq,
-       .mask   = omap_mask_irq,
-       .unmask = omap_unmask_irq,
-       .wake   = omap_wake_irq,
+       .ack            = omap_mask_ack_irq,
+       .mask           = omap_mask_irq,
+       .unmask         = omap_unmask_irq,
+       .set_wake       = omap_wake_irq,
 };
 
 void __init omap_init_irq(void)
index efc2f657184edaf0245863b8782510985f28eb00..33dae99ec2d843290105013226519a47e3a50daf 100644 (file)
@@ -11,7 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
 obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
 obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
 obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARP_C7xx)   += corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_PXA_SHARP_C7xx)   += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
 obj-$(CONFIG_MACH_POODLE)      += poodle.o
 
 # Support for blinky lights
index 06ea730e8675f713784382b6d76a91e0d0695545..29185acdd9e1ea7e6eb7a8f9182e18bac37f35b1 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <asm/mach/sharpsl_param.h>
 #include <asm/hardware/scoop.h>
-#include <video/w100fb.h>
 
 #include "generic.h"
 
@@ -87,7 +86,7 @@ struct platform_device corgiscoop_device = {
  * also use scoop functions and this makes the power up/down order
  * work correctly.
  */
-static struct platform_device corgissp_device = {
+struct platform_device corgissp_device = {
        .name           = "corgi-ssp",
        .dev            = {
                .parent = &corgiscoop_device.dev,
@@ -97,41 +96,33 @@ static struct platform_device corgissp_device = {
 
 
 /*
- * Corgi w100 Frame Buffer Device
+ * Corgi Backlight Device
  */
-static struct w100fb_mach_info corgi_fb_info = {
-       .w100fb_ssp_send        = corgi_ssp_lcdtg_send,
-       .comadj                         = -1,
-       .phadadj                        = -1,
-};
-
-static struct resource corgi_fb_resources[] = {
-       [0] = {
-               .start          = 0x08000000,
-               .end            = 0x08ffffff,
-               .flags          = IORESOURCE_MEM,
+static struct platform_device corgibl_device = {
+       .name           = "corgi-bl",
+       .dev            = {
+               .parent = &corgifb_device.dev,
        },
+       .id             = -1,
 };
 
-static struct platform_device corgifb_device = {
-       .name           = "w100fb",
+
+/*
+ * Corgi Keyboard Device
+ */
+static struct platform_device corgikbd_device = {
+       .name           = "corgi-keyboard",
        .id             = -1,
-       .dev            = {
-               .platform_data  = &corgi_fb_info,
-               .parent = &corgissp_device.dev,
-       },
-       .num_resources  = ARRAY_SIZE(corgi_fb_resources),
-       .resource       = corgi_fb_resources,
 };
 
 
 /*
- * Corgi Backlight Device
+ * Corgi Touch Screen Device
  */
-static struct platform_device corgibl_device = {
-       .name           = "corgi-bl",
+static struct platform_device corgits_device = {
+       .name           = "corgi-ts",
        .dev            = {
-               .parent = &corgifb_device.dev,
+               .parent = &corgissp_device.dev,
        },
        .id             = -1,
 };
@@ -199,6 +190,11 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
        }
 }
 
+static int corgi_mci_get_ro(struct device *dev)
+{
+       return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP);
+}
+
 static void corgi_mci_exit(struct device *dev, void *data)
 {
        free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
@@ -208,11 +204,13 @@ static void corgi_mci_exit(struct device *dev, void *data)
 static struct pxamci_platform_data corgi_mci_platform_data = {
        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
        .init           = corgi_mci_init,
+       .get_ro         = corgi_mci_get_ro,
        .setpower       = corgi_mci_setpower,
        .exit           = corgi_mci_exit,
 };
 
 
+
 /*
  * USB Device Controller
  */
@@ -238,14 +236,13 @@ static struct platform_device *devices[] __initdata = {
        &corgiscoop_device,
        &corgissp_device,
        &corgifb_device,
+       &corgikbd_device,
        &corgibl_device,
+       &corgits_device,
 };
 
 static void __init corgi_init(void)
 {
-       corgi_fb_info.comadj=sharpsl_param.comadj;
-       corgi_fb_info.phadadj=sharpsl_param.phadadj;
-
        pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
        pxa_set_udc_info(&udc_info);
        pxa_set_mci_info(&corgi_mci_platform_data);
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
new file mode 100644 (file)
index 0000000..deac29c
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * linux/drivers/video/w100fb.c
+ *
+ * Corgi LCD Specific Code for ATI Imageon w100 (Wallaby)
+ *
+ * Copyright (C) 2005 Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <asm/arch/corgi.h>
+#include <asm/mach/sharpsl_param.h>
+#include <video/w100fb.h>
+
+/* Register Addresses */
+#define RESCTL_ADRS     0x00
+#define PHACTRL_ADRS    0x01
+#define DUTYCTRL_ADRS   0x02
+#define POWERREG0_ADRS  0x03
+#define POWERREG1_ADRS  0x04
+#define GPOR3_ADRS      0x05
+#define PICTRL_ADRS     0x06
+#define POLCTRL_ADRS    0x07
+
+/* Resgister Bit Definitions */
+#define RESCTL_QVGA     0x01
+#define RESCTL_VGA      0x00
+
+#define POWER1_VW_ON    0x01  /* VW Supply FET ON */
+#define POWER1_GVSS_ON  0x02  /* GVSS(-8V) Power Supply ON */
+#define POWER1_VDD_ON   0x04  /* VDD(8V),SVSS(-4V) Power Supply ON */
+
+#define POWER1_VW_OFF   0x00  /* VW Supply FET OFF */
+#define POWER1_GVSS_OFF 0x00  /* GVSS(-8V) Power Supply OFF */
+#define POWER1_VDD_OFF  0x00  /* VDD(8V),SVSS(-4V) Power Supply OFF */
+
+#define POWER0_COM_DCLK 0x01  /* COM Voltage DC Bias DAC Serial Data Clock */
+#define POWER0_COM_DOUT 0x02  /* COM Voltage DC Bias DAC Serial Data Out */
+#define POWER0_DAC_ON   0x04  /* DAC Power Supply ON */
+#define POWER0_COM_ON   0x08  /* COM Powewr Supply ON */
+#define POWER0_VCC5_ON  0x10  /* VCC5 Power Supply ON */
+
+#define POWER0_DAC_OFF  0x00  /* DAC Power Supply OFF */
+#define POWER0_COM_OFF  0x00  /* COM Powewr Supply OFF */
+#define POWER0_VCC5_OFF 0x00  /* VCC5 Power Supply OFF */
+
+#define PICTRL_INIT_STATE      0x01
+#define PICTRL_INIOFF          0x02
+#define PICTRL_POWER_DOWN      0x04
+#define PICTRL_COM_SIGNAL_OFF  0x08
+#define PICTRL_DAC_SIGNAL_OFF  0x10
+
+#define POLCTRL_SYNC_POL_FALL  0x01
+#define POLCTRL_EN_POL_FALL    0x02
+#define POLCTRL_DATA_POL_FALL  0x04
+#define POLCTRL_SYNC_ACT_H     0x08
+#define POLCTRL_EN_ACT_L       0x10
+
+#define POLCTRL_SYNC_POL_RISE  0x00
+#define POLCTRL_EN_POL_RISE    0x00
+#define POLCTRL_DATA_POL_RISE  0x00
+#define POLCTRL_SYNC_ACT_L     0x00
+#define POLCTRL_EN_ACT_H       0x00
+
+#define PHACTRL_PHASE_MANUAL   0x01
+#define DEFAULT_PHAD_QVGA     (9)
+#define DEFAULT_COMADJ        (125)
+
+/*
+ * This is only a psuedo I2C interface. We can't use the standard kernel
+ * routines as the interface is write only. We just assume the data is acked...
+ */
+static void lcdtg_ssp_i2c_send(u8 data)
+{
+       corgi_ssp_lcdtg_send(POWERREG0_ADRS, data);
+       udelay(10);
+}
+
+static void lcdtg_i2c_send_bit(u8 data)
+{
+       lcdtg_ssp_i2c_send(data);
+       lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
+       lcdtg_ssp_i2c_send(data);
+}
+
+static void lcdtg_i2c_send_start(u8 base)
+{
+       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
+       lcdtg_ssp_i2c_send(base);
+}
+
+static void lcdtg_i2c_send_stop(u8 base)
+{
+       lcdtg_ssp_i2c_send(base);
+       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
+       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+}
+
+static void lcdtg_i2c_send_byte(u8 base, u8 data)
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               if (data & 0x80)
+                       lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
+               else
+                       lcdtg_i2c_send_bit(base);
+               data <<= 1;
+       }
+}
+
+static void lcdtg_i2c_wait_ack(u8 base)
+{
+       lcdtg_i2c_send_bit(base);
+}
+
+static void lcdtg_set_common_voltage(u8 base_data, u8 data)
+{
+       /* Set Common Voltage to M62332FP via I2C */
+       lcdtg_i2c_send_start(base_data);
+       lcdtg_i2c_send_byte(base_data, 0x9c);
+       lcdtg_i2c_wait_ack(base_data);
+       lcdtg_i2c_send_byte(base_data, 0x00);
+       lcdtg_i2c_wait_ack(base_data);
+       lcdtg_i2c_send_byte(base_data, data);
+       lcdtg_i2c_wait_ack(base_data);
+       lcdtg_i2c_send_stop(base_data);
+}
+
+/* Set Phase Adjuct */
+static void lcdtg_set_phadadj(struct w100fb_par *par)
+{
+       int adj;
+       switch(par->xres) {
+               case 480:
+               case 640:
+                       /* Setting for VGA */
+                       adj = sharpsl_param.phadadj;
+                       if (adj < 0) {
+                               adj = PHACTRL_PHASE_MANUAL;
+                       } else {
+                               adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
+                       }
+                       break;
+               case 240:
+               case 320:
+               default:
+                       /* Setting for QVGA */
+                       adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
+                       break;
+       }
+
+       corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj);
+}
+
+static int lcd_inited;
+
+static void lcdtg_hw_init(struct w100fb_par *par)
+{
+       if (!lcd_inited) {
+               int comadj;
+
+               /* Initialize Internal Logic & Port */
+               corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE
+                               | PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF);
+
+               corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF
+                               | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+               corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+
+               /* VDD(+8V), SVSS(-4V) ON */
+               corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+               mdelay(3);
+
+               /* DAC ON */
+               corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
+                               | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+               /* INIB = H, INI = L  */
+               /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
+               corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
+
+               /* Set Common Voltage */
+               comadj = sharpsl_param.comadj;
+               if (comadj < 0)
+                       comadj = DEFAULT_COMADJ;
+               lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
+
+               /* VCC5 ON, DAC ON */
+               corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
+                               POWER0_COM_OFF | POWER0_VCC5_ON);
+
+               /* GVSS(-8V) ON, VDD ON */
+               corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+               mdelay(2);
+
+               /* COM SIGNAL ON (PICTL[3] = L) */
+               corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE);
+
+               /* COM ON, DAC ON, VCC5_ON */
+               corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
+                               | POWER0_COM_ON | POWER0_VCC5_ON);
+
+               /* VW ON, GVSS ON, VDD ON */
+               corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+               /* Signals output enable */
+               corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
+
+               /* Set Phase Adjuct */
+               lcdtg_set_phadadj(par);
+
+               /* Initialize for Input Signals from ATI */
+               corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
+                               | POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H);
+               udelay(1000);
+
+               lcd_inited=1;
+       } else {
+               lcdtg_set_phadadj(par);
+       }
+
+       switch(par->xres) {
+               case 480:
+               case 640:
+                       /* Set Lcd Resolution (VGA) */
+                       corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA);
+                       break;
+               case 240:
+               case 320:
+               default:
+                       /* Set Lcd Resolution (QVGA) */
+                       corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA);
+                       break;
+       }
+}
+
+static void lcdtg_suspend(struct w100fb_par *par)
+{
+       /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
+       mdelay(34);
+
+       /* (1)VW OFF */
+       corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+       /* (2)COM OFF */
+       corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
+       corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
+
+       /* (3)Set Common Voltage Bias 0V */
+       lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
+
+       /* (4)GVSS OFF */
+       corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+
+       /* (5)VCC5 OFF */
+       corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+       /* (6)Set PDWN, INIOFF, DACOFF */
+       corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
+                       PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
+
+       /* (7)DAC OFF */
+       corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+       /* (8)VDD OFF */
+       corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+
+       lcd_inited = 0;
+}
+
+static struct w100_tg_info corgi_lcdtg_info = {
+       .change=lcdtg_hw_init,
+       .suspend=lcdtg_suspend,
+       .resume=lcdtg_hw_init,
+};
+
+/*
+ * Corgi w100 Frame Buffer Device
+ */
+
+static struct w100_mem_info corgi_fb_mem = {
+       .ext_cntl          = 0x00040003,
+       .sdram_mode_reg    = 0x00650021,
+       .ext_timing_cntl   = 0x10002a4a,
+       .io_cntl           = 0x7ff87012,
+       .size              = 0x1fffff,
+};
+
+static struct w100_gen_regs corgi_fb_regs = {
+       .lcd_format    = 0x00000003,
+       .lcdd_cntl1    = 0x01CC0000,
+       .lcdd_cntl2    = 0x0003FFFF,
+       .genlcd_cntl1  = 0x00FFFF0D,
+       .genlcd_cntl2  = 0x003F3003,
+       .genlcd_cntl3  = 0x000102aa,
+};
+
+static struct w100_gpio_regs corgi_fb_gpio = {
+       .init_data1   = 0x000000bf,
+       .init_data2   = 0x00000000,
+       .gpio_dir1    = 0x00000000,
+       .gpio_oe1     = 0x03c0feff,
+       .gpio_dir2    = 0x00000000,
+       .gpio_oe2     = 0x00000000,
+};
+
+static struct w100_mode corgi_fb_modes[] = {
+{
+       .xres            = 480,
+       .yres            = 640,
+       .left_margin     = 0x56,
+       .right_margin    = 0x55,
+       .upper_margin    = 0x03,
+       .lower_margin    = 0x00,
+       .crtc_ss         = 0x82360056,
+       .crtc_ls         = 0xA0280000,
+       .crtc_gs         = 0x80280028,
+       .crtc_vpos_gs    = 0x02830002,
+       .crtc_rev        = 0x00400008,
+       .crtc_dclk       = 0xA0000000,
+       .crtc_gclk       = 0x8015010F,
+       .crtc_goe        = 0x80100110,
+       .crtc_ps1_active = 0x41060010,
+       .pll_freq        = 75,
+       .fast_pll_freq   = 100,
+       .sysclk_src      = CLK_SRC_PLL,
+       .sysclk_divider  = 0,
+       .pixclk_src      = CLK_SRC_PLL,
+       .pixclk_divider  = 2,
+       .pixclk_divider_rotated = 6,
+},{
+       .xres            = 240,
+       .yres            = 320,
+       .left_margin     = 0x27,
+       .right_margin    = 0x2e,
+       .upper_margin    = 0x01,
+       .lower_margin    = 0x00,
+       .crtc_ss         = 0x81170027,
+       .crtc_ls         = 0xA0140000,
+       .crtc_gs         = 0xC0140014,
+       .crtc_vpos_gs    = 0x00010141,
+       .crtc_rev        = 0x00400008,
+       .crtc_dclk       = 0xA0000000,
+       .crtc_gclk       = 0x8015010F,
+       .crtc_goe        = 0x80100110,
+       .crtc_ps1_active = 0x41060010,
+       .pll_freq        = 0,
+       .fast_pll_freq   = 0,
+       .sysclk_src      = CLK_SRC_XTAL,
+       .sysclk_divider  = 0,
+       .pixclk_src      = CLK_SRC_XTAL,
+       .pixclk_divider  = 1,
+       .pixclk_divider_rotated = 1,
+},
+
+};
+
+static struct w100fb_mach_info corgi_fb_info = {
+       .tg         = &corgi_lcdtg_info,
+       .init_mode  = INIT_MODE_ROTATED,
+       .mem        = &corgi_fb_mem,
+       .regs       = &corgi_fb_regs,
+       .modelist   = &corgi_fb_modes[0],
+       .num_modes  = 2,
+       .gpio       = &corgi_fb_gpio,
+       .xtal_freq  = 12500000,
+       .xtal_dbl   = 0,
+};
+
+static struct resource corgi_fb_resources[] = {
+       [0] = {
+               .start   = 0x08000000,
+               .end     = 0x08ffffff,
+               .flags   = IORESOURCE_MEM,
+       },
+};
+
+struct platform_device corgifb_device = {
+       .name           = "w100fb",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(corgi_fb_resources),
+       .resource       = corgi_fb_resources,
+       .dev            = {
+               .platform_data = &corgi_fb_info,
+               .parent = &corgissp_device.dev,
+       },
+
+};
index d4d03d0daaecdecc053b0cb04c033a20f5189d2d..06807c6ee68aa7d4cc15d22c674e31a32c80285a 100644 (file)
@@ -2,6 +2,13 @@ if ARCH_S3C2410
 
 menu "S3C24XX Implementations"
 
+config MACH_ANUBIS
+       bool "Simtec Electronics ANUBIS"
+       select CPU_S3C2440
+       help
+         Say Y gere if you are using the Simtec Electronics ANUBIS
+         development system
+
 config ARCH_BAST
        bool "Simtec Electronics BAST (EB2410ITX)"
        select CPU_S3C2410
@@ -11,6 +18,14 @@ config ARCH_BAST
 
          Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
 
+config BAST_PC104_IRQ
+       bool "BAST PC104 IRQ support"
+       depends on ARCH_BAST
+       default y
+       help
+         Say Y here to enable the PC104 IRQ routing on the
+         Simtec BAST (EB2410ITX)
+
 config ARCH_H1940
        bool "IPAQ H1940"
        select CPU_S3C2410
index 55ed7c7e57dabc091c9f6dd5c28f8bfa3ffd9b3b..b4f1e051c768a4dc06d583cdc52da5445e9fb190 100644 (file)
@@ -26,8 +26,13 @@ obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
 
+# bast extras
+
+obj-$(CONFIG_BAST_PC104_IRQ)   += bast-irq.o
+
 # machine specific support
 
+obj-$(CONFIG_MACH_ANUBIS)      += mach-anubis.o
 obj-$(CONFIG_ARCH_BAST)                += mach-bast.o usb-simtec.o
 obj-$(CONFIG_ARCH_H1940)       += mach-h1940.o
 obj-$(CONFIG_MACH_N30)         += mach-n30.o
index 49914709fa09a9b44007e26fac065530f84751a9..fbbeb05530061eaf24089f3e62acea6d078edad7 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/bast-irq.c
  *
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2003,2005 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -21,7 +21,8 @@
  *
  * Modifications:
  *     08-Jan-2003 BJD  Moved from central IRQ code
- */
+ *     21-Aug-2005 BJD  Fixed missing code and compile errors
+*/
 
 
 #include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
+#include <asm/mach-types.h>
+
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
 #include <asm/mach/irq.h>
-#include <asm/hardware/s3c2410/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+#include "irq.h"
 
 #if 0
 #include <asm/debug-ll.h>
@@ -79,15 +87,15 @@ bast_pc104_mask(unsigned int irqno)
        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
        temp &= ~bast_pc104_irqmasks[irqno];
        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
-
-       if (temp == 0)
-               bast_extint_mask(IRQ_ISA);
 }
 
 static void
-bast_pc104_ack(unsigned int irqno)
+bast_pc104_maskack(unsigned int irqno)
 {
-       bast_extint_ack(IRQ_ISA);
+       struct irqdesc *desc = irq_desc + IRQ_ISA;
+
+       bast_pc104_mask(irqno);
+       desc->chip->ack(IRQ_ISA);
 }
 
 static void
@@ -98,14 +106,12 @@ bast_pc104_unmask(unsigned int irqno)
        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
        temp |= bast_pc104_irqmasks[irqno];
        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
-
-       bast_extint_unmask(IRQ_ISA);
 }
 
-static struct bast_pc104_chip = {
+static struct irqchip  bast_pc104_chip = {
        .mask        = bast_pc104_mask,
        .unmask      = bast_pc104_unmask,
-       .ack         = bast_pc104_ack
+       .ack         = bast_pc104_maskack
 };
 
 static void
@@ -119,14 +125,49 @@ bast_irq_pc104_demux(unsigned int irq,
 
        stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
 
-       for (i = 0; i < 4 && stat != 0; i++) {
-               if (stat & 1) {
-                       irqno = bast_pc104_irqs[i];
-                       desc = irq_desc + irqno;
+       if (unlikely(stat == 0)) {
+               /* ack if we get an irq with nothing (ie, startup) */
+
+               desc = irq_desc + IRQ_ISA;
+               desc->chip->ack(IRQ_ISA);
+       } else {
+               /* handle the IRQ */
+
+               for (i = 0; stat != 0; i++, stat >>= 1) {
+                       if (stat & 1) {
+                               irqno = bast_pc104_irqs[i];
 
-                       desc_handle_irq(irqno, desc, regs);
+                               desc_handle_irq(irqno, irq_desc + irqno, regs);
+                       }
                }
+       }
+}
 
-               stat >>= 1;
+static __init int bast_irq_init(void)
+{
+       unsigned int i;
+
+       if (machine_is_bast()) {
+               printk(KERN_INFO "BAST PC104 IRQ routing, (c) 2005 Simtec Electronics\n");
+
+               /* zap all the IRQs */
+
+               __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
+
+               set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
+
+               /* reigster our IRQs */
+
+               for (i = 0; i < 4; i++) {
+                       unsigned int irqno = bast_pc104_irqs[i];
+
+                       set_irq_chip(irqno, &bast_pc104_chip);
+                       set_irq_handler(irqno, do_level_IRQ);
+                       set_irq_flags(irqno, IRQF_VALID);
+               }
        }
+
+       return 0;
 }
+
+arch_initcall(bast_irq_init);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
new file mode 100644 (file)
index 0000000..f87aa0b
--- /dev/null
@@ -0,0 +1,270 @@
+/* linux/arch/arm/mach-s3c2410/mach-anubis.c
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     02-May-2005 BJD  Copied from mach-bast.c
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/anubis-map.h>
+#include <asm/arch/anubis-irq.h>
+#include <asm/arch/anubis-cpld.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+
+static struct map_desc anubis_iodesc[] __initdata = {
+  /* ISA IO areas */
+
+  { (u32)S3C24XX_VA_ISA_BYTE, 0x0,        SZ_16M, MT_DEVICE },
+  { (u32)S3C24XX_VA_ISA_WORD, 0x0,        SZ_16M, MT_DEVICE },
+
+  /* we could possibly compress the next set down into a set of smaller tables
+   * pagetables, but that would mean using an L2 section, and it still means
+   * we cannot actually feed the same register to an LDR due to 16K spacing
+   */
+
+  /* CPLD control registers */
+
+  { (u32)ANUBIS_VA_CTRL1,      ANUBIS_PA_CTRL1,        SZ_4K, MT_DEVICE },
+  { (u32)ANUBIS_VA_CTRL2,      ANUBIS_PA_CTRL2,        SZ_4K, MT_DEVICE },
+
+  /* IDE drives */
+
+  { (u32)ANUBIS_IDEPRI,                S3C2410_CS3,            SZ_1M, MT_DEVICE },
+  { (u32)ANUBIS_IDEPRIAUX,     S3C2410_CS3+(1<<26),    SZ_1M, MT_DEVICE },
+
+  { (u32)ANUBIS_IDESEC,                S3C2410_CS4,            SZ_1M, MT_DEVICE },
+  { (u32)ANUBIS_IDESECAUX,     S3C2410_CS4+(1<<26),    SZ_1M, MT_DEVICE },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
+       [0] = {
+               .name           = "uclk",
+               .divisor        = 1,
+               .min_baud       = 0,
+               .max_baud       = 0,
+       },
+       [1] = {
+               .name           = "pclk",
+               .divisor        = 1,
+               .min_baud       = 0,
+               .max_baud       = 0.
+       }
+};
+
+
+static struct s3c2410_uartcfg anubis_uartcfgs[] = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+               .clocks      = anubis_serial_clocks,
+               .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+       },
+       [1] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+               .clocks      = anubis_serial_clocks,
+               .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+       },
+};
+
+/* NAND Flash on Anubis board */
+
+static int external_map[]   = { 2 };
+static int chip0_map[]      = { 0 };
+static int chip1_map[]      = { 1 };
+
+struct mtd_partition anubis_default_nand_part[] = {
+       [0] = {
+               .name   = "Boot Agent",
+               .size   = SZ_16K,
+               .offset = 0
+       },
+       [1] = {
+               .name   = "/boot",
+               .size   = SZ_4M - SZ_16K,
+               .offset = SZ_16K,
+       },
+       [2] = {
+               .name   = "user1",
+               .offset = SZ_4M,
+               .size   = SZ_32M - SZ_4M,
+       },
+       [3] = {
+               .name   = "user2",
+               .offset = SZ_32M,
+               .size   = MTDPART_SIZ_FULL,
+       }
+};
+
+/* the Anubis has 3 selectable slots for nand-flash, the two
+ * on-board chip areas, as well as the external slot.
+ *
+ * Note, there is no current hot-plug support for the External
+ * socket.
+*/
+
+static struct s3c2410_nand_set anubis_nand_sets[] = {
+       [1] = {
+               .name           = "External",
+               .nr_chips       = 1,
+               .nr_map         = external_map,
+               .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
+               .partitions     = anubis_default_nand_part
+       },
+       [0] = {
+               .name           = "chip0",
+               .nr_chips       = 1,
+               .nr_map         = chip0_map,
+               .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
+               .partitions     = anubis_default_nand_part
+       },
+       [2] = {
+               .name           = "chip1",
+               .nr_chips       = 1,
+               .nr_map         = chip1_map,
+               .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
+               .partitions     = anubis_default_nand_part
+       },
+};
+
+static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
+{
+       unsigned int tmp;
+
+       slot = set->nr_map[slot] & 3;
+
+       pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
+                slot, set, set->nr_map);
+
+       tmp = __raw_readb(ANUBIS_VA_CTRL1);
+       tmp &= ~ANUBIS_CTRL1_NANDSEL;
+       tmp |= slot;
+
+       pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
+
+       __raw_writeb(tmp, ANUBIS_VA_CTRL1);
+}
+
+static struct s3c2410_platform_nand anubis_nand_info = {
+       .tacls          = 25,
+       .twrph0         = 80,
+       .twrph1         = 80,
+       .nr_sets        = ARRAY_SIZE(anubis_nand_sets),
+       .sets           = anubis_nand_sets,
+       .select_chip    = anubis_nand_select,
+};
+
+
+/* Standard Anubis devices */
+
+static struct platform_device *anubis_devices[] __initdata = {
+       &s3c_device_usb,
+       &s3c_device_wdt,
+       &s3c_device_adc,
+       &s3c_device_i2c,
+       &s3c_device_rtc,
+       &s3c_device_nand,
+};
+
+static struct clk *anubis_clocks[] = {
+       &s3c24xx_dclk0,
+       &s3c24xx_dclk1,
+       &s3c24xx_clkout0,
+       &s3c24xx_clkout1,
+       &s3c24xx_uclk,
+};
+
+static struct s3c24xx_board anubis_board __initdata = {
+       .devices       = anubis_devices,
+       .devices_count = ARRAY_SIZE(anubis_devices),
+       .clocks        = anubis_clocks,
+       .clocks_count  = ARRAY_SIZE(anubis_clocks)
+};
+
+void __init anubis_map_io(void)
+{
+       /* initialise the clocks */
+
+       s3c24xx_dclk0.parent = NULL;
+       s3c24xx_dclk0.rate   = 12*1000*1000;
+
+       s3c24xx_dclk1.parent = NULL;
+       s3c24xx_dclk1.rate   = 24*1000*1000;
+
+       s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+       s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
+
+       s3c24xx_uclk.parent  = &s3c24xx_clkout1;
+
+       s3c_device_nand.dev.platform_data = &anubis_nand_info;
+
+       s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
+       s3c24xx_init_clocks(0);
+       s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
+       s3c24xx_set_board(&anubis_board);
+
+       /* ensure that the GPIO is setup */
+       s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+}
+
+MACHINE_START(ANUBIS, "Simtec-Anubis")
+       /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
+       .phys_ram       = S3C2410_SDRAM_PA,
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .map_io         = anubis_map_io,
+       .init_irq       = s3c24xx_init_irq,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
index 2cb798832223ad9d69c9c0c7feed90f3d48dbc70..4c7ccef6c207d0d2ba67349445324c1b87c2974a 100644 (file)
@@ -48,7 +48,7 @@ static __init int pm_simtec_init(void)
 
        /* check which machine we are running on */
 
-       if (!machine_is_bast() && !machine_is_vr1000())
+       if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
                return 0;
 
        printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
index 765a3a9ae032581b7f6c97217807fb8bc9cdc014..c0acfb2ad790a711c877afda5195be642288f690 100644 (file)
@@ -164,7 +164,7 @@ static void s3c2410_timer_setup (void)
 
        /* configure the system for whichever machine is in use */
 
-       if (machine_is_bast() || machine_is_vr1000()) {
+       if (machine_is_bast() || machine_is_vr1000() || machine_is_anubis()) {
                /* timer is at 12MHz, scaler is 1 */
                timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
                tcnt = 12000000 / HZ;
index 345365852f8cb999ed4f4ae5fec549236058d0d4..9693e9b4ffd1e70b024803b251b8a3629b5f41f9 100644 (file)
@@ -91,6 +91,13 @@ config OMAP_32K_TIMER_HZ
          Kernel internal timer frequency should be a divisor of 32768,
          such as 64 or 128.
 
+config OMAP_DM_TIMER
+       bool "Use dual-mode timer"
+       default n
+       depends on ARCH_OMAP16XX
+       help
+        Select this option if you want to use OMAP Dual-Mode timers.
+
 choice
        prompt "Low-level debug console UART"
        depends on ARCH_OMAP
@@ -107,6 +114,15 @@ config OMAP_LL_DEBUG_UART3
 
 endchoice
 
+config OMAP_SERIAL_WAKE
+       bool "Enable wake-up events for serial ports"
+       depends OMAP_MUX
+       default y
+       help
+         Select this option if you want to have your system wake up
+         to data on the serial RX line. This allows you to wake the
+         system from serial console.
+
 endmenu
 
 endif
index 531e11af54d4b6c5e2b7b21859bb41bef463e143..7e144f9cad1c3104c05cce4068fc3d7550ed9c45 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -15,3 +15,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 obj-$(CONFIG_PM) += pm.o sleep.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
+obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
+
index 59d91b3262ba0f3a0540a5c7ddb9f79f9bd73d44..52a58b2da2882553121810e75ba9aa1d168674b0 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/arch/usb.h>
 
 #include "clock.h"
+#include "sram.h"
 
 static LIST_HEAD(clocks);
 static DECLARE_MUTEX(clocks_sem);
@@ -141,7 +142,7 @@ static struct clk arm_ck = {
 static struct clk armper_ck = {
        .name           = "armper_ck",
        .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP730 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
                          RATE_CKCTL,
        .enable_reg     = ARM_IDLECT2,
        .enable_bit     = EN_PERCK,
@@ -385,7 +386,8 @@ static struct clk uart2_ck = {
        .name           = "uart2_ck",
        /* Direct from ULPD, no parent */
        .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
+                         ALWAYS_ENABLED,
        .enable_reg     = MOD_CONF_CTRL_0,
        .enable_bit     = 30,   /* Chooses between 12MHz and 48MHz */
        .set_rate       = &set_uart_rate,
@@ -443,6 +445,15 @@ static struct clk usb_hhc_ck16xx = {
        .enable_bit     = 8 /* UHOST_EN */,
 };
 
+static struct clk usb_dc_ck = {
+       .name           = "usb_dc_ck",
+       /* Direct from ULPD, no parent */
+       .rate           = 48000000,
+       .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED,
+       .enable_reg     = SOFT_REQ_REG,
+       .enable_bit     = 4,
+};
+
 static struct clk mclk_1510 = {
        .name           = "mclk",
        /* Direct from ULPD, no parent. May be enabled by ext hardware. */
@@ -552,6 +563,7 @@ static struct clk *  onchip_clks[] = {
        &uart3_16xx,
        &usb_clko,
        &usb_hhc_ck1510, &usb_hhc_ck16xx,
+       &usb_dc_ck,
        &mclk_1510,  &mclk_16xx,
        &bclk_1510,  &bclk_16xx,
        &mmc1_ck,
@@ -946,14 +958,13 @@ static int select_table_rate(struct clk *  clk, unsigned long rate)
        if (!ptr->rate)
                return -EINVAL;
 
-       if (!ptr->rate)
-               return -EINVAL;
+       /*
+        * In most cases we should not need to reprogram DPLL.
+        * Reprogramming the DPLL is tricky, it must be done from SRAM.
+        */
+       omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
 
-       if (unlikely(ck_dpll1.rate == 0)) {
-               omap_writew(ptr->dpllctl_val, DPLL_CTL);
-               ck_dpll1.rate = ptr->pll_rate;
-       }
-       omap_writew(ptr->ckctl_val, ARM_CKCTL);
+       ck_dpll1.rate = ptr->pll_rate;
        propagate_rate(&ck_dpll1);
        return 0;
 }
@@ -1224,9 +1235,11 @@ int __init clk_init(void)
 #endif
        /* Cache rates for clocks connected to ck_ref (not dpll1) */
        propagate_rate(&ck_ref);
-       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld/%ld MHz\n",
+       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
+               "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
               ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-              ck_dpll1.rate, arm_ck.rate);
+              ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+              arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
 
 #ifdef CONFIG_MACH_OMAP_PERSEUS2
        /* Select slicer output as OMAP input clock */
@@ -1271,7 +1284,9 @@ static int __init omap_late_clk_reset(void)
        struct clk *p;
        __u32 regval32;
 
-       omap_writew(0, SOFT_REQ_REG);
+       /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+       regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
+       omap_writew(regval32, SOFT_REQ_REG);
        omap_writew(0, SOFT_REQ_REG2);
 
        list_for_each_entry(p, &clocks, node) {
index ea967a8f6ce52716a8292dcdf1f5fcf890e27d99..6cb20aea7f518b22dbd9b25a6d93cc6ac93fd1ff 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/hardware/clock.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
+#include <asm/setup.h>
 
 #include <asm/arch/board.h>
 #include <asm/arch/mux.h>
 
 #define NO_LENGTH_CHECK 0xffffffff
 
-extern int omap_bootloader_tag_len;
-extern u8 omap_bootloader_tag[];
+unsigned char omap_bootloader_tag[512];
+int omap_bootloader_tag_len;
 
 struct omap_board_config_kernel *omap_board_config;
-int omap_board_config_size = 0;
+int omap_board_config_size;
 
 static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
 {
index c0a5c2fa42bdf0784038e21fe14455c97e74b880..da7b6514565884e894d82f729ee38274d63ae46d 100644 (file)
@@ -425,7 +425,7 @@ static int dma_handle_ch(int ch)
                dma_chan[ch + 6].saved_csr = csr >> 7;
                csr &= 0x7f;
        }
-       if (!csr)
+       if ((csr & 0x3f) == 0)
                return 0;
        if (unlikely(dma_chan[ch].dev_id == -1)) {
                printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
@@ -890,11 +890,11 @@ void omap_enable_lcd_dma(void)
        w |= 1 << 8;
        omap_writew(w, OMAP1610_DMA_LCD_CTRL);
 
+       lcd_dma.active = 1;
+
        w = omap_readw(OMAP1610_DMA_LCD_CCR);
        w |= 1 << 7;
        omap_writew(w, OMAP1610_DMA_LCD_CCR);
-
-       lcd_dma.active = 1;
 }
 
 void omap_setup_lcd_dma(void)
@@ -965,8 +965,8 @@ void omap_clear_dma(int lch)
  */
 dma_addr_t omap_get_dma_src_pos(int lch)
 {
-       return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
-                            (OMAP_DMA_CSSA_U(lch) << 16));
+       return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) |
+       (omap_readw(OMAP_DMA_CSSA_U(lch)) << 16));
 }
 
 /*
@@ -979,8 +979,18 @@ dma_addr_t omap_get_dma_src_pos(int lch)
  */
 dma_addr_t omap_get_dma_dst_pos(int lch)
 {
-       return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
-                            (OMAP_DMA_CDSA_U(lch) << 16));
+       return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) |
+       (omap_readw(OMAP_DMA_CDSA_U(lch)) << 16));
+}
+
+/*
+ * Returns current source transfer counting for the given DMA channel.
+ * Can be used to monitor the progress of a transfer inside a  block.
+ * It must be called with disabled interrupts.
+ */
+int omap_get_dma_src_addr_counter(int lch)
+{
+       return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch));
 }
 
 int omap_dma_running(void)
@@ -1076,6 +1086,7 @@ arch_initcall(omap_init_dma);
 
 EXPORT_SYMBOL(omap_get_dma_src_pos);
 EXPORT_SYMBOL(omap_get_dma_dst_pos);
+EXPORT_SYMBOL(omap_get_dma_src_addr_counter);
 EXPORT_SYMBOL(omap_clear_dma);
 EXPORT_SYMBOL(omap_set_dma_priority);
 EXPORT_SYMBOL(omap_request_dma);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
new file mode 100644 (file)
index 0000000..a1468d7
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * linux/arch/arm/plat-omap/dmtimer.c
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/dmtimer.h>
+#include <asm/io.h>
+#include <asm/arch/irqs.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#define OMAP_TIMER_COUNT               8
+
+#define OMAP_TIMER_ID_REG              0x00
+#define OMAP_TIMER_OCP_CFG_REG         0x10
+#define OMAP_TIMER_SYS_STAT_REG                0x14
+#define OMAP_TIMER_STAT_REG            0x18
+#define OMAP_TIMER_INT_EN_REG          0x1c
+#define OMAP_TIMER_WAKEUP_EN_REG       0x20
+#define OMAP_TIMER_CTRL_REG            0x24
+#define OMAP_TIMER_COUNTER_REG         0x28
+#define OMAP_TIMER_LOAD_REG            0x2c
+#define OMAP_TIMER_TRIGGER_REG         0x30
+#define OMAP_TIMER_WRITE_PEND_REG      0x34
+#define OMAP_TIMER_MATCH_REG           0x38
+#define OMAP_TIMER_CAPTURE_REG         0x3c
+#define OMAP_TIMER_IF_CTRL_REG         0x40
+
+
+static struct dmtimer_info_struct {
+       struct list_head        unused_timers;
+       struct list_head        reserved_timers;
+} dm_timer_info;
+
+static struct omap_dm_timer dm_timers[] = {
+       { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },
+       { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },
+       { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },
+       { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },
+       { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },
+       { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },
+       { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },
+       { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },
+       { .base=0x0 },
+};
+
+
+static spinlock_t dm_timer_lock;
+
+
+inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
+{
+       omap_writel(value, timer->base + reg);
+       while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
+               ;
+}
+
+u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
+{
+       return omap_readl(timer->base + reg);
+}
+
+int omap_dm_timers_active(void)
+{
+       struct omap_dm_timer *timer;
+
+       for (timer = &dm_timers[0]; timer->base; ++timer)
+               if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
+                   OMAP_TIMER_CTRL_ST)
+                       return 1;
+
+       return 0;
+}
+
+
+void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+{
+       int n = (timer - dm_timers) << 1;
+       u32 l;
+
+       l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+       l |= source << n;
+       omap_writel(l, MOD_CONF_CTRL_1);
+}
+
+
+static void omap_dm_timer_reset(struct omap_dm_timer *timer)
+{
+       /* Reset and set posted mode */
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
+
+       omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
+}
+
+
+
+struct omap_dm_timer * omap_dm_timer_request(void)
+{
+       struct omap_dm_timer *timer = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dm_timer_lock, flags);
+       if (!list_empty(&dm_timer_info.unused_timers)) {
+               timer = (struct omap_dm_timer *)
+                               dm_timer_info.unused_timers.next;
+               list_move_tail((struct list_head *)timer,
+                               &dm_timer_info.reserved_timers);
+       }
+       spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+       return timer;
+}
+
+
+void omap_dm_timer_free(struct omap_dm_timer *timer)
+{
+       unsigned long flags;
+
+       omap_dm_timer_reset(timer);
+
+       spin_lock_irqsave(&dm_timer_lock, flags);
+       list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
+       spin_unlock_irqrestore(&dm_timer_lock, flags);
+}
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+                               unsigned int value)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+}
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
+{
+       return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+}
+
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+}
+
+void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer)
+{
+       u32 l;
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+       l |= OMAP_TIMER_CTRL_AR;
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
+}
+
+void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
+{
+       u32 l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+       l |= value & 0x3;
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_start(struct omap_dm_timer *timer)
+{
+       u32 l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+       l |= OMAP_TIMER_CTRL_ST;
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_stop(struct omap_dm_timer *timer)
+{
+       u32 l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+       l &= ~0x1;
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
+{
+       return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+}
+
+void omap_dm_timer_reset_counter(struct omap_dm_timer *timer)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);
+}
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+}
+
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match)
+{
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+}
+
+void omap_dm_timer_enable_compare(struct omap_dm_timer *timer)
+{
+       u32 l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+       l |= OMAP_TIMER_CTRL_CE;
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+
+static inline void __dm_timer_init(void)
+{
+       struct omap_dm_timer *timer;
+
+       spin_lock_init(&dm_timer_lock);
+       INIT_LIST_HEAD(&dm_timer_info.unused_timers);
+       INIT_LIST_HEAD(&dm_timer_info.reserved_timers);
+
+       timer = &dm_timers[0];
+       while (timer->base) {
+               list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
+               omap_dm_timer_reset(timer);
+               timer++;
+       }
+}
+
+static int __init omap_dm_timer_init(void)
+{
+       if (cpu_is_omap16xx())
+               __dm_timer_init();
+       return 0;
+}
+
+arch_initcall(omap_dm_timer_init);
index aa481ea3d702c0fb00035a1941be2bdbc0d999eb..55059a24ad419da31fbc026f5345a9db386ee9fc 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Support functions for OMAP GPIO
  *
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003-2005 Nokia Corporation
  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  *
  * This program is free software; you can redistribute it and/or modify
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
 
 #include <asm/hardware.h>
+#include <asm/hardware/clock.h>
 #include <asm/irq.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/gpio.h>
@@ -29,7 +32,7 @@
 /*
  * OMAP1510 GPIO registers
  */
-#define OMAP1510_GPIO_BASE             0xfffce000
+#define OMAP1510_GPIO_BASE             (void __iomem *)0xfffce000
 #define OMAP1510_GPIO_DATA_INPUT       0x00
 #define OMAP1510_GPIO_DATA_OUTPUT      0x04
 #define OMAP1510_GPIO_DIR_CONTROL      0x08
 /*
  * OMAP1610 specific GPIO registers
  */
-#define OMAP1610_GPIO1_BASE            0xfffbe400
-#define OMAP1610_GPIO2_BASE            0xfffbec00
-#define OMAP1610_GPIO3_BASE            0xfffbb400
-#define OMAP1610_GPIO4_BASE            0xfffbbc00
+#define OMAP1610_GPIO1_BASE            (void __iomem *)0xfffbe400
+#define OMAP1610_GPIO2_BASE            (void __iomem *)0xfffbec00
+#define OMAP1610_GPIO3_BASE            (void __iomem *)0xfffbb400
+#define OMAP1610_GPIO4_BASE            (void __iomem *)0xfffbbc00
 #define OMAP1610_GPIO_REVISION         0x0000
 #define OMAP1610_GPIO_SYSCONFIG                0x0010
 #define OMAP1610_GPIO_SYSSTATUS                0x0014
 #define OMAP1610_GPIO_IRQSTATUS1       0x0018
 #define OMAP1610_GPIO_IRQENABLE1       0x001c
+#define OMAP1610_GPIO_WAKEUPENABLE     0x0028
 #define OMAP1610_GPIO_DATAIN           0x002c
 #define OMAP1610_GPIO_DATAOUT          0x0030
 #define OMAP1610_GPIO_DIRECTION                0x0034
 #define OMAP1610_GPIO_EDGE_CTRL1       0x0038
 #define OMAP1610_GPIO_EDGE_CTRL2       0x003c
 #define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
+#define OMAP1610_GPIO_CLEAR_WAKEUPENA  0x00a8
 #define OMAP1610_GPIO_CLEAR_DATAOUT    0x00b0
 #define OMAP1610_GPIO_SET_IRQENABLE1   0x00dc
+#define OMAP1610_GPIO_SET_WAKEUPENA    0x00e8
 #define OMAP1610_GPIO_SET_DATAOUT      0x00f0
 
 /*
  * OMAP730 specific GPIO registers
  */
-#define OMAP730_GPIO1_BASE             0xfffbc000
-#define OMAP730_GPIO2_BASE             0xfffbc800
-#define OMAP730_GPIO3_BASE             0xfffbd000
-#define OMAP730_GPIO4_BASE             0xfffbd800
-#define OMAP730_GPIO5_BASE             0xfffbe000
-#define OMAP730_GPIO6_BASE             0xfffbe800
+#define OMAP730_GPIO1_BASE             (void __iomem *)0xfffbc000
+#define OMAP730_GPIO2_BASE             (void __iomem *)0xfffbc800
+#define OMAP730_GPIO3_BASE             (void __iomem *)0xfffbd000
+#define OMAP730_GPIO4_BASE             (void __iomem *)0xfffbd800
+#define OMAP730_GPIO5_BASE             (void __iomem *)0xfffbe000
+#define OMAP730_GPIO6_BASE             (void __iomem *)0xfffbe800
 #define OMAP730_GPIO_DATA_INPUT                0x00
 #define OMAP730_GPIO_DATA_OUTPUT       0x04
 #define OMAP730_GPIO_DIR_CONTROL       0x08
 #define OMAP730_GPIO_INT_MASK          0x10
 #define OMAP730_GPIO_INT_STATUS                0x14
 
+/*
+ * omap24xx specific GPIO registers
+ */
+#define OMAP24XX_GPIO1_BASE            (void __iomem *)0x48018000
+#define OMAP24XX_GPIO2_BASE            (void __iomem *)0x4801a000
+#define OMAP24XX_GPIO3_BASE            (void __iomem *)0x4801c000
+#define OMAP24XX_GPIO4_BASE            (void __iomem *)0x4801e000
+#define OMAP24XX_GPIO_REVISION         0x0000
+#define OMAP24XX_GPIO_SYSCONFIG                0x0010
+#define OMAP24XX_GPIO_SYSSTATUS                0x0014
+#define OMAP24XX_GPIO_IRQSTATUS1       0x0018
+#define OMAP24XX_GPIO_IRQENABLE1       0x001c
+#define OMAP24XX_GPIO_CTRL             0x0030
+#define OMAP24XX_GPIO_OE               0x0034
+#define OMAP24XX_GPIO_DATAIN           0x0038
+#define OMAP24XX_GPIO_DATAOUT          0x003c
+#define OMAP24XX_GPIO_LEVELDETECT0     0x0040
+#define OMAP24XX_GPIO_LEVELDETECT1     0x0044
+#define OMAP24XX_GPIO_RISINGDETECT     0x0048
+#define OMAP24XX_GPIO_FALLINGDETECT    0x004c
+#define OMAP24XX_GPIO_CLEARIRQENABLE1  0x0060
+#define OMAP24XX_GPIO_SETIRQENABLE1    0x0064
+#define OMAP24XX_GPIO_CLEARWKUENA      0x0080
+#define OMAP24XX_GPIO_SETWKUENA                0x0084
+#define OMAP24XX_GPIO_CLEARDATAOUT     0x0090
+#define OMAP24XX_GPIO_SETDATAOUT       0x0094
+
 #define OMAP_MPUIO_MASK                (~OMAP_MAX_GPIO_LINES & 0xff)
 
 struct gpio_bank {
-       u32 base;
+       void __iomem *base;
        u16 irq;
        u16 virtual_irq_start;
-       u8 method;
+       int method;
        u32 reserved_map;
+       u32 suspend_wakeup;
+       u32 saved_wakeup;
        spinlock_t lock;
 };
 
@@ -93,8 +128,9 @@ struct gpio_bank {
 #define METHOD_GPIO_1510       1
 #define METHOD_GPIO_1610       2
 #define METHOD_GPIO_730                3
+#define METHOD_GPIO_24XX       4
 
-#if defined(CONFIG_ARCH_OMAP16XX)
+#ifdef CONFIG_ARCH_OMAP16XX
 static struct gpio_bank gpio_bank_1610[5] = {
        { OMAP_MPUIO_BASE,     INT_MPUIO,           IH_MPUIO_BASE,     METHOD_MPUIO},
        { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,      IH_GPIO_BASE,      METHOD_GPIO_1610 },
@@ -123,6 +159,15 @@ static struct gpio_bank gpio_bank_730[7] = {
 };
 #endif
 
+#ifdef CONFIG_ARCH_OMAP24XX
+static struct gpio_bank gpio_bank_24xx[4] = {
+       { OMAP24XX_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,       METHOD_GPIO_24XX },
+       { OMAP24XX_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,  METHOD_GPIO_24XX },
+       { OMAP24XX_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,  METHOD_GPIO_24XX },
+       { OMAP24XX_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,  METHOD_GPIO_24XX },
+};
+#endif
+
 static struct gpio_bank *gpio_bank;
 static int gpio_bank_count;
 
@@ -149,14 +194,23 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
                return &gpio_bank[1 + (gpio >> 5)];
        }
 #endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (cpu_is_omap24xx())
+               return &gpio_bank[gpio >> 5];
+#endif
 }
 
 static inline int get_gpio_index(int gpio)
 {
+#ifdef CONFIG_ARCH_OMAP730
        if (cpu_is_omap730())
                return gpio & 0x1f;
-       else
-               return gpio & 0x0f;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (cpu_is_omap24xx())
+               return gpio & 0x1f;
+#endif
+       return gpio & 0x0f;
 }
 
 static inline int gpio_valid(int gpio)
@@ -179,6 +233,10 @@ static inline int gpio_valid(int gpio)
 #ifdef CONFIG_ARCH_OMAP730
        if (cpu_is_omap730() && gpio < 192)
                return 0;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (cpu_is_omap24xx() && gpio < 128)
+               return 0;
 #endif
        return -1;
 }
@@ -195,7 +253,7 @@ static int check_gpio(int gpio)
 
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
 {
-       u32 reg = bank->base;
+       void __iomem *reg = bank->base;
        u32 l;
 
        switch (bank->method) {
@@ -211,6 +269,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_DIR_CONTROL;
                break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_OE;
+               break;
        }
        l = __raw_readl(reg);
        if (is_input)
@@ -234,7 +295,7 @@ void omap_set_gpio_direction(int gpio, int is_input)
 
 static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
 {
-       u32 reg = bank->base;
+       void __iomem *reg = bank->base;
        u32 l = 0;
 
        switch (bank->method) {
@@ -269,6 +330,13 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                else
                        l &= ~(1 << gpio);
                break;
+       case METHOD_GPIO_24XX:
+               if (enable)
+                       reg += OMAP24XX_GPIO_SETDATAOUT;
+               else
+                       reg += OMAP24XX_GPIO_CLEARDATAOUT;
+               l = 1 << gpio;
+               break;
        default:
                BUG();
                return;
@@ -291,7 +359,7 @@ void omap_set_gpio_dataout(int gpio, int enable)
 int omap_get_gpio_datain(int gpio)
 {
        struct gpio_bank *bank;
-       u32 reg;
+       void __iomem *reg;
 
        if (check_gpio(gpio) < 0)
                return -1;
@@ -310,109 +378,132 @@ int omap_get_gpio_datain(int gpio)
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_DATA_INPUT;
                break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_DATAIN;
+               break;
        default:
                BUG();
                return -1;
        }
-       return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+       return (__raw_readl(reg)
+                       & (1 << get_gpio_index(gpio))) != 0;
 }
 
-static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge)
+#define MOD_REG_BIT(reg, bit_mask, set)        \
+do {   \
+       int l = __raw_readl(base + reg); \
+       if (set) l |= bit_mask; \
+       else l &= ~bit_mask; \
+       __raw_writel(l, base + reg); \
+} while(0)
+
+static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger)
 {
-       u32 reg = bank->base;
-       u32 l;
+       u32 gpio_bit = 1 << gpio;
+
+       MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+               trigger & IRQT_LOW);
+       MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+               trigger & IRQT_HIGH);
+       MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+               trigger & IRQT_RISING);
+       MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+               trigger & IRQT_FALLING);
+       /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
+        * triggering requested. */
+}
+
+static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+{
+       void __iomem *reg = bank->base;
+       u32 l = 0;
 
        switch (bank->method) {
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_INT_EDGE;
                l = __raw_readl(reg);
-               if (edge == OMAP_GPIO_RISING_EDGE)
+               if (trigger == IRQT_RISING)
                        l |= 1 << gpio;
-               else
+               else if (trigger == IRQT_FALLING)
                        l &= ~(1 << gpio);
-               __raw_writel(l, reg);
+               else
+                       goto bad;
                break;
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
-               if (edge == OMAP_GPIO_RISING_EDGE)
+               if (trigger == IRQT_RISING)
                        l |= 1 << gpio;
-               else
+               else if (trigger == IRQT_FALLING)
                        l &= ~(1 << gpio);
-               __raw_writel(l, reg);
+               else
+                       goto bad;
                break;
        case METHOD_GPIO_1610:
-               edge &= 0x03;
                if (gpio & 0x08)
                        reg += OMAP1610_GPIO_EDGE_CTRL2;
                else
                        reg += OMAP1610_GPIO_EDGE_CTRL1;
                gpio &= 0x07;
+               /* We allow only edge triggering, i.e. two lowest bits */
+               if (trigger & ~IRQT_BOTHEDGE)
+                       BUG();
+               /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
+               trigger &= 0x03;
                l = __raw_readl(reg);
                l &= ~(3 << (gpio << 1));
-               l |= edge << (gpio << 1);
-               __raw_writel(l, reg);
+               l |= trigger << (gpio << 1);
                break;
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
-               if (edge == OMAP_GPIO_RISING_EDGE)
+               if (trigger == IRQT_RISING)
                        l |= 1 << gpio;
-               else
+               else if (trigger == IRQT_FALLING)
                        l &= ~(1 << gpio);
-               __raw_writel(l, reg);
+               else
+                       goto bad;
+               break;
+       case METHOD_GPIO_24XX:
+               set_24xx_gpio_triggering(reg, gpio, trigger);
                break;
        default:
                BUG();
-               return;
+               goto bad;
        }
+       __raw_writel(l, reg);
+       return 0;
+bad:
+       return -EINVAL;
 }
 
-void omap_set_gpio_edge_ctrl(int gpio, int edge)
+static int gpio_irq_type(unsigned irq, unsigned type)
 {
        struct gpio_bank *bank;
+       unsigned gpio;
+       int retval;
+
+       if (irq > IH_MPUIO_BASE)
+               gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
+       else
+               gpio = irq - IH_GPIO_BASE;
 
        if (check_gpio(gpio) < 0)
-               return;
+               return -EINVAL;
+
+       if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+               return -EINVAL;
+
        bank = get_gpio_bank(gpio);
        spin_lock(&bank->lock);
-       _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge);
+       retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
        spin_unlock(&bank->lock);
-}
-
-
-static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
-{
-       u32 reg = bank->base, l;
-
-       switch (bank->method) {
-       case METHOD_MPUIO:
-               l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE);
-               return (l & (1 << gpio)) ?
-                       OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
-       case METHOD_GPIO_1510:
-               l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL);
-               return (l & (1 << gpio)) ?
-                       OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
-       case METHOD_GPIO_1610:
-               if (gpio & 0x08)
-                       reg += OMAP1610_GPIO_EDGE_CTRL2;
-               else
-                       reg += OMAP1610_GPIO_EDGE_CTRL1;
-               return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03;
-       case METHOD_GPIO_730:
-               l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL);
-               return (l & (1 << gpio)) ?
-                       OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
-       default:
-               BUG();
-               return -1;
-       }
+       return retval;
 }
 
 static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
-       u32 reg = bank->base;
+       void __iomem *reg = bank->base;
 
        switch (bank->method) {
        case METHOD_MPUIO:
@@ -428,6 +519,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_STATUS;
                break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_IRQSTATUS1;
+               break;
        default:
                BUG();
                return;
@@ -442,7 +536,7 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
 
 static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
 {
-       u32 reg = bank->base;
+       void __iomem *reg = bank->base;
        u32 l;
 
        switch (bank->method) {
@@ -477,6 +571,13 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                else
                        l |= gpio_mask;
                break;
+       case METHOD_GPIO_24XX:
+               if (enable)
+                       reg += OMAP24XX_GPIO_SETIRQENABLE1;
+               else
+                       reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
+               l = gpio_mask;
+               break;
        default:
                BUG();
                return;
@@ -489,6 +590,50 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
        _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
 }
 
+/*
+ * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
+ * 1510 does not seem to have a wake-up register. If JTAG is connected
+ * to the target, system will wake up always on GPIO events. While
+ * system is running all registered GPIO interrupts need to have wake-up
+ * enabled. When system is suspended, only selected GPIO interrupts need
+ * to have wake-up enabled.
+ */
+static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
+{
+       switch (bank->method) {
+       case METHOD_GPIO_1610:
+       case METHOD_GPIO_24XX:
+               spin_lock(&bank->lock);
+               if (enable)
+                       bank->suspend_wakeup |= (1 << gpio);
+               else
+                       bank->suspend_wakeup &= ~(1 << gpio);
+               spin_unlock(&bank->lock);
+               return 0;
+       default:
+               printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
+                      bank->method);
+               return -EINVAL;
+       }
+}
+
+/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
+static int gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+       unsigned int gpio = irq - IH_GPIO_BASE;
+       struct gpio_bank *bank;
+       int retval;
+
+       if (check_gpio(gpio) < 0)
+               return -ENODEV;
+       bank = get_gpio_bank(gpio);
+       spin_lock(&bank->lock);
+       retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
+       spin_unlock(&bank->lock);
+
+       return retval;
+}
+
 int omap_request_gpio(int gpio)
 {
        struct gpio_bank *bank;
@@ -505,14 +650,32 @@ int omap_request_gpio(int gpio)
                return -1;
        }
        bank->reserved_map |= (1 << get_gpio_index(gpio));
+
+       /* Set trigger to none. You need to enable the trigger after request_irq */
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
+
 #ifdef CONFIG_ARCH_OMAP1510
        if (bank->method == METHOD_GPIO_1510) {
-               u32 reg;
+               void __iomem *reg;
 
-               /* Claim the pin for the ARM */
+               /* Claim the pin for MPU */
                reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
                __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
        }
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       if (bank->method == METHOD_GPIO_1610) {
+               /* Enable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+               __raw_writel(1 << get_gpio_index(gpio), reg);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (bank->method == METHOD_GPIO_24XX) {
+               /* Enable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA;
+               __raw_writel(1 << get_gpio_index(gpio), reg);
+       }
 #endif
        spin_unlock(&bank->lock);
 
@@ -533,6 +696,20 @@ void omap_free_gpio(int gpio)
                spin_unlock(&bank->lock);
                return;
        }
+#ifdef CONFIG_ARCH_OMAP16XX
+       if (bank->method == METHOD_GPIO_1610) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+               __raw_writel(1 << get_gpio_index(gpio), reg);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (bank->method == METHOD_GPIO_24XX) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+               __raw_writel(1 << get_gpio_index(gpio), reg);
+       }
+#endif
        bank->reserved_map &= ~(1 << get_gpio_index(gpio));
        _set_gpio_direction(bank, get_gpio_index(gpio), 1);
        _set_gpio_irqenable(bank, gpio, 0);
@@ -552,7 +729,7 @@ void omap_free_gpio(int gpio)
 static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
                             struct pt_regs *regs)
 {
-       u32 isr_reg = 0;
+       void __iomem *isr_reg = NULL;
        u32 isr;
        unsigned int gpio_irq;
        struct gpio_bank *bank;
@@ -574,24 +751,30 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
        if (bank->method == METHOD_GPIO_730)
                isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
 #endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (bank->method == METHOD_GPIO_24XX)
+               isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
+#endif
 
-       isr = __raw_readl(isr_reg);
-       _enable_gpio_irqbank(bank, isr, 0);
-       _clear_gpio_irqbank(bank, isr);
-       _enable_gpio_irqbank(bank, isr, 1);
-       desc->chip->unmask(irq);
-
-       if (unlikely(!isr))
-               return;
-
-       gpio_irq = bank->virtual_irq_start;
-       for (; isr != 0; isr >>= 1, gpio_irq++) {
-               struct irqdesc *d;
-               if (!(isr & 1))
-                       continue;
-               d = irq_desc + gpio_irq;
-               desc_handle_irq(gpio_irq, d, regs);
-       }
+       while(1) {
+               isr = __raw_readl(isr_reg);
+               _enable_gpio_irqbank(bank, isr, 0);
+               _clear_gpio_irqbank(bank, isr);
+               _enable_gpio_irqbank(bank, isr, 1);
+               desc->chip->unmask(irq);
+
+               if (!isr)
+                       break;
+
+               gpio_irq = bank->virtual_irq_start;
+               for (; isr != 0; isr >>= 1, gpio_irq++) {
+                       struct irqdesc *d;
+                       if (!(isr & 1))
+                               continue;
+                       d = irq_desc + gpio_irq;
+                       desc_handle_irq(gpio_irq, d, regs);
+               }
+        }
 }
 
 static void gpio_ack_irq(unsigned int irq)
@@ -613,14 +796,10 @@ static void gpio_mask_irq(unsigned int irq)
 static void gpio_unmask_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
+       unsigned int gpio_idx = get_gpio_index(gpio);
        struct gpio_bank *bank = get_gpio_bank(gpio);
 
-       if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
-               printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n",
-                      gpio);
-               _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
-       }
-       _set_gpio_irqenable(bank, gpio, 1);
+       _set_gpio_irqenable(bank, gpio_idx, 1);
 }
 
 static void mpuio_ack_irq(unsigned int irq)
@@ -645,9 +824,11 @@ static void mpuio_unmask_irq(unsigned int irq)
 }
 
 static struct irqchip gpio_irq_chip = {
-       .ack    = gpio_ack_irq,
-       .mask   = gpio_mask_irq,
-       .unmask = gpio_unmask_irq,
+       .ack            = gpio_ack_irq,
+       .mask           = gpio_mask_irq,
+       .unmask         = gpio_unmask_irq,
+       .set_type       = gpio_irq_type,
+       .set_wake       = gpio_wake_enable,
 };
 
 static struct irqchip mpuio_irq_chip = {
@@ -657,6 +838,7 @@ static struct irqchip mpuio_irq_chip = {
 };
 
 static int initialized = 0;
+static struct clk * gpio_ck = NULL;
 
 static int __init _omap_gpio_init(void)
 {
@@ -665,6 +847,14 @@ static int __init _omap_gpio_init(void)
 
        initialized = 1;
 
+       if (cpu_is_omap1510()) {
+               gpio_ck = clk_get(NULL, "arm_gpio_ck");
+               if (IS_ERR(gpio_ck))
+                       printk("Could not get arm_gpio_ck\n");
+               else
+                       clk_use(gpio_ck);
+       }
+
 #ifdef CONFIG_ARCH_OMAP1510
        if (cpu_is_omap1510()) {
                printk(KERN_INFO "OMAP1510 GPIO hardware\n");
@@ -674,7 +864,7 @@ static int __init _omap_gpio_init(void)
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
        if (cpu_is_omap16xx()) {
-               int rev;
+               u32 rev;
 
                gpio_bank_count = 5;
                gpio_bank = gpio_bank_1610;
@@ -689,6 +879,17 @@ static int __init _omap_gpio_init(void)
                gpio_bank_count = 7;
                gpio_bank = gpio_bank_730;
        }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (cpu_is_omap24xx()) {
+               int rev;
+
+               gpio_bank_count = 4;
+               gpio_bank = gpio_bank_24xx;
+               rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+               printk(KERN_INFO "OMAP24xx GPIO hardware version %d.%d\n",
+                       (rev >> 4) & 0x0f, rev & 0x0f);
+       }
 #endif
        for (i = 0; i < gpio_bank_count; i++) {
                int j, gpio_count = 16;
@@ -710,6 +911,7 @@ static int __init _omap_gpio_init(void)
                if (bank->method == METHOD_GPIO_1610) {
                        __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
                        __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
+                       __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
                }
 #endif
 #ifdef CONFIG_ARCH_OMAP730
@@ -719,6 +921,14 @@ static int __init _omap_gpio_init(void)
 
                        gpio_count = 32; /* 730 has 32-bit GPIOs */
                }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+               if (bank->method == METHOD_GPIO_24XX) {
+                       __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
+                       __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
+
+                       gpio_count = 32;
+               }
 #endif
                for (j = bank->virtual_irq_start;
                     j < bank->virtual_irq_start + gpio_count; j++) {
@@ -735,12 +945,97 @@ static int __init _omap_gpio_init(void)
 
        /* Enable system clock for GPIO module.
         * The CAM_CLK_CTRL *is* really the right place. */
-       if (cpu_is_omap1610() || cpu_is_omap1710())
+       if (cpu_is_omap16xx())
                omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
 
        return 0;
 }
 
+#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
+static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+{
+       int i;
+
+       if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+               return 0;
+
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *wake_status;
+               void __iomem *wake_clear;
+               void __iomem *wake_set;
+
+               switch (bank->method) {
+               case METHOD_GPIO_1610:
+                       wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
+                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       break;
+               case METHOD_GPIO_24XX:
+                       wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
+                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+                       break;
+               default:
+                       continue;
+               }
+
+               spin_lock(&bank->lock);
+               bank->saved_wakeup = __raw_readl(wake_status);
+               __raw_writel(0xffffffff, wake_clear);
+               __raw_writel(bank->suspend_wakeup, wake_set);
+               spin_unlock(&bank->lock);
+       }
+
+       return 0;
+}
+
+static int omap_gpio_resume(struct sys_device *dev)
+{
+       int i;
+
+       if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+               return 0;
+
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *wake_clear;
+               void __iomem *wake_set;
+
+               switch (bank->method) {
+               case METHOD_GPIO_1610:
+                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       break;
+               case METHOD_GPIO_24XX:
+                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       break;
+               default:
+                       continue;
+               }
+
+               spin_lock(&bank->lock);
+               __raw_writel(0xffffffff, wake_clear);
+               __raw_writel(bank->saved_wakeup, wake_set);
+               spin_unlock(&bank->lock);
+       }
+
+       return 0;
+}
+
+static struct sysdev_class omap_gpio_sysclass = {
+       set_kset_name("gpio"),
+       .suspend        = omap_gpio_suspend,
+       .resume         = omap_gpio_resume,
+};
+
+static struct sys_device omap_gpio_device = {
+       .id             = 0,
+       .cls            = &omap_gpio_sysclass,
+};
+#endif
+
 /*
  * This may get called early from board specific init
  */
@@ -752,11 +1047,30 @@ int omap_gpio_init(void)
                return 0;
 }
 
+static int __init omap_gpio_sysinit(void)
+{
+       int ret = 0;
+
+       if (!initialized)
+               ret = _omap_gpio_init();
+
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
+       if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+               if (ret == 0) {
+                       ret = sysdev_class_register(&omap_gpio_sysclass);
+                       if (ret == 0)
+                               ret = sysdev_register(&omap_gpio_device);
+               }
+       }
+#endif
+
+       return ret;
+}
+
 EXPORT_SYMBOL(omap_request_gpio);
 EXPORT_SYMBOL(omap_free_gpio);
 EXPORT_SYMBOL(omap_set_gpio_direction);
 EXPORT_SYMBOL(omap_set_gpio_dataout);
 EXPORT_SYMBOL(omap_get_gpio_datain);
-EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
 
-arch_initcall(omap_gpio_init);
+arch_initcall(omap_gpio_sysinit);
index 43567d5edddb409124466110e91300743addb0a6..9c9b7df3faf6d2fe15315899cda29e8d43a8466e 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/arch/dma.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
+#include <asm/arch/dsp_common.h>
 #include <asm/arch/mcbsp.h>
 
 #include <asm/hardware/clock.h>
@@ -187,9 +188,6 @@ static int omap_mcbsp_check(unsigned int id)
        return -1;
 }
 
-#define EN_XORPCK              1
-#define DSP_RSTCT2              0xe1008014
-
 static void omap_mcbsp_dsp_request(void)
 {
        if (cpu_is_omap1510() || cpu_is_omap16xx()) {
@@ -198,6 +196,11 @@ static void omap_mcbsp_dsp_request(void)
 
                /* enable 12MHz clock to mcbsp 1 & 3 */
                clk_use(mcbsp_dspxor_ck);
+
+               /*
+                * DSP external peripheral reset
+                * FIXME: This should be moved to dsp code
+                */
                __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
                             DSP_RSTCT2);
        }
index ea7b955b9c819f05df337590529143ae982cc74b..64482040f89e9a7c0da908cd0bb8429b4ac5e274 100644 (file)
@@ -48,6 +48,9 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
                pull_orig = 0, pull = 0;
        unsigned int mask, warn = 0;
 
+       if (cpu_is_omap7xx())
+               return 0;
+
        if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
                printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
                return -EINVAL;
index 2ede2ee8cae420ecf4b5a24593e572058c942929..1fb16f9edfd58ba552ddb0bee7f6487e0fb6d5fd 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
index e6536b16c385b16aabc3a46303a00d668b482239..e15c6c1ddec954775b68ac623738885675da04d4 100644 (file)
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/pm.h>
+#include <linux/interrupt.h>
 
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/mach/time.h>
-#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
 
-#include <asm/arch/omap16xx.h>
+#include <asm/mach-types.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/tc.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/mux.h>
-#include <asm/arch/tc.h>
 #include <asm/arch/tps65010.h>
+#include <asm/arch/dsp_common.h>
 
 #include "clock.h"
+#include "sram.h"
 
 static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
 static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
 static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
 static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
 
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
 /*
  * Let's power down on idle, but only if we are really
  * idle, because once we start down the path of
@@ -65,7 +73,6 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
  */
 void omap_pm_idle(void)
 {
-       int (*func_ptr)(void) = 0;
        unsigned int mask32 = 0;
 
        /*
@@ -83,6 +90,13 @@ void omap_pm_idle(void)
        }
        mask32 = omap_readl(ARM_SYSST);
 
+       /*
+        * Prevent the ULPD from entering low power state by setting
+        * POWER_CTRL_REG:4 = 0
+        */
+       omap_writew(omap_readw(ULPD_POWER_CTRL) &
+                   ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
+
        /*
         * Since an interrupt may set up a timer, we don't want to
         * reprogram the hardware timer with interrupts enabled.
@@ -92,18 +106,9 @@ void omap_pm_idle(void)
 
        if ((mask32 & DSP_IDLE) == 0) {
                __asm__ volatile ("mcr  p15, 0, r0, c7, c0, 4");
-       } else {
-
-               if (cpu_is_omap1510()) {
-                       func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
-               } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
-                       func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
-               } else if (cpu_is_omap5912()) {
-                       func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
-               }
+       } else
+               omap_sram_idle();
 
-               func_ptr();
-       }
        local_fiq_enable();
        local_irq_enable();
 }
@@ -115,58 +120,55 @@ void omap_pm_idle(void)
  */
 static void omap_pm_wakeup_setup(void)
 {
-       /*
-        * Enable ARM XOR clock and release peripheral from reset by
-        * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
-        * for UART configuration to use UART2 to wake up.
-        */
-
-       omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
-       omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
-       omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
+       u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
+       u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
 
        /*
-        * Turn off all interrupts except L1-2nd level cascade,
-        * and the L2 wakeup interrupts: keypad and UART2.
+        * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+        * and the L2 wakeup interrupts: keypad and UART2. Note that the
+        * drivers must still separately call omap_set_gpio_wakeup() to
+        * wake up to a GPIO interrupt.
         */
+       if (cpu_is_omap1510() || cpu_is_omap16xx())
+               level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
+       else if (cpu_is_omap730())
+               level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
 
-       omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
+       omap_writel(~level1_wake, OMAP_IH1_MIR);
 
-       if (cpu_is_omap1510()) {
-               omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD),  OMAP_IH2_MIR);
-       }
+       if (cpu_is_omap1510())
+               omap_writel(~level2_wake,  OMAP_IH2_MIR);
 
+       /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
        if (cpu_is_omap16xx()) {
-               omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
-
-               omap_writel(~0x0, OMAP_IH2_1_MIR);
+               omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+               omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
                omap_writel(~0x0, OMAP_IH2_2_MIR);
                omap_writel(~0x0, OMAP_IH2_3_MIR);
        }
 
-       /*  New IRQ agreement */
+       /*  New IRQ agreement, recalculate in cascade order */
+       omap_writel(1, OMAP_IH2_CONTROL);
        omap_writel(1, OMAP_IH1_CONTROL);
-
-       /* external PULL to down, bit 22 = 0 */
-       omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
 }
 
 void omap_pm_suspend(void)
 {
-       unsigned int mask32 = 0;
        unsigned long arg0 = 0, arg1 = 0;
-       int (*func_ptr)(unsigned short, unsigned short) = 0;
-       unsigned short save_dsp_idlect2;
 
-       printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
+       printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+       omap_serial_wake_trigger(1);
 
        if (machine_is_omap_osk()) {
                /* Stop LED1 (D9) blink */
                tps65010_set_led(LED1, OFF);
        }
 
+       omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
        /*
-        * Step 1: turn off interrupts
+        * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
         */
 
        local_irq_disable();
@@ -207,6 +209,8 @@ void omap_pm_suspend(void)
        ARM_SAVE(ARM_CKCTL);
        ARM_SAVE(ARM_IDLECT1);
        ARM_SAVE(ARM_IDLECT2);
+       if (!(cpu_is_omap1510()))
+               ARM_SAVE(ARM_IDLECT3);
        ARM_SAVE(ARM_EWUPCT);
        ARM_SAVE(ARM_RSTCT1);
        ARM_SAVE(ARM_RSTCT2);
@@ -214,42 +218,12 @@ void omap_pm_suspend(void)
        ULPD_SAVE(ULPD_CLOCK_CTRL);
        ULPD_SAVE(ULPD_STATUS_REQ);
 
-       /*
-        * Step 3: LOW_PWR signal enabling
-        *
-        * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
-        */
-       if (cpu_is_omap1510()) {
-               /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
-               omap_writew(omap_readw(ULPD_POWER_CTRL) |
-                           OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
-       } else if (cpu_is_omap16xx()) {
-               /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
-               omap_writew(omap_readw(ULPD_POWER_CTRL) |
-                           OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
-       }
-
-       /* configure LOW_PWR pin */
-       omap_cfg_reg(T20_1610_LOW_PWR);
+       /* (Step 3 removed - we now allow deep sleep by default) */
 
        /*
         * Step 4: OMAP DSP Shutdown
         */
 
-       /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
-       omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
-                   ARM_RSTCT1);
-
-       /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
-        omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
-
-       /* Set EN_DSPCK = 0, stop DSP block clock */
-       omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
-
-       /* Stop any DSP domain clocks */
-       omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
-       save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
-       __raw_writew(0, DSP_IDLECT2);
 
        /*
         * Step 5: Wakeup Event Setup
@@ -258,24 +232,9 @@ void omap_pm_suspend(void)
        omap_pm_wakeup_setup();
 
        /*
-        * Step 6a: ARM and Traffic controller shutdown
-        *
-        * Step 6 starts here with clock and watchdog disable
+        * Step 6: ARM and Traffic controller shutdown
         */
 
-       /* stop clocks */
-       mask32 = omap_readl(ARM_IDLECT2);
-       mask32 &= ~(1<<EN_WDTCK);  /* bit 0 -> 0 (WDT clock) */
-       mask32 |=  (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
-       mask32 &= ~(1<<EN_PERCK);  /* bit 2 -> 0 (MPUPER_CK clock) */
-       mask32 &= ~(1<<EN_LCDCK);  /* bit 3 -> 0 (LCDC clock) */
-       mask32 &= ~(1<<EN_LBCK);   /* bit 4 -> 0 (local bus clock) */
-       mask32 |=  (1<<EN_APICK);  /* bit 6 -> 1 (MPUI clock) */
-       mask32 &= ~(1<<EN_TIMCK);  /* bit 7 -> 0 (MPU timer clock) */
-       mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
-       mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
-       omap_writel(mask32, ARM_IDLECT2);
-
        /* disable ARM watchdog */
        omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
        omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
@@ -295,47 +254,24 @@ void omap_pm_suspend(void)
        arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
        arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
 
-       if (cpu_is_omap1510()) {
-               func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
-       } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
-               func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
-       } else if (cpu_is_omap5912()) {
-               func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
-       }
-
        /*
         * Step 6c: ARM and Traffic controller shutdown
         *
         * Jump to assembly code. The processor will stay there
         * until wake up.
         */
-
-        func_ptr(arg0, arg1);
+        omap_sram_suspend(arg0, arg1);
 
        /*
         * If we are here, processor is woken up!
         */
 
-       if (cpu_is_omap1510()) {
-               /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
-               omap_writew(omap_readw(ULPD_POWER_CTRL) &
-                           ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
-       } else if (cpu_is_omap16xx()) {
-               /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
-               omap_writew(omap_readw(ULPD_POWER_CTRL) &
-                           ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
-       }
-
-
-       /* Restore DSP clocks */
-       omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
-       __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
-       ARM_RESTORE(ARM_IDLECT2);
-
        /*
         * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
         */
 
+       if (!(cpu_is_omap1510()))
+               ARM_RESTORE(ARM_IDLECT3);
        ARM_RESTORE(ARM_CKCTL);
        ARM_RESTORE(ARM_EWUPCT);
        ARM_RESTORE(ARM_RSTCT1);
@@ -366,6 +302,8 @@ void omap_pm_suspend(void)
                MPUI1610_RESTORE(OMAP_IH2_3_MIR);
        }
 
+       omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
        /*
         * Reenable interrupts
         */
@@ -373,6 +311,8 @@ void omap_pm_suspend(void)
        local_irq_enable();
        local_fiq_enable();
 
+       omap_serial_wake_trigger(0);
+
        printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
 
        if (machine_is_omap_osk()) {
@@ -401,6 +341,8 @@ static int omap_pm_read_proc(
        ARM_SAVE(ARM_CKCTL);
        ARM_SAVE(ARM_IDLECT1);
        ARM_SAVE(ARM_IDLECT2);
+       if (!(cpu_is_omap1510()))
+               ARM_SAVE(ARM_IDLECT3);
        ARM_SAVE(ARM_EWUPCT);
        ARM_SAVE(ARM_RSTCT1);
        ARM_SAVE(ARM_RSTCT2);
@@ -436,6 +378,7 @@ static int omap_pm_read_proc(
                   "ARM_CKCTL_REG:            0x%-8x     \n"
                   "ARM_IDLECT1_REG:          0x%-8x     \n"
                   "ARM_IDLECT2_REG:          0x%-8x     \n"
+                  "ARM_IDLECT3_REG:          0x%-8x     \n"
                   "ARM_EWUPCT_REG:           0x%-8x     \n"
                   "ARM_RSTCT1_REG:           0x%-8x     \n"
                   "ARM_RSTCT2_REG:           0x%-8x     \n"
@@ -449,6 +392,7 @@ static int omap_pm_read_proc(
                   ARM_SHOW(ARM_CKCTL),
                   ARM_SHOW(ARM_IDLECT1),
                   ARM_SHOW(ARM_IDLECT2),
+                  ARM_SHOW(ARM_IDLECT3),
                   ARM_SHOW(ARM_EWUPCT),
                   ARM_SHOW(ARM_RSTCT1),
                   ARM_SHOW(ARM_RSTCT2),
@@ -507,7 +451,7 @@ static void omap_pm_init_proc(void)
 
        entry = create_proc_read_entry("driver/omap_pm",
                                       S_IWUSR | S_IRUGO, NULL,
-                                      omap_pm_read_proc, 0);
+          omap_pm_read_proc, NULL);
 }
 
 #endif /* DEBUG && CONFIG_PROC_FS */
@@ -580,7 +524,21 @@ static int omap_pm_finish(suspend_state_t state)
 }
 
 
-struct pm_ops omap_pm_ops ={
+static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
+                                    struct pt_regs *  regs)
+{
+       return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+       .name           = "peripheral wakeup",
+       .flags          = SA_INTERRUPT,
+       .handler        = omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
        .pm_disk_mode = 0,
         .prepare        = omap_pm_prepare,
         .enter          = omap_pm_enter,
@@ -590,42 +548,61 @@ struct pm_ops omap_pm_ops ={
 static int __init omap_pm_init(void)
 {
        printk("Power Management for TI OMAP.\n");
-       pm_idle = omap_pm_idle;
        /*
         * We copy the assembler sleep/wakeup routines to SRAM.
         * These routines need to be in SRAM as that's the only
         * memory the MPU can see when it wakes up.
         */
-
-#ifdef CONFIG_ARCH_OMAP1510
        if (cpu_is_omap1510()) {
-               memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
-                      omap1510_idle_loop_suspend,
-                      omap1510_idle_loop_suspend_sz);
-               memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
-                      omap1510_cpu_suspend_sz);
-       } else
-#endif
-       if (cpu_is_omap1610() || cpu_is_omap1710()) {
-               memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
-                      omap1610_idle_loop_suspend,
-                      omap1610_idle_loop_suspend_sz);
-               memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
-                      omap1610_cpu_suspend_sz);
-       } else if (cpu_is_omap5912()) {
-               memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
-                      omap1610_idle_loop_suspend,
-                      omap1610_idle_loop_suspend_sz);
-               memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
-                      omap1610_cpu_suspend_sz);
+               omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+                                               omap1510_idle_loop_suspend_sz);
+               omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+                                                  omap1510_cpu_suspend_sz);
+       } else if (cpu_is_omap16xx()) {
+               omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+                                               omap1610_idle_loop_suspend_sz);
+               omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+                                                  omap1610_cpu_suspend_sz);
        }
 
+       if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+               printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+               return -ENODEV;
+       }
+
+       pm_idle = omap_pm_idle;
+
+       setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+#if 0
+       /* --- BEGIN BOARD-DEPENDENT CODE --- */
+       /* Sleepx mask direction */
+       omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+       /* Unmask sleepx signal */
+       omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+       /* --- END BOARD-DEPENDENT CODE --- */
+#endif
+
+       /* Program new power ramp-up time
+        * (0 for most boards since we don't lower voltage when in deep sleep)
+        */
+       omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+       /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+       omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+       /* Configure IDLECT3 */
+       if (cpu_is_omap16xx())
+               omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
        pm_set_ops(&omap_pm_ops);
 
 #if defined(DEBUG) && defined(CONFIG_PROC_FS)
        omap_pm_init_proc();
 #endif
 
+       /* configure LOW_PWR pin */
+       omap_cfg_reg(T20_1610_LOW_PWR);
+
        return 0;
 }
 __initcall(omap_pm_init);
index 279490ce772b16bc9e47cd20718fe8e10ffc69ce..9f745836f6aac97e8b76e8e61c9b516d3d4bf388 100644 (file)
@@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
        @ get ARM_IDLECT2 into r2
        ldrh    r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
        mov     r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
-       orr     r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+       orr     r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
        @ request ARM idle
@@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
        mov     r5, #IDLE_WAIT_CYCLES & 0xff
-       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
 l_1510:        subs    r5, r5, #1
        bne     l_1510
 /*
@@ -96,7 +96,7 @@ l_1510:       subs    r5, r5, #1
        strh    r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
        strh    r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
-       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+       ldmfd   sp!, {r0 - r12, pc}             @ restore regs and return
 
 ENTRY(omap1510_idle_loop_suspend_sz)
        .word   . - omap1510_idle_loop_suspend
@@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
        @ turn off clock domains
        @ get ARM_IDLECT2 into r2
        ldrh    r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-       mov     r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
-       orr     r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
+       mov     r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
+       orr     r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
        @ request ARM idle
@@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
        mov     r5, #IDLE_WAIT_CYCLES & 0xff
-       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
 l_1610:        subs    r5, r5, #1
        bne     l_1610
 /*
@@ -146,7 +146,7 @@ l_1610:     subs    r5, r5, #1
        strh    r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
        strh    r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
-       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+       ldmfd   sp!, {r0 - r12, pc}             @ restore regs and return
 
 ENTRY(omap1610_idle_loop_suspend_sz)
        .word   . - omap1610_idle_loop_suspend
@@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
 
        @ turn off clock domains
        mov     r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
-       orr     r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+       orr     r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
        @ request ARM idle
@@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
        mov     r5, #IDLE_WAIT_CYCLES & 0xff
-       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
 l_1510_2:
        subs    r5, r5, #1
        bne     l_1510_2
@@ -237,7 +237,7 @@ l_1510_2:
        strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
        @ restore regs and return
-       ldmfd   sp!, {r0 - r12, pc}
+       ldmfd   sp!, {r0 - r12, pc}
 
 ENTRY(omap1510_cpu_suspend_sz)
        .word   . - omap1510_cpu_suspend
@@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
        @ save registers on stack
        stmfd   sp!, {r0 - r12, lr}
 
+       @ Drain write cache
+       mov     r4, #0
+       mcr     p15, 0, r0, c7, c10, 4
+       nop
+
        @ load base address of Traffic Controller
-       mov     r4, #TCMIF_ASM_BASE & 0xff000000
-       orr     r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
-       orr     r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
+       mov     r6, #TCMIF_ASM_BASE & 0xff000000
+       orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
+       orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
 
        @ prepare to put SDRAM into self-refresh manually
-       ldr     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
-       orr     r5, r5, #SELF_REFRESH_MODE & 0xff000000
-       orr     r5, r5, #SELF_REFRESH_MODE & 0x000000ff
-       str     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+       ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+       orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
+       orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
+       str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 
        @ prepare to put EMIFS to Sleep
-       ldr     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
-       orr     r5, r5, #IDLE_EMIFS_REQUEST & 0xff
-       str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+       ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+       orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
+       str     r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 
        @ load base address of ARM_IDLECT1 and ARM_IDLECT2
        mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
@@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
 
        @ turn off clock domains
-       mov     r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
-       orr     r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
-       strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-
-       @ work around errata of OMAP1610/5912. Enable (!) peripheral
-       @ clock to let the chip go into deep sleep
-       ldrh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-       orr     r5,r5, #EN_PERCK_BIT & 0xff
+       @ do not disable PERCK (0x04)
+       mov     r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
+       orr     r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
        @ request ARM idle
-       mov     r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
-       orr     r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
+       mov     r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
+       orr     r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
-       mov     r5, #IDLE_WAIT_CYCLES & 0xff
-       orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
-l_1610_2:
-       subs    r5, r5, #1
-       bne     l_1610_2
+       @ disable instruction cache
+       mrc     p15, 0, r9, c1, c0, 0
+       bic     r2, r9, #0x1000
+       mcr     p15, 0, r2, c1, c0, 0
+       nop
+
 /*
  * Let's wait for the next wake up event to wake us up. r0 can't be
  * used here because r0 holds ARM_IDLECT1
@@ -301,13 +302,21 @@ l_1610_2:
  * omap1610_cpu_suspend()'s resume point.
  *
  * It will just start executing here, so we'll restore stuff from the
- * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ * stack.
  */
+       @ re-enable Icache
+       mcr     p15, 0, r9, c1, c0, 0
+
+       @ reset the ARM_IDLECT1 and ARM_IDLECT2.
        strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
        strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
+       @ Restore EMIFF controls
+       str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+       str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
        @ restore regs and return
-       ldmfd   sp!, {r0 - r12, pc}
+       ldmfd   sp!, {r0 - r12, pc}
 
 ENTRY(omap1610_cpu_suspend_sz)
        .word   . - omap1610_cpu_suspend
diff --git a/arch/arm/plat-omap/sram-fn.S b/arch/arm/plat-omap/sram-fn.S
new file mode 100644 (file)
index 0000000..4bea369
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * linux/arch/arm/plat-omap/sram.S
+ *
+ * Functions that need to be run in internal SRAM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+
+       .text
+
+/*
+ * Reprograms ULPD and CKCTL.
+ */
+ENTRY(sram_reprogram_clock)
+       stmfd   sp!, {r0 - r12, lr}             @ save registers on stack
+
+       mov     r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000
+       orr     r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000
+       orr     r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00
+
+       mov     r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000
+       orr     r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
+       orr     r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
+
+       tst     r0, #1 << 4                     @ want lock mode?
+       beq     newck                           @ nope
+       bic     r0, r0, #1 << 4                 @ else clear lock bit
+       strh    r0, [r2]                        @ set dpll into bypass mode
+       orr     r0, r0, #1 << 4                 @ set lock bit again
+
+newck:
+       strh    r1, [r3]                        @ write new ckctl value
+       strh    r0, [r2]                        @ write new dpll value
+
+       mov     r4, #0x0700                     @ let the clocks settle
+       orr     r4, r4, #0x00ff
+delay: sub     r4, r4, #1
+       cmp     r4, #0
+       bne     delay
+
+lock:  ldrh    r4, [r2], #0                    @ read back dpll value
+       tst     r0, #1 << 4                     @ want lock mode?
+       beq     out                             @ nope
+       tst     r4, #1 << 0                     @ dpll rate locked?
+       beq     lock                            @ try again
+
+out:
+       ldmfd   sp!, {r0 - r12, pc}             @ restore regs and return
+ENTRY(sram_reprogram_clock_sz)
+       .word   . - sram_reprogram_clock
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
new file mode 100644 (file)
index 0000000..7719a40
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/plat-omap/sram.c
+ *
+ * OMAP SRAM detection and management
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+#include "sram.h"
+
+#define OMAP1_SRAM_BASE                0xd0000000
+#define OMAP1_SRAM_START       0x20000000
+#define SRAM_BOOTLOADER_SZ     0x80
+
+static unsigned long omap_sram_base;
+static unsigned long omap_sram_size;
+static unsigned long omap_sram_ceil;
+
+/*
+ * The amount of SRAM depends on the core type:
+ * 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
+ * Note that we cannot try to test for SRAM here because writes
+ * to secure SRAM will hang the system. Also the SRAM is not
+ * yet mapped at this point.
+ */
+void __init omap_detect_sram(void)
+{
+       omap_sram_base = OMAP1_SRAM_BASE;
+
+       if (cpu_is_omap730())
+               omap_sram_size = 0x32000;
+       else if (cpu_is_omap1510())
+               omap_sram_size = 0x80000;
+       else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
+               omap_sram_size = 0x4000;
+       else if (cpu_is_omap1611())
+               omap_sram_size = 0x3e800;
+       else {
+               printk(KERN_ERR "Could not detect SRAM size\n");
+               omap_sram_size = 0x4000;
+       }
+
+       printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
+       omap_sram_ceil = omap_sram_base + omap_sram_size;
+}
+
+static struct map_desc omap_sram_io_desc[] __initdata = {
+       { OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
+};
+
+/*
+ * In order to use last 2kB of SRAM on 1611b, we must round the size
+ * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
+ * clock init needs SRAM early.
+ */
+void __init omap_map_sram(void)
+{
+       if (omap_sram_size == 0)
+               return;
+
+       omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
+       omap_sram_io_desc[0].length *= PAGE_SIZE;
+       iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
+
+       /*
+        * Looks like we need to preserve some bootloader code at the
+        * beginning of SRAM for jumping to flash for reboot to work...
+        */
+       memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
+              omap_sram_size - SRAM_BOOTLOADER_SZ);
+}
+
+static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
+
+void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
+{
+       if (_omap_sram_reprogram_clock == NULL)
+               panic("Cannot use SRAM");
+
+       return _omap_sram_reprogram_clock(dpllctl, ckctl);
+}
+
+void * omap_sram_push(void * start, unsigned long size)
+{
+       if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+               printk(KERN_ERR "Not enough space in SRAM\n");
+               return NULL;
+       }
+       omap_sram_ceil -= size;
+       omap_sram_ceil &= ~0x3;
+       memcpy((void *)omap_sram_ceil, start, size);
+
+       return (void *)omap_sram_ceil;
+}
+
+void __init omap_sram_init(void)
+{
+       omap_detect_sram();
+       omap_map_sram();
+       _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
+                                                   sram_reprogram_clock_sz);
+}
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
new file mode 100644 (file)
index 0000000..71984ef
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/arm/plat-omap/sram.h
+ *
+ * Interface for functions that need to be run in internal SRAM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_SRAM_H
+#define __ARCH_ARM_OMAP_SRAM_H
+
+extern void * omap_sram_push(void * start, unsigned long size);
+extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
+
+/* Do not use these */
+extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long sram_reprogram_clock_sz;
+
+#endif
index 25bc4a8dd763d8c7f7e10c8fa8fb6ef6baf3fa9d..98f1c76f86606f039dad4501651f371f7056f099 100644 (file)
@@ -41,6 +41,7 @@
 
 /* These routines should handle the standard chip-specific modes
  * for usb0/1/2 ports, covering basic mux and transceiver setup.
+ * Call omap_usb_init() once, from INIT_MACHINE().
  *
  * Some board-*.c files will need to set up additional mux options,
  * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
index 1f0373267306c20738862141b4dc8f5bd3173bb0..1f00b3d03a076a9a9f70a694198c42e96d9277ba 100644 (file)
@@ -55,6 +55,10 @@ config GENERIC_BUST_SPINLOCK
 config GENERIC_ISA_DMA
        bool
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 
index ada8985530a592a147378f7c97fd39e6882e9e60..e9cb8ef4f3fbdf0ae44197e9db145d506f28226a 100644 (file)
@@ -17,10 +17,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
 CFLAGS         +=-fno-omit-frame-pointer -mno-sched-prolog
 endif
 
-ifeq ($(CONFIG_DEBUG_INFO),y)
-CFLAGS         +=-g
-endif
-
 CFLAGS_BOOT    :=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
 CFLAGS         +=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
 AFLAGS         +=-mapcs-26 -mcpu=arm3 -msoft-float
index 549a6b2e177ef4ca666bfd4355d9b21d7b2dafe8..e66aedd02fad7c2eccf15259efb97c162e3dec5a 100644 (file)
@@ -114,7 +114,7 @@ static unsigned long next_rtc_update;
  */
 static inline void do_set_rtc(void)
 {
-       if (time_status & STA_UNSYNC || set_rtc == NULL)
+       if (!ntp_synced() || set_rtc == NULL)
                return;
 
 //FIXME - timespec.tv_sec is a time_t not unsigned long
@@ -189,10 +189,7 @@ int do_settimeofday(struct timespec *tv)
 
        xtime.tv_sec = tv->tv_sec;
        xtime.tv_nsec = tv->tv_nsec;
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 6b7b4e0802e3ac23991abd09fcfbf9312cf274f8..dc3dfe9b4a1aa64f09a8b35a3947d8b32e1346ec 100644 (file)
@@ -240,7 +240,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * The division here is not time critical since it will run once in 
         * 11 minutes
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - (tick_nsec / 1000) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + (tick_nsec / 1000) / 2) {
index fa2d4323da2592deef3bd5652110d953e7696850..a2d99b4aedcda34f22a5c1ec10fc4f3250050b0c 100644 (file)
@@ -114,10 +114,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 075db6644694b460b6428ce41223cc2c546dabbc..8d6558b00e44fe86128e03922e4a402ac18fee8b 100644 (file)
@@ -85,7 +85,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2
@@ -216,10 +216,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 8a600218334dfcaba3501a34e9e09d0c40f6395a..af8c5d2057dd56ed6fa30257cd9ab2cd5c521bcb 100644 (file)
@@ -116,10 +116,7 @@ int do_settimeofday(struct timespec *tv)
 
        xtime.tv_sec = tv->tv_sec;
        xtime.tv_nsec = tv->tv_nsec;
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 3b3b017e1c154fa9419dfec55b969cb48e91b608..5d51b38bd70d2d0bdc86ed14ee613e3f4786c993 100644 (file)
@@ -37,6 +37,10 @@ config GENERIC_IOMAP
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "Processor type and features"
@@ -1318,6 +1322,11 @@ config GENERIC_IRQ_PROBE
        bool
        default y
 
+config GENERIC_PENDING_IRQ
+       bool
+       depends on GENERIC_HARDIRQS && SMP
+       default y
+
 config X86_SMP
        bool
        depends on SMP && !X86_VOYAGER
index 8cb420f40c58f106972d5ec830e8cd382378470c..ca668d9df16411c29d2928d230c32b99a129104f 100644 (file)
@@ -82,7 +82,7 @@ start:
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
                .ascii  "HdrS"          # header signature
-               .word   0x0203          # header version number (>= 0x0105)
+               .word   0x0204          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
 start_sys_seg: .word   SYSSEG
index 6835f6d47c31e8f5913a670c6bd7bdd57f1e7b7c..05798419a6a93f25be4f347d2eea5e6f04e5ddf6 100644 (file)
@@ -177,7 +177,9 @@ int main(int argc, char ** argv)
                die("Output: seek failed");
        buf[0] = (sys_size & 0xff);
        buf[1] = ((sys_size >> 8) & 0xff);
-       if (write(1, buf, 2) != 2)
+       buf[2] = ((sys_size >> 16) & 0xff);
+       buf[3] = ((sys_size >> 24) & 0xff);
+       if (write(1, buf, 4) != 4)
                die("Write of image length failed");
 
        return 0;                                           /* Everything is OK */
index a3cdf894302b0d5fe48ecfcd1581be41d99c8932..58516e2ac1728fb4cbeb31e7dae8e23d237f5e27 100644 (file)
@@ -6,32 +6,28 @@
 #include <linux/bootmem.h>
 
 
-struct dmi_header {
-       u8 type;
-       u8 length;
-       u16 handle;
-};
-
-#undef DMI_DEBUG
-
-#ifdef DMI_DEBUG
-#define dmi_printk(x) printk x
-#else
-#define dmi_printk(x)
-#endif
-
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
        u8 *bp = ((u8 *) dm) + dm->length;
+       char *str = "";
 
-       if (!s)
-               return "";
-       s--;
-       while (s > 0 && *bp) {
-               bp += strlen(bp) + 1;
+       if (s) {
                s--;
-       }
-       return bp;
+               while (s > 0 && *bp) {
+                       bp += strlen(bp) + 1;
+                       s--;
+               }
+
+               if (*bp != 0) {
+                       str = alloc_bootmem(strlen(bp) + 1);
+                       if (str != NULL)
+                               strcpy(str, bp);
+                       else
+                               printk(KERN_ERR "dmi_string: out of memory.\n");
+               }
+       }
+
+       return str;
 }
 
 /*
@@ -84,69 +80,76 @@ static int __init dmi_checksum(u8 *buf)
        return sum == 0;
 }
 
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+static char *dmi_ident[DMI_STRING_MAX];
+static LIST_HEAD(dmi_devices);
+
+/*
+ *     Save a DMI string
+ */
+static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
 {
-       u8 buf[15];
-       char __iomem *p, *q;
+       char *p, *d = (char*) dm;
 
-       /*
-        * no iounmap() for that ioremap(); it would be a no-op, but it's
-        * so early in setup that sucker gets confused into doing what
-        * it shouldn't if we actually call it.
-        */
-       p = ioremap(0xF0000, 0x10000);
+       if (dmi_ident[slot])
+               return;
+
+       p = dmi_string(dm, d[string]);
        if (p == NULL)
-               return -1;
+               return;
 
-       for (q = p; q < p + 0x10000; q += 16) {
-               memcpy_fromio(buf, q, 15);
-               if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
-                       u16 num = (buf[13] << 8) | buf[12];
-                       u16 len = (buf[7] << 8) | buf[6];
-                       u32 base = (buf[11] << 24) | (buf[10] << 16) |
-                                  (buf[9] << 8) | buf[8];
+       dmi_ident[slot] = p;
+}
 
-                       /*
-                        * DMI version 0.0 means that the real version is taken from
-                        * the SMBIOS version, which we don't know at this point.
-                        */
-                       if (buf[14] != 0)
-                               printk(KERN_INFO "DMI %d.%d present.\n",
-                                       buf[14] >> 4, buf[14] & 0xF);
-                       else
-                               printk(KERN_INFO "DMI present.\n");
+static void __init dmi_save_devices(struct dmi_header *dm)
+{
+       int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
+       struct dmi_device *dev;
+
+       for (i = 0; i < count; i++) {
+               char *d = ((char *) dm) + (i * 2);
 
-                       dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
-                               num, len));
-                       dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
+               /* Skip disabled device */
+               if ((*d & 0x80) == 0)
+                       continue;
 
-                       if (dmi_table(base,len, num, decode) == 0)
-                               return 0;
+               dev = alloc_bootmem(sizeof(*dev));
+               if (!dev) {
+                       printk(KERN_ERR "dmi_save_devices: out of memory.\n");
+                       break;
                }
+
+               dev->type = *d++ & 0x7f;
+               dev->name = dmi_string(dm, *d);
+               dev->device_data = NULL;
+
+               list_add(&dev->list, &dmi_devices);
        }
-       return -1;
 }
 
-static char *dmi_ident[DMI_STRING_MAX];
-
-/*
- *     Save a DMI string
- */
-static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
+static void __init dmi_save_ipmi_device(struct dmi_header *dm)
 {
-       char *d = (char*)dm;
-       char *p = dmi_string(dm, d[string]);
+       struct dmi_device *dev;
+       void * data;
 
-       if (p == NULL || *p == 0)
+       data = alloc_bootmem(dm->length);
+       if (data == NULL) {
+               printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
                return;
-       if (dmi_ident[slot])
+       }
+
+       memcpy(data, dm, dm->length);
+
+       dev = alloc_bootmem(sizeof(*dev));
+       if (!dev) {
+               printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
                return;
+       }
 
-       dmi_ident[slot] = alloc_bootmem(strlen(p) + 1);
-       if(dmi_ident[slot])
-               strcpy(dmi_ident[slot], p);
-       else
-               printk(KERN_ERR "dmi_save_ident: out of memory.\n");
+       dev->type = DMI_DEV_TYPE_IPMI;
+       dev->name = "IPMI controller";
+       dev->device_data = data;
+
+       list_add(&dev->list, &dmi_devices);
 }
 
 /*
@@ -156,42 +159,69 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
  */
 static void __init dmi_decode(struct dmi_header *dm)
 {
-       u8 *data __attribute__((__unused__)) = (u8 *)dm;
-       
        switch(dm->type) {
-       case  0:
-               dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4])));
+       case 0:         /* BIOS Information */
                dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
-               dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5])));
                dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
-               dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8])));
                dmi_save_ident(dm, DMI_BIOS_DATE, 8);
                break;
-       case 1:
-               dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4])));
+       case 1:         /* System Information */
                dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
-               dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5])));
                dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
-               dmi_printk(("Version: %s\n", dmi_string(dm, data[6])));
                dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
-               dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7])));
                dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
                break;
-       case 2:
-               dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4])));
+       case 2:         /* Base Board Information */
                dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
-               dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5])));
                dmi_save_ident(dm, DMI_BOARD_NAME, 5);
-               dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6])));
                dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
                break;
+       case 10:        /* Onboard Devices Information */
+               dmi_save_devices(dm);
+               break;
+       case 38:        /* IPMI Device Information */
+               dmi_save_ipmi_device(dm);
        }
 }
 
 void __init dmi_scan_machine(void)
 {
-       if (dmi_iterate(dmi_decode))
-               printk(KERN_INFO "DMI not present.\n");
+       u8 buf[15];
+       char __iomem *p, *q;
+
+       /*
+        * no iounmap() for that ioremap(); it would be a no-op, but it's
+        * so early in setup that sucker gets confused into doing what
+        * it shouldn't if we actually call it.
+        */
+       p = ioremap(0xF0000, 0x10000);
+       if (p == NULL)
+               goto out;
+
+       for (q = p; q < p + 0x10000; q += 16) {
+               memcpy_fromio(buf, q, 15);
+               if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+                       u16 num = (buf[13] << 8) | buf[12];
+                       u16 len = (buf[7] << 8) | buf[6];
+                       u32 base = (buf[11] << 24) | (buf[10] << 16) |
+                                  (buf[9] << 8) | buf[8];
+
+                       /*
+                        * DMI version 0.0 means that the real version is taken from
+                        * the SMBIOS version, which we don't know at this point.
+                        */
+                       if (buf[14] != 0)
+                               printk(KERN_INFO "DMI %d.%d present.\n",
+                                       buf[14] >> 4, buf[14] & 0xF);
+                       else
+                               printk(KERN_INFO "DMI present.\n");
+
+                       if (dmi_table(base,len, num, dmi_decode) == 0)
+                               return;
+               }
+       }
+
+out:   printk(KERN_INFO "DMI not present.\n");
 }
 
 
@@ -218,9 +248,9 @@ int dmi_check_system(struct dmi_system_id *list)
                        /* No match */
                        goto fail;
                }
+               count++;
                if (d->callback && d->callback(d))
                        break;
-               count++;
 fail:          d++;
        }
 
@@ -240,3 +270,32 @@ char *dmi_get_system_info(int field)
        return dmi_ident[field];
 }
 EXPORT_SYMBOL(dmi_get_system_info);
+
+/**
+ *     dmi_find_device - find onboard device by type/name
+ *     @type: device type or %DMI_DEV_TYPE_ANY to match all device types
+ *     @desc: device name string or %NULL to match all
+ *     @from: previous device found in search, or %NULL for new search.
+ *
+ *     Iterates through the list of known onboard devices. If a device is
+ *     found with a matching @vendor and @device, a pointer to its device
+ *     structure is returned.  Otherwise, %NULL is returned.
+ *     A new search is initiated by passing %NULL to the @from argument.
+ *     If @from is not %NULL, searches continue from next device.
+ */
+struct dmi_device * dmi_find_device(int type, const char *name,
+                                   struct dmi_device *from)
+{
+       struct list_head *d, *head = from ? &from->list : &dmi_devices;
+
+       for(d = head->next; d != &dmi_devices; d = d->next) {
+               struct dmi_device *dev = list_entry(d, struct dmi_device, list);
+
+               if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
+                   ((name == NULL) || (strcmp(dev->name, name) == 0)))
+                       return dev;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(dmi_find_device);
index abb909793efcdce8e0e393e0da9beb738550dc10..3aad03839660de38dd8c24361ecbd6814de5eb52 100644 (file)
@@ -507,7 +507,7 @@ label:                                              \
        pushl $__KERNEL_CS;                     \
        pushl $sysenter_past_esp
 
-ENTRY(debug)
+KPROBE_ENTRY(debug)
        cmpl $sysenter_entry,(%esp)
        jne debug_stack_correct
        FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
@@ -518,7 +518,7 @@ debug_stack_correct:
        movl %esp,%eax                  # pt_regs pointer
        call do_debug
        jmp ret_from_exception
-
+       .previous .text
 /*
  * NMI is doubly nasty. It can happen _while_ we're handling
  * a debug fault, and the debug fault hasn't yet been able to
@@ -591,13 +591,14 @@ nmi_16bit_stack:
        .long 1b,iret_exc
 .previous
 
-ENTRY(int3)
+KPROBE_ENTRY(int3)
        pushl $-1                       # mark this as an int
        SAVE_ALL
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_int3
        jmp ret_from_exception
+       .previous .text
 
 ENTRY(overflow)
        pushl $0
@@ -631,17 +632,19 @@ ENTRY(stack_segment)
        pushl $do_stack_segment
        jmp error_code
 
-ENTRY(general_protection)
+KPROBE_ENTRY(general_protection)
        pushl $do_general_protection
        jmp error_code
+       .previous .text
 
 ENTRY(alignment_check)
        pushl $do_alignment_check
        jmp error_code
 
-ENTRY(page_fault)
+KPROBE_ENTRY(page_fault)
        pushl $do_page_fault
        jmp error_code
+       .previous .text
 
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
index 6578f40bd5012a0af9385d889f8a6cd37a6546a9..0e727e6da5c981743f66bf4fdf74a925f0482b7f 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/sysdev.h>
+
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
@@ -77,7 +78,7 @@ static struct irq_pin_list {
        int apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
 
-int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
 #ifdef CONFIG_PCI_MSI
 #define vector_to_irq(vector)  \
        (platform_legacy_irq(vector) ? vector : vector_irq[vector])
@@ -222,13 +223,21 @@ static void clear_IO_APIC (void)
                        clear_IO_APIC_pin(apic, pin);
 }
 
+#ifdef CONFIG_SMP
 static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 {
        unsigned long flags;
        int pin;
        struct irq_pin_list *entry = irq_2_pin + irq;
        unsigned int apicid_value;
+       cpumask_t tmp;
        
+       cpus_and(tmp, cpumask, cpu_online_map);
+       if (cpus_empty(tmp))
+               tmp = TARGET_CPUS;
+
+       cpus_and(cpumask, tmp, CPU_MASK_ALL);
+
        apicid_value = cpu_mask_to_apicid(cpumask);
        /* Prepare to do the io_apic_write */
        apicid_value = apicid_value << 24;
@@ -242,6 +251,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
                        break;
                entry = irq_2_pin + entry->next;
        }
+       set_irq_info(irq, cpumask);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -259,7 +269,6 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 #  define Dprintk(x...) 
 # endif
 
-cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
 
 #define IRQBALANCE_CHECK_ARCH -999
 static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
@@ -328,12 +337,7 @@ static inline void balance_irq(int cpu, int irq)
        cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
        new_cpu = move(cpu, allowed_mask, now, 1);
        if (cpu != new_cpu) {
-               irq_desc_t *desc = irq_desc + irq;
-               unsigned long flags;
-
-               spin_lock_irqsave(&desc->lock, flags);
-               pending_irq_balance_cpumask[irq] = cpumask_of_cpu(new_cpu);
-               spin_unlock_irqrestore(&desc->lock, flags);
+               set_pending_irq(irq, cpumask_of_cpu(new_cpu));
        }
 }
 
@@ -528,16 +532,12 @@ tryanotherirq:
        cpus_and(tmp, target_cpu_mask, allowed_mask);
 
        if (!cpus_empty(tmp)) {
-               irq_desc_t *desc = irq_desc + selected_irq;
-               unsigned long flags;
 
                Dprintk("irq = %d moved to cpu = %d\n",
                                selected_irq, min_loaded);
                /* mark for change destination */
-               spin_lock_irqsave(&desc->lock, flags);
-               pending_irq_balance_cpumask[selected_irq] =
-                                       cpumask_of_cpu(min_loaded);
-               spin_unlock_irqrestore(&desc->lock, flags);
+               set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+
                /* Since we made a change, come back sooner to 
                 * check for more variation.
                 */
@@ -568,7 +568,8 @@ static int balanced_irq(void *unused)
        
        /* push everything to CPU 0 to give us a starting point.  */
        for (i = 0 ; i < NR_IRQS ; i++) {
-               pending_irq_balance_cpumask[i] = cpumask_of_cpu(0);
+               pending_irq_cpumask[i] = cpumask_of_cpu(0);
+               set_pending_irq(i, cpumask_of_cpu(0));
        }
 
        for ( ; ; ) {
@@ -647,20 +648,9 @@ int __init irqbalance_disable(char *str)
 
 __setup("noirqbalance", irqbalance_disable);
 
-static inline void move_irq(int irq)
-{
-       /* note - we hold the desc->lock */
-       if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
-               set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
-               cpus_clear(pending_irq_balance_cpumask[irq]);
-       }
-}
-
 late_initcall(balanced_irq_init);
-
-#else /* !CONFIG_IRQBALANCE */
-static inline void move_irq(int irq) { }
 #endif /* CONFIG_IRQBALANCE */
+#endif /* CONFIG_SMP */
 
 #ifndef CONFIG_SMP
 void fastcall send_IPI_self(int vector)
@@ -820,6 +810,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
  * we need to reprogram the ioredtbls to cater for the cpus which have come online
  * so mask in all cases should simply be TARGET_CPUS
  */
+#ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
        int pin, ioapic, irq, irq_entry;
@@ -838,6 +829,7 @@ void __init setup_ioapic_dest(void)
 
        }
 }
+#endif
 
 /*
  * EISA Edge/Level control register, ELCR
@@ -1127,7 +1119,7 @@ static inline int IO_APIC_irq_trigger(int irq)
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 
 int assign_irq_vector(int irq)
 {
@@ -1249,6 +1241,7 @@ static void __init setup_IO_APIC_irqs(void)
                spin_lock_irqsave(&ioapic_lock, flags);
                io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
                io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+               set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
        }
@@ -1944,6 +1937,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
 {
        int irq = vector_to_irq(vector);
 
+       move_irq(vector);
        ack_edge_ioapic_irq(irq);
 }
 
@@ -1958,6 +1952,7 @@ static void end_level_ioapic_vector (unsigned int vector)
 {
        int irq = vector_to_irq(vector);
 
+       move_irq(vector);
        end_level_ioapic_irq(irq);
 }
 
@@ -1975,14 +1970,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
        unmask_IO_APIC_irq(irq);
 }
 
+#ifdef CONFIG_SMP
 static void set_ioapic_affinity_vector (unsigned int vector,
                                        cpumask_t cpu_mask)
 {
        int irq = vector_to_irq(vector);
 
+       set_native_irq_info(vector, cpu_mask);
        set_ioapic_affinity_irq(irq, cpu_mask);
 }
 #endif
+#endif
 
 /*
  * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1992,7 +1990,7 @@ static void set_ioapic_affinity_vector (unsigned int vector,
  * edge-triggered handler, without risking IRQ storms and other ugly
  * races.
  */
-static struct hw_interrupt_type ioapic_edge_type = {
+static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
        .typename       = "IO-APIC-edge",
        .startup        = startup_edge_ioapic,
        .shutdown       = shutdown_edge_ioapic,
@@ -2000,10 +1998,12 @@ static struct hw_interrupt_type ioapic_edge_type = {
        .disable        = disable_edge_ioapic,
        .ack            = ack_edge_ioapic,
        .end            = end_edge_ioapic,
+#ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity,
+#endif
 };
 
-static struct hw_interrupt_type ioapic_level_type = {
+static struct hw_interrupt_type ioapic_level_type __read_mostly = {
        .typename       = "IO-APIC-level",
        .startup        = startup_level_ioapic,
        .shutdown       = shutdown_level_ioapic,
@@ -2011,7 +2011,9 @@ static struct hw_interrupt_type ioapic_level_type = {
        .disable        = disable_level_ioapic,
        .ack            = mask_and_ack_level_ioapic,
        .end            = end_level_ioapic,
+#ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity,
+#endif
 };
 
 static inline void init_IO_APIC_traps(void)
@@ -2074,7 +2076,7 @@ static void ack_lapic_irq (unsigned int irq)
 
 static void end_lapic_irq (unsigned int i) { /* nothing */ }
 
-static struct hw_interrupt_type lapic_irq_type = {
+static struct hw_interrupt_type lapic_irq_type __read_mostly = {
        .typename       = "local-APIC-edge",
        .startup        = NULL, /* startup_irq() not used for IRQ0 */
        .shutdown       = NULL, /* shutdown_irq() not used for IRQ0 */
@@ -2569,6 +2571,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
        spin_lock_irqsave(&ioapic_lock, flags);
        io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
        io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+       set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
        return 0;
index a6d8c45961d3ccb33503f38535802d3a7e022afc..6345b430b105fd913c1fdca36768910e2f7fd580 100644 (file)
@@ -62,32 +62,32 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode)
        return 0;
 }
 
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        return 0;
 }
 
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
        memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
        p->opcode = *p->addr;
 }
 
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
        *p->addr = BREAKPOINT_INSTRUCTION;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
        *p->addr = p->opcode;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
 }
 
@@ -127,7 +127,8 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
                regs->eip = (unsigned long)&p->ainsn.insn;
 }
 
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+                                     struct pt_regs *regs)
 {
        unsigned long *sara = (unsigned long *)&regs->esp;
         struct kretprobe_instance *ri;
@@ -150,7 +151,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled thorough out this function.
  */
-static int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p;
        int ret = 0;
@@ -176,7 +177,8 @@ static int kprobe_handler(struct pt_regs *regs)
                   Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
-                       if (kprobe_status == KPROBE_HIT_SS) {
+                       if (kprobe_status == KPROBE_HIT_SS &&
+                               *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
                                regs->eflags &= ~TF_MASK;
                                regs->eflags |= kprobe_saved_eflags;
                                unlock_kprobes();
@@ -220,7 +222,10 @@ static int kprobe_handler(struct pt_regs *regs)
                         * either a probepoint or a debugger breakpoint
                         * at this address.  In either case, no further
                         * handling of this interrupt is appropriate.
+                        * Back up over the (now missing) int3 and run
+                        * the original instruction.
                         */
+                       regs->eip -= sizeof(kprobe_opcode_t);
                        ret = 1;
                }
                /* Not one of ours: let kernel handle it */
@@ -259,7 +264,7 @@ no_kprobe:
 /*
  * Called when we hit the probe point at kretprobe_trampoline
  */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
@@ -338,7 +343,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  * that is atop the stack is the address following the copied instruction.
  * We need to make it the address following the original instruction.
  */
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        unsigned long *tos = (unsigned long *)&regs->esp;
        unsigned long next_eip = 0;
@@ -444,8 +449,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 /*
  * Wrapper routine to for handling exceptions.
  */
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
-                            void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
 {
        struct die_args *args = (struct die_args *)data;
        switch (val) {
@@ -473,7 +478,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        return NOTIFY_DONE;
 }
 
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct jprobe *jp = container_of(p, struct jprobe, kp);
        unsigned long addr;
@@ -495,7 +500,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
 {
        preempt_enable_no_resched();
        asm volatile ("       xchgl   %%ebx,%%esp     \n"
@@ -506,7 +511,7 @@ void jprobe_return(void)
                      (jprobe_saved_esp):"memory");
 }
 
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        u8 *addr = (u8 *) (regs->eip - 1);
        unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
index 8bbdbda07a2d6c0dd54d68ec06ea968b52d064fb..0178457db72130b54d3170dfd8150742b8addfe1 100644 (file)
@@ -478,6 +478,11 @@ void touch_nmi_watchdog (void)
         */
        for (i = 0; i < NR_CPUS; i++)
                alert_counter[i] = 0;
+
+       /*
+        * Tickle the softlockup detector too:
+        */
+       touch_softlockup_watchdog();
 }
 
 extern void die_nmi(struct pt_regs *, const char *msg);
index 294bcca985ab7ec2de873dff4716f0681500c0be..e29fd5aeaf8e4fa9dfa5f73281e17b7079c153f9 100644 (file)
@@ -82,7 +82,7 @@ EXPORT_SYMBOL(efi_enabled);
 /* cpu data as detected by the assembly code in head.S */
 struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 /* common cpu data for all cpus */
-struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
index 6f794a78ee1e7be1f12074b7c0cfaad15aa8a9fd..eefea7c5500893bd47e9d9485f7111ae34cd76e1 100644 (file)
@@ -194,10 +194,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
@@ -252,8 +249,7 @@ EXPORT_SYMBOL(profile_pc);
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void do_timer_interrupt(int irq, void *dev_id,
-                                       struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_IO_APIC
        if (timer_ack) {
@@ -307,7 +303,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        cur_timer->mark_offset();
  
-       do_timer_interrupt(irq, NULL, regs);
+       do_timer_interrupt(irq, regs);
 
        write_sequnlock(&xtime_lock);
        return IRQ_HANDLED;
@@ -348,7 +344,7 @@ static void sync_cmos_clock(unsigned long dummy)
         * This code is run on a timer.  If the clock is set, that timer
         * may not expire at the correct time.  Thus, we adjust...
         */
-       if ((time_status & STA_UNSYNC) != 0)
+       if (!ntp_synced())
                /*
                 * Not synced, exit, do not restart a timer (if one is
                 * running, let it run out).
@@ -422,6 +418,7 @@ static int timer_resume(struct sys_device *dev)
                last_timer->resume();
        cur_timer = last_timer;
        last_timer = NULL;
+       touch_softlockup_watchdog();
        return 0;
 }
 
index 001de97c9e4a78b720cf5d567e60656739c200a5..d973a8b681fd5256d75212e77e43131141e07641 100644 (file)
@@ -18,8 +18,8 @@
 #include "mach_timer.h"
 #include <asm/hpet.h>
 
-static unsigned long __read_mostly hpet_usec_quotient; /* convert hpet clks to usec */
-static unsigned long tsc_hpet_quotient;                /* convert tsc to hpet clks */
+static unsigned long hpet_usec_quotient __read_mostly; /* convert hpet clks to usec */
+static unsigned long tsc_hpet_quotient __read_mostly;  /* convert tsc to hpet clks */
 static unsigned long hpet_last;        /* hpet counter value at last tick*/
 static unsigned long last_tsc_low;     /* lsb 32 bits of Time Stamp Counter */
 static unsigned long last_tsc_high;    /* msb 32 bits of Time Stamp Counter */
index 54629bb5893ae1c9ab6765ea6b84a23c1fae3761..09a58cb6daa7050e018496a127458241f2fa0e30 100644 (file)
@@ -363,8 +363,9 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
                die(str, regs, err);
 }
 
-static void do_trap(int trapnr, int signr, char *str, int vm86,
-                          struct pt_regs * regs, long error_code, siginfo_t *info)
+static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+                             struct pt_regs * regs, long error_code,
+                             siginfo_t *info)
 {
        struct task_struct *tsk = current;
        tsk->thread.error_code = error_code;
@@ -460,7 +461,8 @@ DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 
-fastcall void do_general_protection(struct pt_regs * regs, long error_code)
+fastcall void __kprobes do_general_protection(struct pt_regs * regs,
+                                             long error_code)
 {
        int cpu = get_cpu();
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
@@ -657,7 +659,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
 
        ++nmi_count(cpu);
 
-       if (!nmi_callback(regs, cpu))
+       if (!rcu_dereference(nmi_callback)(regs, cpu))
                default_do_nmi(regs);
 
        nmi_exit();
@@ -665,7 +667,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
 
 void set_nmi_callback(nmi_callback_t callback)
 {
-       nmi_callback = callback;
+       rcu_assign_pointer(nmi_callback, callback);
 }
 EXPORT_SYMBOL_GPL(set_nmi_callback);
 
@@ -676,7 +678,7 @@ void unset_nmi_callback(void)
 EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
 #ifdef CONFIG_KPROBES
-fastcall void do_int3(struct pt_regs *regs, long error_code)
+fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
@@ -710,7 +712,7 @@ fastcall void do_int3(struct pt_regs *regs, long error_code)
  * find every occurrence of the TF bit that could be saved away even
  * by user code)
  */
-fastcall void do_debug(struct pt_regs * regs, long error_code)
+fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
 {
        unsigned int condition;
        struct task_struct *tsk = current;
index 761972f8cb6c86dadf1ed297d2ea12a6ae234977..13b9c62cbbb45ce1d95357a1784afea6f8e3db89 100644 (file)
@@ -22,6 +22,7 @@ SECTIONS
        *(.text)
        SCHED_TEXT
        LOCK_TEXT
+       KPROBES_TEXT
        *(.fixup)
        *(.gnu.warning)
        } = 0x9090
index 23395fff35d16e59dcade164354dc0045ee95d1f..b64314069e785636a2375ed44c354bd717dd91fb 100644 (file)
@@ -76,7 +76,7 @@ static int __init topology_init(void)
        for_each_online_node(i)
                arch_register_node(i);
 
-       for_each_cpu(i)
+       for_each_present_cpu(i)
                arch_register_cpu(i);
        return 0;
 }
@@ -87,7 +87,7 @@ static int __init topology_init(void)
 {
        int i;
 
-       for_each_cpu(i)
+       for_each_present_cpu(i)
                arch_register_cpu(i);
        return 0;
 }
index 6711ce3f6916ad3601b33d4ba5a2d694f2bd2989..244d8ec66be2a473361bf00d81e81ba53cdf9fe0 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/mmzone.h>
 #include <bios_ebda.h>
 
-struct pglist_data *node_data[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 bootmem_data_t node0_bdata;
 
@@ -49,8 +49,8 @@ bootmem_data_t node0_bdata;
  * 2) node_start_pfn   - the starting page frame number for a node
  * 3) node_end_pfn     - the ending page fram number for a node
  */
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
+unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
 
 
 #ifdef CONFIG_DISCONTIGMEM
@@ -66,7 +66,7 @@ unsigned long node_end_pfn[MAX_NUMNODES];
  *     physnode_map[4-7] = 1;
  *     physnode_map[8- ] = -1;
  */
-s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
 EXPORT_SYMBOL(physnode_map);
 
 void memory_present(int nid, unsigned long start, unsigned long end)
index 411b8500ad1b07736c92412fb3eaced4e5baf4f8..9edd4485b91eafd6396affe5649c92d00b8666ae 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/kprobes.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -223,7 +224,8 @@ fastcall void do_invalid_op(struct pt_regs *, unsigned long);
  *     bit 1 == 0 means read, 1 means write
  *     bit 2 == 0 means kernel, 1 means user-mode
  */
-fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+fastcall void __kprobes do_page_fault(struct pt_regs *regs,
+                                     unsigned long error_code)
 {
        struct task_struct *tsk;
        struct mm_struct *mm;
index 9edfc058b8943bb95cf056a86ffe7a2e443e6b5a..2ebaf75f732e92e8e901ea408e490718794b8821 100644 (file)
@@ -393,7 +393,7 @@ void zap_low_mappings (void)
 }
 
 static int disable_nx __initdata = 0;
-u64 __supported_pte_mask = ~_PAGE_NX;
+u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
 
 /*
  * noexec = on|off
index c90332de582b9a213c5aa91a0557c3ce93179567..5341d481d92fb789e4432abc69eb14fbc268036a 100644 (file)
@@ -15,9 +15,9 @@
  * with the NMI mode driver.
  */
  
-extern int nmi_init(struct oprofile_operations * ops);
-extern int nmi_timer_init(struct oprofile_operations * ops);
-extern void nmi_exit(void);
+extern int op_nmi_init(struct oprofile_operations * ops);
+extern int op_nmi_timer_init(struct oprofile_operations * ops);
+extern void op_nmi_exit(void);
 extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
 
 
@@ -28,11 +28,11 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
        ret = -ENODEV;
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       ret = nmi_init(ops);
+       ret = op_nmi_init(ops);
 #endif
 #ifdef CONFIG_X86_IO_APIC
        if (ret < 0)
-               ret = nmi_timer_init(ops);
+               ret = op_nmi_timer_init(ops);
 #endif
        ops->backtrace = x86_backtrace;
 
@@ -43,6 +43,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
 void oprofile_arch_exit(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-       nmi_exit();
+       op_nmi_exit();
 #endif
 }
index 255e4702d185e363558c5064751ae7be9f9c20c0..0493e8b8ec49266618b155fb3490f02854dc70db 100644 (file)
@@ -355,7 +355,7 @@ static int __init ppro_init(char ** cpu_type)
 /* in order to get driverfs right */
 static int using_nmi;
 
-int __init nmi_init(struct oprofile_operations *ops)
+int __init op_nmi_init(struct oprofile_operations *ops)
 {
        __u8 vendor = boot_cpu_data.x86_vendor;
        __u8 family = boot_cpu_data.x86;
@@ -420,7 +420,7 @@ int __init nmi_init(struct oprofile_operations *ops)
 }
 
 
-void nmi_exit(void)
+void op_nmi_exit(void)
 {
        if (using_nmi)
                exit_driverfs();
index c58d0c14f2744a0ae524f07d3f73089d9486e049..ad93cdd55d63bf20f20b8bf4ad7ab0329910017b 100644 (file)
@@ -40,7 +40,7 @@ static void timer_stop(void)
 }
 
 
-int __init nmi_timer_init(struct oprofile_operations * ops)
+int __init op_nmi_timer_init(struct oprofile_operations * ops)
 {
        extern int nmi_active;
 
index 3deced637f07c814706698e6e90a10088aebe889..17b5dbf8c311909faa9a1871da94868e89bbb547 100644 (file)
@@ -434,6 +434,11 @@ config GENERIC_IRQ_PROBE
        bool
        default y
 
+config GENERIC_PENDING_IRQ
+       bool
+       depends on GENERIC_HARDIRQS && SMP
+       default y
+
 source "arch/ia64/hp/sim/Kconfig"
 
 source "arch/ia64/oprofile/Kconfig"
index 7dcb8582ae0d6c0b5cc8384485034585899b7a57..b42ec37be51c317911e1037d85718a9b95fdc045 100644 (file)
@@ -130,7 +130,7 @@ static void rs_stop(struct tty_struct *tty)
 
 static void rs_start(struct tty_struct *tty)
 {
-#if SIMSERIAL_DEBUG
+#ifdef SIMSERIAL_DEBUG
        printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
                tty->stopped, tty->hw_stopped, tty->flow_stopped);
 #endif
index 829a6d80711c13827ecd5fe74d19f0ce4732a1dc..0708edb06cc4da8190f76eb4e16e1bafcb2e6833 100644 (file)
@@ -215,7 +215,7 @@ ia32_syscall_table:
        data8 sys32_fork
        data8 sys_read
        data8 sys_write
-       data8 sys32_open          /* 5 */
+       data8 compat_sys_open     /* 5 */
        data8 sys_close
        data8 sys32_waitpid
        data8 sys_creat
index c1e20d65dd6cb4688391f928f43445aea644b66b..e29a8a55486a5e35fdc8eac3a2bb0acefc5cb062 100644 (file)
@@ -2359,37 +2359,6 @@ sys32_brk (unsigned int brk)
        return ret;
 }
 
-/*
- * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
- */
-asmlinkage long
-sys32_open (const char __user * filename, int flags, int mode)
-{
-       char * tmp;
-       int fd, error;
-
-       tmp = getname(filename);
-       fd = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               fd = get_unused_fd();
-               if (fd >= 0) {
-                       struct file *f = filp_open(tmp, flags, mode);
-                       error = PTR_ERR(f);
-                       if (IS_ERR(f))
-                               goto out_error;
-                       fd_install(fd, f);
-               }
-out:
-               putname(tmp);
-       }
-       return fd;
-
-out_error:
-       put_unused_fd(fd);
-       fd = error;
-       goto out;
-}
-
 /* Structure for ia32 emulation on ia64 */
 struct epoll_event32
 {
index b242594be55b46716d0ddf0a08e01dab60df14dd..307514f7a2826207fc5e8da881f64c61c7f8a06c 100644 (file)
@@ -16,7 +16,7 @@ obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
 obj-$(CONFIG_IA64_PALINFO)     += palinfo.o
 obj-$(CONFIG_IOSAPIC)          += iosapic.o
 obj-$(CONFIG_MODULES)          += module.o
-obj-$(CONFIG_SMP)              += smp.o smpboot.o domain.o
+obj-$(CONFIG_SMP)              += smp.o smpboot.o
 obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_PERFMON)          += perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)     += cyclone.o
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
deleted file mode 100644 (file)
index bbb8efe..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * arch/ia64/kernel/domain.c
- * Architecture specific sched-domains builder.
- *
- * Copyright (C) 2004 Jesse Barnes
- * Copyright (C) 2004 Silicon Graphics, Inc.
- */
-
-#include <linux/sched.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-#include <linux/cpumask.h>
-#include <linux/init.h>
-#include <linux/topology.h>
-#include <linux/nodemask.h>
-
-#define SD_NODES_PER_DOMAIN 16
-
-#ifdef CONFIG_NUMA
-/**
- * find_next_best_node - find the next node to include in a sched_domain
- * @node: node whose sched_domain we're building
- * @used_nodes: nodes already in the sched_domain
- *
- * Find the next node to include in a given scheduling domain.  Simply
- * finds the closest node not already in the @used_nodes map.
- *
- * Should use nodemask_t.
- */
-static int find_next_best_node(int node, unsigned long *used_nodes)
-{
-       int i, n, val, min_val, best_node = 0;
-
-       min_val = INT_MAX;
-
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               /* Start at @node */
-               n = (node + i) % MAX_NUMNODES;
-
-               if (!nr_cpus_node(n))
-                       continue;
-
-               /* Skip already used nodes */
-               if (test_bit(n, used_nodes))
-                       continue;
-
-               /* Simple min distance search */
-               val = node_distance(node, n);
-
-               if (val < min_val) {
-                       min_val = val;
-                       best_node = n;
-               }
-       }
-
-       set_bit(best_node, used_nodes);
-       return best_node;
-}
-
-/**
- * sched_domain_node_span - get a cpumask for a node's sched_domain
- * @node: node whose cpumask we're constructing
- * @size: number of nodes to include in this span
- *
- * Given a node, construct a good cpumask for its sched_domain to span.  It
- * should be one that prevents unnecessary balancing, but also spreads tasks
- * out optimally.
- */
-static cpumask_t sched_domain_node_span(int node)
-{
-       int i;
-       cpumask_t span, nodemask;
-       DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
-
-       cpus_clear(span);
-       bitmap_zero(used_nodes, MAX_NUMNODES);
-
-       nodemask = node_to_cpumask(node);
-       cpus_or(span, span, nodemask);
-       set_bit(node, used_nodes);
-
-       for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
-               int next_node = find_next_best_node(node, used_nodes);
-               nodemask = node_to_cpumask(next_node);
-               cpus_or(span, span, nodemask);
-       }
-
-       return span;
-}
-#endif
-
-/*
- * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we
- * can switch it on easily if needed.
- */
-#ifdef CONFIG_SCHED_SMT
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static struct sched_group sched_group_cpus[NR_CPUS];
-static int cpu_to_cpu_group(int cpu)
-{
-       return cpu;
-}
-#endif
-
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static struct sched_group sched_group_phys[NR_CPUS];
-static int cpu_to_phys_group(int cpu)
-{
-#ifdef CONFIG_SCHED_SMT
-       return first_cpu(cpu_sibling_map[cpu]);
-#else
-       return cpu;
-#endif
-}
-
-#ifdef CONFIG_NUMA
-/*
- * The init_sched_build_groups can't handle what we want to do with node
- * groups, so roll our own. Now each node has its own list of groups which
- * gets dynamically allocated.
- */
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static struct sched_group *sched_group_nodes[MAX_NUMNODES];
-
-static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
-static struct sched_group sched_group_allnodes[MAX_NUMNODES];
-
-static int cpu_to_allnodes_group(int cpu)
-{
-       return cpu_to_node(cpu);
-}
-#endif
-
-/*
- * Build sched domains for a given set of cpus and attach the sched domains
- * to the individual cpus
- */
-void build_sched_domains(const cpumask_t *cpu_map)
-{
-       int i;
-
-       /*
-        * Set up domains for cpus specified by the cpu_map.
-        */
-       for_each_cpu_mask(i, *cpu_map) {
-               int group;
-               struct sched_domain *sd = NULL, *p;
-               cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
-
-               cpus_and(nodemask, nodemask, *cpu_map);
-
-#ifdef CONFIG_NUMA
-               if (num_online_cpus()
-                               > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
-                       sd = &per_cpu(allnodes_domains, i);
-                       *sd = SD_ALLNODES_INIT;
-                       sd->span = *cpu_map;
-                       group = cpu_to_allnodes_group(i);
-                       sd->groups = &sched_group_allnodes[group];
-                       p = sd;
-               } else
-                       p = NULL;
-
-               sd = &per_cpu(node_domains, i);
-               *sd = SD_NODE_INIT;
-               sd->span = sched_domain_node_span(cpu_to_node(i));
-               sd->parent = p;
-               cpus_and(sd->span, sd->span, *cpu_map);
-#endif
-
-               p = sd;
-               sd = &per_cpu(phys_domains, i);
-               group = cpu_to_phys_group(i);
-               *sd = SD_CPU_INIT;
-               sd->span = nodemask;
-               sd->parent = p;
-               sd->groups = &sched_group_phys[group];
-
-#ifdef CONFIG_SCHED_SMT
-               p = sd;
-               sd = &per_cpu(cpu_domains, i);
-               group = cpu_to_cpu_group(i);
-               *sd = SD_SIBLING_INIT;
-               sd->span = cpu_sibling_map[i];
-               cpus_and(sd->span, sd->span, *cpu_map);
-               sd->parent = p;
-               sd->groups = &sched_group_cpus[group];
-#endif
-       }
-
-#ifdef CONFIG_SCHED_SMT
-       /* Set up CPU (sibling) groups */
-       for_each_cpu_mask(i, *cpu_map) {
-               cpumask_t this_sibling_map = cpu_sibling_map[i];
-               cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
-               if (i != first_cpu(this_sibling_map))
-                       continue;
-
-               init_sched_build_groups(sched_group_cpus, this_sibling_map,
-                                               &cpu_to_cpu_group);
-       }
-#endif
-
-       /* Set up physical groups */
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               cpumask_t nodemask = node_to_cpumask(i);
-
-               cpus_and(nodemask, nodemask, *cpu_map);
-               if (cpus_empty(nodemask))
-                       continue;
-
-               init_sched_build_groups(sched_group_phys, nodemask,
-                                               &cpu_to_phys_group);
-       }
-
-#ifdef CONFIG_NUMA
-       init_sched_build_groups(sched_group_allnodes, *cpu_map,
-                               &cpu_to_allnodes_group);
-
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               /* Set up node groups */
-               struct sched_group *sg, *prev;
-               cpumask_t nodemask = node_to_cpumask(i);
-               cpumask_t domainspan;
-               cpumask_t covered = CPU_MASK_NONE;
-               int j;
-
-               cpus_and(nodemask, nodemask, *cpu_map);
-               if (cpus_empty(nodemask))
-                       continue;
-
-               domainspan = sched_domain_node_span(i);
-               cpus_and(domainspan, domainspan, *cpu_map);
-
-               sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
-               sched_group_nodes[i] = sg;
-               for_each_cpu_mask(j, nodemask) {
-                       struct sched_domain *sd;
-                       sd = &per_cpu(node_domains, j);
-                       sd->groups = sg;
-                       if (sd->groups == NULL) {
-                               /* Turn off balancing if we have no groups */
-                               sd->flags = 0;
-                       }
-               }
-               if (!sg) {
-                       printk(KERN_WARNING
-                       "Can not alloc domain group for node %d\n", i);
-                       continue;
-               }
-               sg->cpu_power = 0;
-               sg->cpumask = nodemask;
-               cpus_or(covered, covered, nodemask);
-               prev = sg;
-
-               for (j = 0; j < MAX_NUMNODES; j++) {
-                       cpumask_t tmp, notcovered;
-                       int n = (i + j) % MAX_NUMNODES;
-
-                       cpus_complement(notcovered, covered);
-                       cpus_and(tmp, notcovered, *cpu_map);
-                       cpus_and(tmp, tmp, domainspan);
-                       if (cpus_empty(tmp))
-                               break;
-
-                       nodemask = node_to_cpumask(n);
-                       cpus_and(tmp, tmp, nodemask);
-                       if (cpus_empty(tmp))
-                               continue;
-
-                       sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
-                       if (!sg) {
-                               printk(KERN_WARNING
-                               "Can not alloc domain group for node %d\n", j);
-                               break;
-                       }
-                       sg->cpu_power = 0;
-                       sg->cpumask = tmp;
-                       cpus_or(covered, covered, tmp);
-                       prev->next = sg;
-                       prev = sg;
-               }
-               prev->next = sched_group_nodes[i];
-       }
-#endif
-
-       /* Calculate CPU power for physical packages and nodes */
-       for_each_cpu_mask(i, *cpu_map) {
-               int power;
-               struct sched_domain *sd;
-#ifdef CONFIG_SCHED_SMT
-               sd = &per_cpu(cpu_domains, i);
-               power = SCHED_LOAD_SCALE;
-               sd->groups->cpu_power = power;
-#endif
-
-               sd = &per_cpu(phys_domains, i);
-               power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
-                               (cpus_weight(sd->groups->cpumask)-1) / 10;
-               sd->groups->cpu_power = power;
-
-#ifdef CONFIG_NUMA
-               sd = &per_cpu(allnodes_domains, i);
-               if (sd->groups) {
-                       power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
-                               (cpus_weight(sd->groups->cpumask)-1) / 10;
-                       sd->groups->cpu_power = power;
-               }
-#endif
-       }
-
-#ifdef CONFIG_NUMA
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               struct sched_group *sg = sched_group_nodes[i];
-               int j;
-
-               if (sg == NULL)
-                       continue;
-next_sg:
-               for_each_cpu_mask(j, sg->cpumask) {
-                       struct sched_domain *sd;
-                       int power;
-
-                       sd = &per_cpu(phys_domains, j);
-                       if (j != first_cpu(sd->groups->cpumask)) {
-                               /*
-                                * Only add "power" once for each
-                                * physical package.
-                                */
-                               continue;
-                       }
-                       power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
-                               (cpus_weight(sd->groups->cpumask)-1) / 10;
-
-                       sg->cpu_power += power;
-               }
-               sg = sg->next;
-               if (sg != sched_group_nodes[i])
-                       goto next_sg;
-       }
-#endif
-
-       /* Attach the domains */
-       for_each_cpu_mask(i, *cpu_map) {
-               struct sched_domain *sd;
-#ifdef CONFIG_SCHED_SMT
-               sd = &per_cpu(cpu_domains, i);
-#else
-               sd = &per_cpu(phys_domains, i);
-#endif
-               cpu_attach_domain(sd, i);
-       }
-}
-/*
- * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
- */
-void arch_init_sched_domains(const cpumask_t *cpu_map)
-{
-       cpumask_t cpu_default_map;
-
-       /*
-        * Setup mask for cpus without special case scheduling requirements.
-        * For now this just excludes isolated cpus, but could be used to
-        * exclude other special cases in the future.
-        */
-       cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
-
-       build_sched_domains(&cpu_default_map);
-}
-
-void arch_destroy_sched_domains(const cpumask_t *cpu_map)
-{
-#ifdef CONFIG_NUMA
-       int i;
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               cpumask_t nodemask = node_to_cpumask(i);
-               struct sched_group *oldsg, *sg = sched_group_nodes[i];
-
-               cpus_and(nodemask, nodemask, *cpu_map);
-               if (cpus_empty(nodemask))
-                       continue;
-
-               if (sg == NULL)
-                       continue;
-               sg = sg->next;
-next_sg:
-               oldsg = sg;
-               sg = sg->next;
-               kfree(oldsg);
-               if (oldsg != sched_group_nodes[i])
-                       goto next_sg;
-               sched_group_nodes[i] = NULL;
-       }
-#endif
-}
-
index 28f2aadc38d00ed2318be5690648b563d9044776..205d980282612e8a4f41ccd97858df3ac5da5dde 100644 (file)
@@ -91,23 +91,8 @@ skip:
 }
 
 #ifdef CONFIG_SMP
-/*
- * This is updated when the user sets irq affinity via /proc
- */
-static cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
-static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
-
 static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
 
-/*
- * Arch specific routine for deferred write to iosapic rte to reprogram
- * intr destination.
- */
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
-       pending_irq_cpumask[irq] = mask_val;
-}
-
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
        cpumask_t mask = CPU_MASK_NONE;
@@ -116,32 +101,10 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 
        if (irq < NR_IRQS) {
                irq_affinity[irq] = mask;
+               set_irq_info(irq, mask);
                irq_redir[irq] = (char) (redir & 0xff);
        }
 }
-
-
-void move_irq(int irq)
-{
-       /* note - we hold desc->lock */
-       cpumask_t tmp;
-       irq_desc_t *desc = irq_descp(irq);
-       int redir = test_bit(irq, pending_irq_redir);
-
-       if (unlikely(!desc->handler->set_affinity))
-               return;
-
-       if (!cpus_empty(pending_irq_cpumask[irq])) {
-               cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
-               if (unlikely(!cpus_empty(tmp))) {
-                       desc->handler->set_affinity(irq | (redir ? IA64_IRQ_REDIRECTED : 0),
-                                                   pending_irq_cpumask[irq]);
-               }
-               cpus_clear(pending_irq_cpumask[irq]);
-       }
-}
-
-
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_HOTPLUG_CPU
index b7fa3ccd2b0f7ca124836866284a8762d67207ac..2323377e36950ee236a662bcddada08c2f423d45 100644 (file)
@@ -49,6 +49,7 @@
        /*
         * void jprobe_break(void)
         */
+       .section .kprobes.text, "ax"
 ENTRY(jprobe_break)
        break.m 0x80300
 END(jprobe_break)
index 884f5cd27d8a656856a46342f616d4a198ec25c6..471086b808a4b942781aa19abe940fb08dc8533b 100644 (file)
@@ -87,12 +87,25 @@ static enum instruction_type bundle_encoding[32][3] = {
  * is IP relative instruction and update the kprobe
  * inst flag accordingly
  */
-static void update_kprobe_inst_flag(uint template, uint  slot, uint major_opcode,
-       unsigned long kprobe_inst, struct kprobe *p)
+static void __kprobes update_kprobe_inst_flag(uint template, uint  slot,
+                                             uint major_opcode,
+                                             unsigned long kprobe_inst,
+                                             struct kprobe *p)
 {
        p->ainsn.inst_flag = 0;
        p->ainsn.target_br_reg = 0;
 
+       /* Check for Break instruction
+        * Bits 37:40 Major opcode to be zero
+        * Bits 27:32 X6 to be zero
+        * Bits 32:35 X3 to be zero
+        */
+       if ((!major_opcode) && (!((kprobe_inst >> 27) & 0x1FF)) ) {
+               /* is a break instruction */
+               p->ainsn.inst_flag |= INST_FLAG_BREAK_INST;
+               return;
+       }
+
        if (bundle_encoding[template][slot] == B) {
                switch (major_opcode) {
                  case INDIRECT_CALL_OPCODE:
@@ -126,8 +139,10 @@ static void update_kprobe_inst_flag(uint template, uint  slot, uint major_opcode
  * Returns 0 if supported
  * Returns -EINVAL if unsupported
  */
-static int unsupported_inst(uint template, uint  slot, uint major_opcode,
-       unsigned long kprobe_inst, struct kprobe *p)
+static int __kprobes unsupported_inst(uint template, uint  slot,
+                                     uint major_opcode,
+                                     unsigned long kprobe_inst,
+                                     struct kprobe *p)
 {
        unsigned long addr = (unsigned long)p->addr;
 
@@ -168,8 +183,9 @@ static int unsupported_inst(uint template, uint  slot, uint major_opcode,
  * on which we are inserting kprobe is cmp instruction
  * with ctype as unc.
  */
-static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
-unsigned long kprobe_inst)
+static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
+                                           uint major_opcode,
+                                           unsigned long kprobe_inst)
 {
        cmp_inst_t cmp_inst;
        uint ctype_unc = 0;
@@ -201,8 +217,10 @@ out:
  * In this function we override the bundle with
  * the break instruction at the given slot.
  */
-static void prepare_break_inst(uint template, uint  slot, uint major_opcode,
-       unsigned long kprobe_inst, struct kprobe *p)
+static void __kprobes prepare_break_inst(uint template, uint  slot,
+                                        uint major_opcode,
+                                        unsigned long kprobe_inst,
+                                        struct kprobe *p)
 {
        unsigned long break_inst = BREAK_INST;
        bundle_t *bundle = &p->ainsn.insn.bundle;
@@ -271,7 +289,8 @@ static inline int in_ivt_functions(unsigned long addr)
                && addr < (unsigned long)__end_ivt_text);
 }
 
-static int valid_kprobe_addr(int template, int slot, unsigned long addr)
+static int __kprobes valid_kprobe_addr(int template, int slot,
+                                      unsigned long addr)
 {
        if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
                printk(KERN_WARNING "Attempting to insert unaligned kprobe "
@@ -323,7 +342,7 @@ static void kretprobe_trampoline(void)
  *    - cleanup by marking the instance as unused
  *    - long jump back to the original return address
  */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct kretprobe_instance *ri = NULL;
        struct hlist_head *head;
@@ -381,7 +400,8 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         return 1;
 }
 
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+                                     struct pt_regs *regs)
 {
        struct kretprobe_instance *ri;
 
@@ -399,7 +419,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
        }
 }
 
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        unsigned long addr = (unsigned long) p->addr;
        unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
@@ -430,7 +450,7 @@ int arch_prepare_kprobe(struct kprobe *p)
        return 0;
 }
 
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
@@ -439,7 +459,7 @@ void arch_arm_kprobe(struct kprobe *p)
        flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
 }
 
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
@@ -449,7 +469,7 @@ void arch_disarm_kprobe(struct kprobe *p)
        flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
 }
 
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
 }
 
@@ -461,7 +481,7 @@ void arch_remove_kprobe(struct kprobe *p)
  * to original stack address, handle the case where we need to fixup the
  * relative IP address and/or fixup branch register.
  */
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
        unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
@@ -528,13 +548,16 @@ turn_ss_off:
        ia64_psr(regs)->ss = 0;
 }
 
-static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
 {
        unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
        unsigned long slot = (unsigned long)p->addr & 0xf;
 
-       /* Update instruction pointer (IIP) and slot number (IPSR.ri) */
-       regs->cr_iip = bundle_addr & ~0xFULL;
+       /* single step inline if break instruction */
+       if (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)
+               regs->cr_iip = (unsigned long)p->addr & ~0xFULL;
+       else
+               regs->cr_iip = bundle_addr & ~0xFULL;
 
        if (slot > 2)
                slot = 0;
@@ -545,7 +568,39 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
        ia64_psr(regs)->ss = 1;
 }
 
-static int pre_kprobes_handler(struct die_args *args)
+static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
+{
+       unsigned int slot = ia64_psr(regs)->ri;
+       unsigned int template, major_opcode;
+       unsigned long kprobe_inst;
+       unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
+       bundle_t bundle;
+
+       memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
+       template = bundle.quad0.template;
+
+       /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+       if (slot == 1 && bundle_encoding[template][1] == L)
+               slot++;
+
+       /* Get Kprobe probe instruction at given slot*/
+       get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);
+
+       /* For break instruction,
+        * Bits 37:40 Major opcode to be zero
+        * Bits 27:32 X6 to be zero
+        * Bits 32:35 X3 to be zero
+        */
+       if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
+               /* Not a break instruction */
+               return 0;
+       }
+
+       /* Is a break instruction */
+       return 1;
+}
+
+static int __kprobes pre_kprobes_handler(struct die_args *args)
 {
        struct kprobe *p;
        int ret = 0;
@@ -558,7 +613,9 @@ static int pre_kprobes_handler(struct die_args *args)
        if (kprobe_running()) {
                p = get_kprobe(addr);
                if (p) {
-                       if (kprobe_status == KPROBE_HIT_SS) {
+                       if ( (kprobe_status == KPROBE_HIT_SS) &&
+                            (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
+                               ia64_psr(regs)->ss = 0;
                                unlock_kprobes();
                                goto no_kprobe;
                        }
@@ -592,6 +649,19 @@ static int pre_kprobes_handler(struct die_args *args)
        p = get_kprobe(addr);
        if (!p) {
                unlock_kprobes();
+               if (!is_ia64_break_inst(regs)) {
+                       /*
+                        * The breakpoint instruction was removed right
+                        * after we hit it.  Another cpu has removed
+                        * either a probepoint or a debugger breakpoint
+                        * at this address.  In either case, no further
+                        * handling of this interrupt is appropriate.
+                        */
+                       ret = 1;
+
+               }
+
+               /* Not one of our break, let kernel handle it */
                goto no_kprobe;
        }
 
@@ -616,7 +686,7 @@ no_kprobe:
        return ret;
 }
 
-static int post_kprobes_handler(struct pt_regs *regs)
+static int __kprobes post_kprobes_handler(struct pt_regs *regs)
 {
        if (!kprobe_running())
                return 0;
@@ -641,7 +711,7 @@ out:
        return 1;
 }
 
-static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
 {
        if (!kprobe_running())
                return 0;
@@ -659,8 +729,8 @@ static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
        return 0;
 }
 
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
-                            void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
 {
        struct die_args *args = (struct die_args *)data;
        switch(val) {
@@ -681,7 +751,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        return NOTIFY_DONE;
 }
 
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct jprobe *jp = container_of(p, struct jprobe, kp);
        unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
@@ -703,7 +773,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        *regs = jprobe_saved_regs;
        return 1;
index 4440c8343fa4303df0dbc658954d9d3cebc1ab8d..f970359e7edf2fbb67117695c2f7b1a25f86b4d0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/module.h>       /* for EXPORT_SYMBOL */
 #include <linux/hardirq.h>
+#include <linux/kprobes.h>
 
 #include <asm/fpswa.h>
 #include <asm/ia32.h>
@@ -122,7 +123,7 @@ die_if_kernel (char *str, struct pt_regs *regs, long err)
 }
 
 void
-ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
+__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
 {
        siginfo_t siginfo;
        int sig, code;
@@ -444,7 +445,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
        return rv;
 }
 
-void
+void __kprobes
 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
            unsigned long iim, unsigned long itir, long arg5, long arg6,
            long arg7, struct pt_regs regs)
index a676e79e0681bb183986e3036e6484f8878c4e70..30d8564e96032bd9b7cc9735721457627db9ff7d 100644 (file)
@@ -48,6 +48,7 @@ SECTIONS
        *(.text)
        SCHED_TEXT
        LOCK_TEXT
+       KPROBES_TEXT
        *(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
index 3e2cfa2c6d39436d29f0c05e8f8cb1611fe76560..2a0d27f2f21bdd200df5c62a010e4673bc314abd 100644 (file)
@@ -20,6 +20,7 @@
         *
         *      Note: "in0" and "in1" are preserved for debugging purposes.
         */
+       .section .kprobes.text,"ax"
 GLOBAL_ENTRY(flush_icache_range)
 
        .prologue
index ff62551eb3a125765463768adaec354107200b47..24614869e866ed7f2bd653d1cdc577d4aa02ce89 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/kprobes.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned long address)
        return pte_present(pte);
 }
 
-void
+void __kprobes
 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
 {
        int signal = SIGSEGV, code = SEGV_MAPERR;
index 4564ed0b5ff31e32aab74c819369e3762382f512..906622d9f933374931b07a570c91fa17f7bcd41d 100644 (file)
@@ -431,7 +431,7 @@ void sn_bus_store_sysdata(struct pci_dev *dev)
 {
        struct sysdata_el *element;
 
-       element = kcalloc(1, sizeof(struct sysdata_el), GFP_KERNEL);
+       element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
        if (!element) {
                dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
                return;
index 254fe15c064b705ab5575cda49634a3c45ab5735..b45db5133f55062abda30bc36b194e3ff8f2012f 100644 (file)
@@ -191,7 +191,7 @@ cx_device_register(nasid_t nasid, int part_num, int mfg_num,
 {
        struct cx_dev *cx_dev;
 
-       cx_dev = kcalloc(1, sizeof(struct cx_dev), GFP_KERNEL);
+       cx_dev = kzalloc(sizeof(struct cx_dev), GFP_KERNEL);
        DBG("cx_dev= 0x%p\n", cx_dev);
        if (cx_dev == NULL)
                return -ENOMEM;
index ea09c12f02586de9d6bc49507951fb919420ea70..19bced34d5f1f1e79998fb11917053c91567ad1f 100644 (file)
@@ -148,7 +148,7 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
        tioca_kern->ca_pcigart_entries =
            tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
        tioca_kern->ca_pcigart_pagemap =
-           kcalloc(1, tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
+           kzalloc(tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
        if (!tioca_kern->ca_pcigart_pagemap) {
                free_pages((unsigned long)tioca_kern->ca_gart,
                           get_order(tioca_kern->ca_gart_size));
@@ -392,7 +392,7 @@ tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
         * allocate a map struct
         */
 
-       ca_dmamap = kcalloc(1, sizeof(struct tioca_dmamap), GFP_ATOMIC);
+       ca_dmamap = kzalloc(sizeof(struct tioca_dmamap), GFP_ATOMIC);
        if (!ca_dmamap)
                goto map_return;
 
@@ -600,7 +600,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
         * Allocate kernel bus soft and copy from prom.
         */
 
-       tioca_common = kcalloc(1, sizeof(struct tioca_common), GFP_KERNEL);
+       tioca_common = kzalloc(sizeof(struct tioca_common), GFP_KERNEL);
        if (!tioca_common)
                return NULL;
 
@@ -609,7 +609,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
 
        /* init kernel-private area */
 
-       tioca_kern = kcalloc(1, sizeof(struct tioca_kernel), GFP_KERNEL);
+       tioca_kern = kzalloc(sizeof(struct tioca_kernel), GFP_KERNEL);
        if (!tioca_kern) {
                kfree(tioca_common);
                return NULL;
index 8a2b77bc5749b50b01a45ef3c81b6d2c8870fc05..539c562cd54de57b04eb45f59ea5bea9fc3f0012 100644 (file)
@@ -171,10 +171,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
 
@@ -221,7 +218,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * called as close as possible to 500 ms before the new second starts.
         */
        write_seqlock(&xtime_lock);
-       if ((time_status & STA_UNSYNC) == 0
+       if (ntp_synced()
                && xtime.tv_sec > last_rtc_update + 660
                && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
                && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
index 178c4a3fbb72c22229edeec9be348c6899a7bd95..ba960bbc8e6d41124dd9b706ce92f1d27be7b832 100644 (file)
@@ -25,6 +25,11 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       depends on Q40 || (BROKEN && SUN3X)
+       default y
+
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
index c6b2a410bf9abaea143de4e52376dcf06d840909..eb63ca6ed94c591668bbc94c6861571e36da13f6 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/poll.h>
+#include <linux/module.h>
 #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
 #include <linux/smp_lock.h>
 #include <asm/bvme6000hw.h>
@@ -171,7 +172,7 @@ static struct miscdevice rtc_dev = {
        .fops =         &rtc_fops
 };
 
-int __init rtc_DP8570A_init(void)
+static int __init rtc_DP8570A_init(void)
 {
        if (!MACH_IS_BVME6000)
                return -ENODEV;
@@ -179,4 +180,4 @@ int __init rtc_DP8570A_init(void)
        printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION);
        return misc_register(&rtc_dev);
 }
-
+module_init(rtc_DP8570A_init);
index e47e19588525e47c1fb19edba8ae3621201e6d08..4ec95e3cb8748721ec6b37880d0a87aaf1b55f83 100644 (file)
@@ -166,10 +166,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index 8a2425069088240e0e87031dd1c103108eca5eb7..7977eae50af27c2344bb432844493c1e8a8a2143 100644 (file)
@@ -161,7 +161,7 @@ static struct miscdevice rtc_dev=
        .fops =         &rtc_fops
 };
 
-int __init rtc_MK48T08_init(void)
+static int __init rtc_MK48T08_init(void)
 {
        if (!MACH_IS_MVME16x)
                return -ENODEV;
@@ -169,4 +169,4 @@ int __init rtc_MK48T08_init(void)
        printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
        return misc_register(&rtc_dev);
 }
-
+module_init(rtc_MK48T08_init);
index 5c3ca671627c19fdd82cb71e631801448be616c7..b17c1ecba966e103d36ad2f7108b4c28a16d2b1a 100644 (file)
@@ -68,7 +68,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec  / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -178,10 +178,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index d79fba0aa8bf12657cdaab3e9946fdd884a76c7e..8d76eb1ff29169080b025ca5f0a7c153c6e4e72c 100644 (file)
@@ -4,6 +4,11 @@ config MIPS
        # Horrible source of confusion.  Die, die, die ...
        select EMBEDDED
 
+# shouldn't it be per-subarchitecture?
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 mainmenu "Linux/MIPS Kernel Configuration"
 
 source "init/Kconfig"
index 4613219dd73ef9f290529589012372b499285418..ece4564919d8f76c077ccf8cdbb6c95545f8d468 100644 (file)
@@ -546,20 +546,20 @@ struct msgbuf32 { s32 mtype; char mtext[1]; };
 struct ipc_perm32
 {
        key_t             key;
-        compat_uid_t  uid;
-        compat_gid_t  gid;
-        compat_uid_t  cuid;
-        compat_gid_t  cgid;
+        __compat_uid_t  uid;
+        __compat_gid_t  gid;
+        __compat_uid_t  cuid;
+        __compat_gid_t  cgid;
         compat_mode_t  mode;
         unsigned short  seq;
 };
 
 struct ipc64_perm32 {
        key_t key;
-       compat_uid_t uid;
-       compat_gid_t gid;
-       compat_uid_t cuid;
-       compat_gid_t cgid;
+       __compat_uid_t uid;
+       __compat_gid_t gid;
+       __compat_uid_t cuid;
+       __compat_gid_t cgid;
        compat_mode_t   mode;
        unsigned short  seq;
        unsigned short __pad1;
index f3bf0e43b8bb207ed0d50d4f01a14525509d2195..b4659546271789c6498967d40f81bb68e7283f83 100644 (file)
@@ -632,10 +632,7 @@ asmlinkage int irix_stime(int value)
        write_seqlock_irq(&xtime_lock);
        xtime.tv_sec = value;
        xtime.tv_nsec = 0;
-       time_adjust = 0;                        /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
 
        return 0;
index 648c82292ed6c8ab8870b09902d694de87f211a1..0dd0df7a3b04af60f095e03bd33cd6db0c3adac9 100644 (file)
@@ -223,10 +223,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                        /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
 
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
@@ -442,7 +439,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * called as close as possible to 500 ms before the new second starts.
         */
        write_seqlock(&xtime_lock);
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
index 8c1b96fffa764e8e3a4c9d7ea163c04d2a61620e..cddf1cedf007108daf8bfbb8f286656f7e48e196 100644 (file)
@@ -118,7 +118,7 @@ again:
         * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to when a second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
index 1c2d87435233ca911ff1d4773cf7268a0847e504..0b07922a2ac603e32451514a64a5250878389b5c 100644 (file)
@@ -49,6 +49,10 @@ config ISA_DMA_API
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 
index 6cf7407344badb9c4a7841b94d98251ec6264e27..7ff67f8e9f8c019bd2132cef0e3cabf6768859d9 100644 (file)
@@ -188,10 +188,7 @@ do_settimeofday (struct timespec *tv)
                set_normalized_timespec(&xtime, sec, nsec);
                set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-               time_adjust = 0;                /* stop active adjtime() */
-               time_status |= STA_UNSYNC;
-               time_maxerror = NTP_PHASE_LIMIT;
-               time_esterror = NTP_PHASE_LIMIT;
+               ntp_clear();
        }
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
index 36dee0ff5ca048719ba8b6f9187fb6918ccb7cf7..6ab7e5ea5fcfd9e0ae748d83bde3f31f158fa25b 100644 (file)
@@ -47,6 +47,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "Processor"
index bf4ddca5e853b22f460a7d4f8b0a06e396ae406c..a3c5281a5d2d8c05e328a6fc5c83f10b9981193c 100644 (file)
@@ -169,7 +169,7 @@ void timer_interrupt(struct pt_regs * regs)
                 * We should have an rtc call that only sets the minutes and
                 * seconds like on Intel to avoid problems with non UTC clocks.
                 */
-               if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
+               if ( ppc_md.set_rtc_time && ntp_synced() &&
                     xtime.tv_sec - last_rtc_update >= 659 &&
                     abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ &&
                     jiffies - wall_jiffies == 1) {
@@ -271,10 +271,7 @@ int do_settimeofday(struct timespec *tv)
         */
        last_rtc_update = new_sec - 658;
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irqrestore(&xtime_lock, flags);
        clock_was_set();
        return 0;
index e5fd2ae503ea7c2240c373f022ffa0c989ad52e3..9ccce438bd7af7ffc1dce54b32377a5975140bcd 100644 (file)
@@ -165,7 +165,7 @@ ocp_device_remove(struct device *dev)
 }
 
 static int
-ocp_device_suspend(struct device *dev, u32 state)
+ocp_device_suspend(struct device *dev, pm_message_t state)
 {
        struct ocp_device *ocp_dev = to_ocp_dev(dev);
        struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
index 13b262f10216aa4d88d88988374ef744f9b3174f..deca68ad644ae41681537867c7e8accdb6d2a18b 100644 (file)
@@ -44,6 +44,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 # We optimistically allocate largepages from the VM, so make the limit
 # large enough (16MB). This badly named config option is actually
 # max order + 1
index 6350cce82efb9d5c27ed703a6c4fb8e5a9275534..8189953a372c93b6579f150359facb604cb4af46 100644 (file)
@@ -49,7 +49,7 @@ NM            := $(NM) --synthetic
 
 endif
 
-CHECKFLAGS     += -m64 -D__powerpc__
+CHECKFLAGS     += -m64 -D__powerpc__ -D__powerpc64__
 
 LDFLAGS                := -m elf64ppc
 LDFLAGS_vmlinux        := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
index a3d519518fb8dfe41f2bcf7450bd2d5546bc3987..7e80d49c589a3bf2f5eea3e68f3d3690b1ceeb03 100644 (file)
@@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev;
 static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
 static struct pt_regs jprobe_saved_regs;
 
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        int ret = 0;
        kprobe_opcode_t insn = *p->addr;
@@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p)
        return ret;
 }
 
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
        memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
        p->opcode = *p->addr;
 }
 
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
        *p->addr = BREAKPOINT_INSTRUCTION;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
        *p->addr = p->opcode;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        up(&kprobe_mutex);
        free_insn_slot(p->ainsn.insn);
@@ -102,7 +102,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
        regs->msr |= MSR_SE;
 
        /* single step inline if it is a trap variant */
-       if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn))
+       if (is_trap(insn))
                regs->nip = (unsigned long)p->addr;
        else
                regs->nip = (unsigned long)p->ainsn.insn;
@@ -122,7 +122,8 @@ static inline void restore_previous_kprobe(void)
        kprobe_saved_msr = kprobe_saved_msr_prev;
 }
 
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+                                     struct pt_regs *regs)
 {
        struct kretprobe_instance *ri;
 
@@ -151,7 +152,9 @@ static inline int kprobe_handler(struct pt_regs *regs)
                   Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
-                       if (kprobe_status == KPROBE_HIT_SS) {
+                       kprobe_opcode_t insn = *p->ainsn.insn;
+                       if (kprobe_status == KPROBE_HIT_SS &&
+                                       is_trap(insn)) {
                                regs->msr &= ~MSR_SE;
                                regs->msr |= kprobe_saved_msr;
                                unlock_kprobes();
@@ -191,8 +194,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
                         * trap variant, it could belong to someone else
                         */
                        kprobe_opcode_t cur_insn = *addr;
-                       if (IS_TW(cur_insn) || IS_TD(cur_insn) ||
-                                       IS_TWI(cur_insn) || IS_TDI(cur_insn))
+                       if (is_trap(cur_insn))
                                goto no_kprobe;
                        /*
                         * The breakpoint instruction was removed right
@@ -244,7 +246,7 @@ void kretprobe_trampoline_holder(void)
 /*
  * Called when the probe at kretprobe trampoline is hit
  */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
@@ -308,7 +310,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  * single-stepped a copy of the instruction.  The address of this
  * copy is p->ainsn.insn.
  */
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        int ret;
        unsigned int insn = *p->ainsn.insn;
@@ -373,8 +375,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 /*
  * Wrapper routine to for handling exceptions.
  */
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
-                            void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
 {
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
@@ -402,11 +404,11 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        default:
                break;
        }
-       preempt_enable();
+       preempt_enable_no_resched();
        return ret;
 }
 
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct jprobe *jp = container_of(p, struct jprobe, kp);
 
@@ -419,16 +421,16 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
 {
        asm volatile("trap" ::: "memory");
 }
 
-void jprobe_return_end(void)
+void __kprobes jprobe_return_end(void)
 {
 };
 
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        /*
         * FIXME - we should ideally be validating that we got here 'cos
index 474df0a862bfac60094e0e50c6ba0890f87e03c7..6d860c1d9fa0849f44fab1856d77932d3a35fed3 100644 (file)
@@ -183,7 +183,7 @@ PPC64_CACHES:
  *   flush all bytes from start through stop-1 inclusive
  */
 
-_GLOBAL(__flush_icache_range)
+_KPROBE(__flush_icache_range)
 
 /*
  * Flush the data cache to memory 
@@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range)
        bdnz    2b
        isync
        blr
-       
+       .previous .text
 /*
  * Like above, but only do the D-cache.
  *
@@ -957,7 +957,7 @@ _GLOBAL(sys_call_table32)
        .llong .ppc_fork
        .llong .sys_read
        .llong .sys_write
-       .llong .sys32_open              /* 5 */
+       .llong .compat_sys_open         /* 5 */
        .llong .sys_close
        .llong .sys32_waitpid
        .llong .sys32_creat
index dc2a69d412a204820546107a47ab7c676036a7de..58c61219d08e0765646450c30cba107936db01ab 100644 (file)
@@ -111,7 +111,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
        struct device_node *np;
        int err = -ENOMEM;
 
-       np = kcalloc(1, sizeof(*np), GFP_KERNEL);
+       np = kzalloc(sizeof(*np), GFP_KERNEL);
        if (!np)
                goto out_err;
 
index 206619080e669b42cfdb3003dc85e715bf6e8221..214914a95a504e546a48837995bebfa9571a7eb1 100644 (file)
@@ -867,37 +867,6 @@ off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
        return sys_lseek(fd, (int)offset, origin);
 }
 
-/*
- * This is just a version for 32-bit applications which does
- * not force O_LARGEFILE on.
- */
-asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
-{
-       char * tmp;
-       int fd, error;
-
-       tmp = getname(filename);
-       fd = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               fd = get_unused_fd();
-               if (fd >= 0) {
-                       struct file * f = filp_open(tmp, flags, mode);
-                       error = PTR_ERR(f);
-                       if (IS_ERR(f))
-                               goto out_error;
-                       fd_install(fd, f);
-               }
-out:
-               putname(tmp);
-       }
-       return fd;
-
-out_error:
-       put_unused_fd(fd);
-       fd = error;
-       goto out;
-}
-
 /* Note: it is necessary to treat bufsiz as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
index 91ef95ccda4fca400f2efe3fd6d983a2f85a40b8..9939c206afa42c776eef326e92094a29e5eaa211 100644 (file)
@@ -128,7 +128,7 @@ static __inline__ void timer_check_rtc(void)
          * We should have an rtc call that only sets the minutes and
          * seconds like on Intel to avoid problems with non UTC clocks.
          */
-        if ( (time_status & STA_UNSYNC) == 0 &&
+        if (ntp_synced() &&
              xtime.tv_sec - last_rtc_update >= 659 &&
              abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
              jiffies - wall_jiffies == 1) {
@@ -435,10 +435,7 @@ int do_settimeofday(struct timespec *tv)
         */
        last_rtc_update = new_sec - 658;
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
 
        delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
                             do_gtod.varp->tb_to_xs );
index a8d5e83ee89fceafa18c46f43001aaebd4938567..7467ae508e6e27e734c1fc9110c2f03e60790900 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/kprobes.h>
 #include <asm/kdebug.h>
 
 #include <asm/pgtable.h>
@@ -220,7 +221,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
        _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
 }
 
-void single_step_exception(struct pt_regs *regs)
+void __kprobes single_step_exception(struct pt_regs *regs)
 {
        regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
 
@@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs)
        return 0;
 }
 
-void program_check_exception(struct pt_regs *regs)
+void __kprobes program_check_exception(struct pt_regs *regs)
 {
        if (debugger_fault_handler(regs))
                return;
index 4103cc13f8d62e93eb8d526f3ffa6c061129a52d..0306510bc4ffb00aec0997129c152f2e512890fa 100644 (file)
@@ -15,6 +15,7 @@ SECTIONS
        *(.text .text.*)
        SCHED_TEXT
        LOCK_TEXT
+       KPROBES_TEXT
        *(.fixup)
        . = ALIGN(4096);
        _etext = .;
index 20b0f37e8bf8fbe3ac28c2f0113a97b6aa951675..772f0714a5b7d4be9231b362650c920c1c70cb9c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
+#include <linux/kprobes.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -84,8 +85,8 @@ static int store_updates_sp(struct pt_regs *regs)
  * The return value is 0 if the fault was handled, or the signal
  * number if this is a kernel fault that can't be handled here.
  */
-int do_page_fault(struct pt_regs *regs, unsigned long address,
-                 unsigned long error_code)
+int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
+                           unsigned long error_code)
 {
        struct vm_area_struct * vma;
        struct mm_struct *mm = current->mm;
index 8ca485676780de694b31134f2303b094e5053e68..2fd75da1549522b13816e9a9c50e1be8c4db2b42 100644 (file)
@@ -139,10 +139,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
index adc8109f8b7719ca25c910f1600abd90495bc0e2..3e804c736e640eb9340128cf2adb18435a2ee61c 100644 (file)
@@ -37,6 +37,10 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "System type"
index df7a9b9d4cbffb298c77518958b97a9581dbfc4d..02ca69918d7c0992a943f7d7d856149f0145a9a3 100644 (file)
@@ -215,10 +215,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
 
@@ -234,7 +231,7 @@ static long last_rtc_update;
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
 {
        do_timer(regs);
 #ifndef CONFIG_SMP
@@ -252,7 +249,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
         * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -285,7 +282,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * locally disabled. -arca
         */
        write_seqlock(&xtime_lock);
-       do_timer_interrupt(irq, NULL, regs);
+       do_timer_interrupt(irq, regs);
        write_sequnlock(&xtime_lock);
 
        return IRQ_HANDLED;
index 6c84da3efc7383d3511434c91ef7815a05b2421d..f4a62a10053c60e6921d00b280d050a90eae8735 100644 (file)
@@ -247,10 +247,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
 
@@ -303,7 +300,7 @@ static long last_rtc_update = 0;
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
 {
        unsigned long long current_ctc;
        asm ("getcon cr62, %0" : "=r" (current_ctc));
@@ -328,7 +325,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
         * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -361,7 +358,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * locally disabled. -arca
         */
        write_lock(&xtime_lock);
-       do_timer_interrupt(irq, NULL, regs);
+       do_timer_interrupt(irq, regs);
        write_unlock(&xtime_lock);
 
        return IRQ_HANDLED;
index aca028aa29bfb5d2fb42896a7a73019b4fca4697..aba05394d30a05603685e2bcc62cc9c2b85b4d3b 100644 (file)
@@ -211,6 +211,10 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 config SUN_PM
        bool
        default y
index 597d3ff6ad68ce16d1a5426a7562cfba3d4e065d..36a40697b8d61e66a9c129a61cb009712199f663 100644 (file)
@@ -840,10 +840,7 @@ static int pci_do_settimeofday(struct timespec *tv)
 
        xtime.tv_sec = tv->tv_sec;
        xtime.tv_nsec = tv->tv_nsec;
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        return 0;
 }
 
index 3b759aefc170e39b69f76d93487da243b46c1dc4..bc015e980341060dc9eb3fa28d6bc9485cb964bd 100644 (file)
@@ -139,7 +139,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
 
        /* Determine when to update the Mostek clock. */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -554,10 +554,7 @@ static int sbus_do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        return 0;
 }
 
index 73ec6aec5ed5c60198f25876bd8e21f079ee3ab2..1e9d8638a28a249823d31f53c7d629d392240088 100644 (file)
@@ -26,6 +26,10 @@ config TIME_INTERPOLATION
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 choice
        prompt "Kernel page size"
        default SPARC64_PAGE_SIZE_8KB
index bbf11f85dab15a00a05c4c9d11774a8f93776c13..0d66d07c8c6eead89fa6e5799ec6ba5fcf57873f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kprobes.h>
 #include <asm/kdebug.h>
 #include <asm/signal.h>
+#include <asm/cacheflush.h>
 
 /* We do not have hardware single-stepping on sparc64.
  * So we implement software single-stepping with breakpoint
  * - Mark that we are no longer actively in a kprobe.
  */
 
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        return 0;
 }
 
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
        p->ainsn.insn[0] = *p->addr;
        p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
        p->opcode = *p->addr;
 }
 
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
        *p->addr = BREAKPOINT_INSTRUCTION;
        flushi(p->addr);
 }
 
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
        *p->addr = p->opcode;
        flushi(p->addr);
 }
 
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
 }
 
@@ -111,7 +112,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
        }
 }
 
-static int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p;
        void *addr = (void *) regs->tpc;
@@ -191,8 +192,9 @@ no_kprobe:
  * The original INSN location was REAL_PC, it actually
  * executed at PC and produced destination address NPC.
  */
-static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
-                                    unsigned long pc, unsigned long npc)
+static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
+                                              unsigned long pc,
+                                              unsigned long npc)
 {
        /* Branch not taken, no mods necessary.  */
        if (npc == pc + 0x4UL)
@@ -217,7 +219,8 @@ static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
 /* If INSN is an instruction which writes it's PC location
  * into a destination register, fix that up.
  */
-static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
+static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
+                                 unsigned long real_pc)
 {
        unsigned long *slot = NULL;
 
@@ -257,7 +260,7 @@ static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
  * This function prepares to return from the post-single-step
  * breakpoint trap.
  */
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        u32 insn = p->ainsn.insn[0];
 
@@ -315,8 +318,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 /*
  * Wrapper routine to for handling exceptions.
  */
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
-                            void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
 {
        struct die_args *args = (struct die_args *)data;
        switch (val) {
@@ -344,7 +347,8 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        return NOTIFY_DONE;
 }
 
-asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
+asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
+                                     struct pt_regs *regs)
 {
        BUG_ON(trap_level != 0x170 && trap_level != 0x171);
 
@@ -368,7 +372,7 @@ static struct pt_regs jprobe_saved_regs;
 static struct pt_regs *jprobe_saved_regs_location;
 static struct sparc_stackf jprobe_saved_stack;
 
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct jprobe *jp = container_of(p, struct jprobe, kp);
 
@@ -390,7 +394,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
 {
        preempt_enable_no_resched();
        __asm__ __volatile__(
@@ -403,7 +407,7 @@ extern void jprobe_return_trap_instruction(void);
 
 extern void __show_regs(struct pt_regs * regs);
 
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        u32 *addr = (u32 *) regs->tpc;
 
index 87c1aeb022204eac4faedfb1fc58e0b9e18920e5..7654b8a7f03a6ffb400ac8bbb27a8a02aab82d68 100644 (file)
@@ -152,11 +152,12 @@ asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg)
                ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg);
                goto out;
 
-       case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
-               ret = sys_ioctl(fd, SIOCSIFMTU, arg);
+       case _IOW('i', 21, struct ifreq32):
+               ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg);
                goto out;
-       case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
-               ret = sys_ioctl(fd, SIOCGIFMTU, arg);
+
+       case _IOWR('i', 22, struct ifreq32):
+               ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg);
                goto out;
 
        case _IOWR('i', 23, struct ifreq32):
index 1d3aa588df8a5a8466113947ae3d3102c021c1e1..7f6239ed252142e52c45f2921de58b339d770086 100644 (file)
@@ -1002,29 +1002,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
 asmlinkage long sparc32_open(const char __user *filename,
                             int flags, int mode)
 {
-       char * tmp;
-       int fd, error;
-
-       tmp = getname(filename);
-       fd = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               fd = get_unused_fd();
-               if (fd >= 0) {
-                       struct file * f = filp_open(tmp, flags, mode);
-                       error = PTR_ERR(f);
-                       if (IS_ERR(f))
-                               goto out_error;
-                       fd_install(fd, f);
-               }
-out:
-               putname(tmp);
-       }
-       return fd;
-
-out_error:
-       put_unused_fd(fd);
-       fd = error;
-       goto out;
+       return do_sys_open(filename, flags, mode);
 }
 
 extern unsigned long do_mremap(unsigned long addr,
index 362b9c26871b26af39abe9142bf7ed830ff31e66..3f08a32f51a16d2a91231ddcf15701dbdbe3d51b 100644 (file)
@@ -449,7 +449,7 @@ static inline void timer_check_rtc(void)
        static long last_rtc_update;
 
        /* Determine when to update the Mostek clock. */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
index 950423da8a6ab395767ce6aa8af112bcc773d493..f47d0be39378a2a7603e4470d0bb5962c1e2dc9e 100644 (file)
@@ -17,6 +17,7 @@ SECTIONS
     *(.text)
     SCHED_TEXT
     LOCK_TEXT
+    KPROBES_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
index 52e9375288a96f34d63cf94261c5b4ba3498b14e..db1e3310e907dc2ba2f4c60a237f2c69664964ff 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/kprobes.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -117,8 +118,9 @@ unsigned long __init prom_probe_memory (void)
        return tally;
 }
 
-static void unhandled_fault(unsigned long address, struct task_struct *tsk,
-                           struct pt_regs *regs)
+static void __kprobes unhandled_fault(unsigned long address,
+                                     struct task_struct *tsk,
+                                     struct pt_regs *regs)
 {
        if ((unsigned long) address < PAGE_SIZE) {
                printk(KERN_ALERT "Unable to handle kernel NULL "
@@ -304,7 +306,7 @@ cannot_handle:
        unhandled_fault (address, current, regs);
 }
 
-asmlinkage void do_sparc64_fault(struct pt_regs *regs)
+asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
index 3fbaf342a452368972f0db2c9881d4be555ad41d..fdb1ebb308c95bad153283b87e8665b177e0df2d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/kprobes.h>
 
 #include <asm/head.h>
 #include <asm/system.h>
@@ -250,7 +251,7 @@ out:
        put_cpu();
 }
 
-void flush_icache_range(unsigned long start, unsigned long end)
+void __kprobes flush_icache_range(unsigned long start, unsigned long end)
 {
        /* Cheetah has coherent I-cache. */
        if (tlb_type == spitfire) {
index 8dfa825eca51f5a92a269400b15b366f92b766ca..b2ee9b53227f5746b19351dc20ea873231831a58 100644 (file)
@@ -119,6 +119,7 @@ __spitfire_flush_tlb_mm_slow:
 #else
 #error unsupported PAGE_SIZE
 #endif
+       .section .kprobes.text, "ax"
        .align          32
        .globl          __flush_icache_page
 __flush_icache_page:   /* %o0 = phys_page */
@@ -201,6 +202,7 @@ dflush4:stxa                %g0, [%o4] ASI_DCACHE_TAG
         nop
 #endif /* DCACHE_ALIASING_POSSIBLE */
 
+       .previous .text
        .align          32
 __prefill_dtlb:
        rdpr            %pstate, %g7
index a777e57dbf893a2b92517ec804eea57c4ab03acc..1ab431a53ac3d0cc3eb336d5d1c07a996e7ab554 100644 (file)
@@ -27,7 +27,7 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
 endif
 endif
 
-CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS)
+CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
 
 ifneq ($(CONFIG_GPROF),y)
 ARCH_CFLAGS += -DUM_FASTCALL
index d705daa2d8543119127775040796b7904525a306..0aa620970adb5a4e930f139a649ed3874742e3d6 100644 (file)
@@ -12,3 +12,4 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
 DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
 DEFINE_STR(UM_KERN_INFO, KERN_INFO);
 DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+DEFINE(HOST_ELF_CLASS, ELF_CLASS);
index 6e348cb6de24a8eb1a0e6be8fa33868d72bbe73b..84c0868cd5613610c4f874aa280283d2d5f0a35b 100644 (file)
 #define access_ok(type, addr, size) \
        CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
-       return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
-                               size));
-}
-
 static inline int copy_from_user(void *to, const void __user *from, int n)
 {
        return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to,
index 5597bd39e6b54a9f9d93ac914327c5eb1fb264ed..64fa062cc1192bd60178d035cfe2e9bad80d67a3 100644 (file)
@@ -196,7 +196,7 @@ static void init_highmem(void)
 
 static void __init fixaddr_user_init( void)
 {
-#if CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
        long size = FIXADDR_USER_END - FIXADDR_USER_START;
        pgd_t *pgd;
        pud_t *pud;
index d3c1560e3ed85365bf1a93ffa6c644c38d6f3727..7a1662419c0c6d703e3f8d2f96d877aa379d643d 100644 (file)
@@ -9,6 +9,9 @@ obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
 USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
        tty.o
 
+elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
+CFLAGS_elf_aux.o += -I$(objtree)/arch/um
+
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
 
 HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \
index 4cca3e9c23fe065c3fb2c5a84464d7cd7ab44178..1399520a85889d79c37862f160233946939cbf22 100644 (file)
@@ -12,8 +12,9 @@
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
+#include <kernel-offsets.h>
 
-#if ELF_CLASS == ELFCLASS32
+#if HOST_ELF_CLASS == ELFCLASS32
 typedef Elf32_auxv_t elf_auxv_t;
 #else
 typedef Elf64_auxv_t elf_auxv_t;
index 9f8ecd1fdd9614b03a05c5fc03dd1d3d01b42132..a1070af2bcd823a1d2c580afbfb1c156b14242f5 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/elf.h>
 #include <asm/page.h>
 
 #define DEFINE(sym, val) \
index 220e875cbe292c09641f66534610ce55177145d5..998541eade41e0cd80f16cfc0a9de8835dd8467e 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/elf.h>
 #include <asm/page.h>
 
 #define DEFINE(sym, val) \
index f722a268238a69f8921f09f63c9df3003c4b6763..ea3fd8844ff06b1bc4df01188db13407def7b833 100644 (file)
@@ -66,7 +66,7 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       if ((time_status & STA_UNSYNC) == 0 &&
+       if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -169,10 +169,7 @@ int do_settimeofday(struct timespec *tv)
        xtime.tv_sec = tv->tv_sec;
        xtime.tv_nsec = tv->tv_nsec;
 
-       time_adjust = 0;                /* stop active adjtime () */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
 
        write_sequnlock_irq (&xtime_lock);
        clock_was_set();
index 75e52c57f19c0442e2288e7eefef45355b835e71..8f868b67ef0f1fe0060d3688cd2a37573a830c4f 100644 (file)
@@ -65,6 +65,10 @@ config GENERIC_IOMAP
        bool
        default y
 
+config ARCH_MAY_HAVE_PC_FDC
+       bool
+       default y
+
 source "init/Kconfig"
 
 
@@ -441,6 +445,11 @@ config ISA_DMA_API
        bool
        default y
 
+config GENERIC_PENDING_IRQ
+       bool
+       depends on GENERIC_HARDIRQS && SMP
+       default y
+
 menu "Power management options"
 
 source kernel/power/Kconfig
index ff58b2832b75d5b54df35e57a60fc9dd398c16cd..12ea0b6c52e2a8b48cea525ec530d49b8c1d97a5 100644 (file)
@@ -81,7 +81,7 @@ start:
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
                .ascii  "HdrS"          # header signature
-               .word   0x0203          # header version number (>= 0x0105)
+               .word   0x0204          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
 start_sys_seg: .word   SYSSEG
index 18b5bac1c4282fb94a8bb71afbc79a383164246a..c44f5e2ec1006fc93d09c7b958ccd5d4cb0ad709 100644 (file)
@@ -178,7 +178,9 @@ int main(int argc, char ** argv)
                die("Output: seek failed");
        buf[0] = (sys_size & 0xff);
        buf[1] = ((sys_size >> 8) & 0xff);
-       if (write(1, buf, 2) != 2)
+       buf[2] = ((sys_size >> 16) & 0xff);
+       buf[3] = ((sys_size >> 24) & 0xff);
+       if (write(1, buf, 4) != 4)
                die("Write of image length failed");
 
        return 0;                                           /* Everything is OK */
index c45d6a05b984f6d1e43e863e6da10b2b5f96d074..f174083d55672335bdbc0a442ae5c8fc4c2a697e 100644 (file)
@@ -307,7 +307,7 @@ ia32_sys_call_table:
        .quad stub32_fork
        .quad sys_read
        .quad sys_write
-       .quad sys32_open                /* 5 */
+       .quad compat_sys_open           /* 5 */
        .quad sys_close
        .quad sys32_waitpid
        .quad sys_creat
index be996d1b691e19e0061391794706484f2dac18a4..04d80406ce4fed4c1a6ce646253675c65b074269 100644 (file)
@@ -969,32 +969,6 @@ long sys32_kill(int pid, int sig)
        return sys_kill(pid, sig);
 }
  
-asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
-{
-       char * tmp;
-       int fd, error;
-
-       /* don't force O_LARGEFILE */
-       tmp = getname(filename);
-       fd = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               fd = get_unused_fd();
-               if (fd >= 0) {
-                       struct file *f = filp_open(tmp, flags, mode);
-                       error = PTR_ERR(f);
-                       if (IS_ERR(f)) {
-                               put_unused_fd(fd); 
-                               fd = error;
-                       } else {
-                               fsnotify_open(f->f_dentry);
-                               fd_install(fd, f);
-                       }
-               }
-               putname(tmp);
-       }
-       return fd;
-}
-
 extern asmlinkage long
 sys_timer_create(clockid_t which_clock,
                 struct sigevent __user *timer_event_spec,
index b548dea4e5b95e30c01f369f0c95dcd06db67551..116ac5f53dced70d0098178e57b7e09207d90603 100644 (file)
@@ -85,7 +85,7 @@ int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
                struct e820entry *ei = &e820.map[i]; 
                if (type && ei->type != type) 
                        continue;
-               if (ei->addr >= end || ei->addr + ei->size < start) 
+               if (ei->addr >= end || ei->addr + ei->size <= start)
                        continue; 
                return 1; 
        } 
index 096d470e280f38d6e64eb179a23525ecaa1252e5..be51dbe1f75ec1a91765e8a4735a052ae144c6e1 100644 (file)
@@ -784,8 +784,9 @@ ENTRY(execve)
        ret
        CFI_ENDPROC
 
-ENTRY(page_fault)
+KPROBE_ENTRY(page_fault)
        errorentry do_page_fault
+       .previous .text
 
 ENTRY(coprocessor_error)
        zeroentry do_coprocessor_error
@@ -797,13 +798,14 @@ ENTRY(device_not_available)
        zeroentry math_state_restore
 
        /* runs on exception stack */
-ENTRY(debug)
+KPROBE_ENTRY(debug)
        CFI_STARTPROC
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug
        jmp paranoid_exit
        CFI_ENDPROC
+       .previous .text
 
        /* runs on exception stack */   
 ENTRY(nmi)
@@ -854,8 +856,9 @@ paranoid_schedule:
        jmp paranoid_userspace
        CFI_ENDPROC
 
-ENTRY(int3)
+KPROBE_ENTRY(int3)
        zeroentry do_int3       
+       .previous .text
 
 ENTRY(overflow)
        zeroentry do_overflow
@@ -892,8 +895,9 @@ ENTRY(stack_segment)
        jmp paranoid_exit
        CFI_ENDPROC
 
-ENTRY(general_protection)
+KPROBE_ENTRY(general_protection)
        errorentry do_general_protection
+       .previous .text
 
 ENTRY(alignment_check)
        errorentry do_alignment_check
index 30c843a5efddf7cb2c3ed9312e2aadcbfb16d95d..f062aa03bab7e282d149091b852c3718e5dbb537 100644 (file)
@@ -25,7 +25,7 @@
 #endif
 
 /* which logical CPU number maps to which CPU (physical APIC ID) */
-u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
 u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
index 9703da7202e368fe97b73b197c57465f1f3e9f34..f6523dd1bc0938fb6f21ff811af0b8292d77ca46 100644 (file)
@@ -72,10 +72,14 @@ static void cluster_send_IPI_mask(cpumask_t mask, int vector)
 static void cluster_send_IPI_allbutself(int vector)
 {
        cpumask_t mask = cpu_online_map;
-       cpu_clear(smp_processor_id(), mask);
+       int me = get_cpu(); /* Ensure we are not preempted when we clear */
+
+       cpu_clear(me, mask);
 
        if (!cpus_empty(mask))
                cluster_send_IPI_mask(mask, vector);
+
+       put_cpu();
 }
 
 static void cluster_send_IPI_all(int vector)
index d206d7e49cf5a5381e0c72c96d202bb77c677020..ba1a744e9bf0d72e0d8a49eaed6b287243a80415 100644 (file)
@@ -70,7 +70,7 @@ static struct irq_pin_list {
        short apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
 
-int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
 #ifdef CONFIG_PCI_MSI
 #define vector_to_irq(vector)  \
        (platform_legacy_irq(vector) ? vector : vector_irq[vector])
@@ -78,6 +78,54 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
 #define vector_to_irq(vector)  (vector)
 #endif
 
+#define __DO_ACTION(R, ACTION, FINAL)                                  \
+                                                                       \
+{                                                                      \
+       int pin;                                                        \
+       struct irq_pin_list *entry = irq_2_pin + irq;                   \
+                                                                       \
+       for (;;) {                                                      \
+               unsigned int reg;                                       \
+               pin = entry->pin;                                       \
+               if (pin == -1)                                          \
+                       break;                                          \
+               reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
+               reg ACTION;                                             \
+               io_apic_modify(entry->apic, reg);                       \
+               if (!entry->next)                                       \
+                       break;                                          \
+               entry = irq_2_pin + entry->next;                        \
+       }                                                               \
+       FINAL;                                                          \
+}
+
+#ifdef CONFIG_SMP
+static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+       unsigned long flags;
+       unsigned int dest;
+       cpumask_t tmp;
+
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               tmp = TARGET_CPUS;
+
+       cpus_and(mask, tmp, CPU_MASK_ALL);
+
+       dest = cpu_mask_to_apicid(mask);
+
+       /*
+        * Only the high 8 bits are valid.
+        */
+       dest = SET_APIC_LOGICAL_ID(dest);
+
+       spin_lock_irqsave(&ioapic_lock, flags);
+       __DO_ACTION(1, = dest, )
+       set_irq_info(irq, mask);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+#endif
+
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
@@ -101,26 +149,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
        entry->pin = pin;
 }
 
-#define __DO_ACTION(R, ACTION, FINAL)                                  \
-                                                                       \
-{                                                                      \
-       int pin;                                                        \
-       struct irq_pin_list *entry = irq_2_pin + irq;                   \
-                                                                       \
-       for (;;) {                                                      \
-               unsigned int reg;                                       \
-               pin = entry->pin;                                       \
-               if (pin == -1)                                          \
-                       break;                                          \
-               reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
-               reg ACTION;                                             \
-               io_apic_modify(entry->apic, reg);                       \
-               if (!entry->next)                                       \
-                       break;                                          \
-               entry = irq_2_pin + entry->next;                        \
-       }                                                               \
-       FINAL;                                                          \
-}
 
 #define DO_ACTION(name,R,ACTION, FINAL)                                        \
                                                                        \
@@ -655,7 +683,7 @@ static inline int IO_APIC_irq_trigger(int irq)
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 
 int assign_irq_vector(int irq)
 {
@@ -767,6 +795,7 @@ static void __init setup_IO_APIC_irqs(void)
                spin_lock_irqsave(&ioapic_lock, flags);
                io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
                io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+               set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
        }
@@ -1314,6 +1343,7 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
  */
 static void ack_edge_ioapic_irq(unsigned int irq)
 {
+       move_irq(irq);
        if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
                                        == (IRQ_PENDING | IRQ_DISABLED))
                mask_IO_APIC_irq(irq);
@@ -1343,26 +1373,10 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq)
 
 static void end_level_ioapic_irq (unsigned int irq)
 {
+       move_irq(irq);
        ack_APIC_irq();
 }
 
-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
-{
-       unsigned long flags;
-       unsigned int dest;
-
-       dest = cpu_mask_to_apicid(mask);
-
-       /*
-        * Only the high 8 bits are valid.
-        */
-       dest = SET_APIC_LOGICAL_ID(dest);
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       __DO_ACTION(1, = dest, )
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
 #ifdef CONFIG_PCI_MSI
 static unsigned int startup_edge_ioapic_vector(unsigned int vector)
 {
@@ -1375,6 +1389,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
 {
        int irq = vector_to_irq(vector);
 
+       move_native_irq(vector);
        ack_edge_ioapic_irq(irq);
 }
 
@@ -1389,6 +1404,7 @@ static void end_level_ioapic_vector (unsigned int vector)
 {
        int irq = vector_to_irq(vector);
 
+       move_native_irq(vector);
        end_level_ioapic_irq(irq);
 }
 
@@ -1406,14 +1422,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
        unmask_IO_APIC_irq(irq);
 }
 
+#ifdef CONFIG_SMP
 static void set_ioapic_affinity_vector (unsigned int vector,
                                        cpumask_t cpu_mask)
 {
        int irq = vector_to_irq(vector);
 
+       set_native_irq_info(vector, cpu_mask);
        set_ioapic_affinity_irq(irq, cpu_mask);
 }
-#endif
+#endif // CONFIG_SMP
+#endif // CONFIG_PCI_MSI
 
 /*
  * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1424,7 +1443,7 @@ static void set_ioapic_affinity_vector (unsigned int vector,
  * races.
  */
 
-static struct hw_interrupt_type ioapic_edge_type = {
+static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
        .typename = "IO-APIC-edge",
        .startup        = startup_edge_ioapic,
        .shutdown       = shutdown_edge_ioapic,
@@ -1432,10 +1451,12 @@ static struct hw_interrupt_type ioapic_edge_type = {
        .disable        = disable_edge_ioapic,
        .ack            = ack_edge_ioapic,
        .end            = end_edge_ioapic,
+#ifdef CONFIG_SMP
        .set_affinity = set_ioapic_affinity,
+#endif
 };
 
-static struct hw_interrupt_type ioapic_level_type = {
+static struct hw_interrupt_type ioapic_level_type __read_mostly = {
        .typename = "IO-APIC-level",
        .startup        = startup_level_ioapic,
        .shutdown       = shutdown_level_ioapic,
@@ -1443,7 +1464,9 @@ static struct hw_interrupt_type ioapic_level_type = {
        .disable        = disable_level_ioapic,
        .ack            = mask_and_ack_level_ioapic,
        .end            = end_level_ioapic,
+#ifdef CONFIG_SMP
        .set_affinity = set_ioapic_affinity,
+#endif
 };
 
 static inline void init_IO_APIC_traps(void)
@@ -1506,7 +1529,7 @@ static void ack_lapic_irq (unsigned int irq)
 
 static void end_lapic_irq (unsigned int i) { /* nothing */ }
 
-static struct hw_interrupt_type lapic_irq_type = {
+static struct hw_interrupt_type lapic_irq_type __read_mostly = {
        .typename = "local-APIC-edge",
        .startup = NULL, /* startup_irq() not used for IRQ0 */
        .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
@@ -1918,6 +1941,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
        spin_lock_irqsave(&ioapic_lock, flags);
        io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
        io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+       set_native_irq_info(use_pci_vector() ?  entry.vector : irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
        return 0;
@@ -1931,6 +1955,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
  * we need to reprogram the ioredtbls to cater for the cpus which have come online
  * so mask in all cases should simply be TARGET_CPUS
  */
+#ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
        int pin, ioapic, irq, irq_entry;
@@ -1949,3 +1974,4 @@ void __init setup_ioapic_dest(void)
 
        }
 }
+#endif
index 5c6dc705148299e5cede75693244e10ebe367410..df08c43276a07fffee23a7dd7edf28feb92b2de7 100644 (file)
@@ -74,7 +74,7 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn)
        return 0;
 }
 
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        /* insn: must be on special executable page on x86_64. */
        up(&kprobe_mutex);
@@ -189,7 +189,7 @@ static inline s32 *is_riprel(u8 *insn)
        return NULL;
 }
 
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
        s32 *ripdisp;
        memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
@@ -215,21 +215,21 @@ void arch_copy_kprobe(struct kprobe *p)
        p->opcode = *p->addr;
 }
 
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
        *p->addr = BREAKPOINT_INSTRUCTION;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
        *p->addr = p->opcode;
        flush_icache_range((unsigned long) p->addr,
                           (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        up(&kprobe_mutex);
        free_insn_slot(p->ainsn.insn);
@@ -261,7 +261,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
                kprobe_saved_rflags &= ~IF_MASK;
 }
 
-static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
        regs->eflags |= TF_MASK;
        regs->eflags &= ~IF_MASK;
@@ -272,7 +272,8 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
                regs->rip = (unsigned long)p->ainsn.insn;
 }
 
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+                                     struct pt_regs *regs)
 {
        unsigned long *sara = (unsigned long *)regs->rsp;
         struct kretprobe_instance *ri;
@@ -295,7 +296,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled thorough out this function.
  */
-int kprobe_handler(struct pt_regs *regs)
+int __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p;
        int ret = 0;
@@ -310,7 +311,8 @@ int kprobe_handler(struct pt_regs *regs)
                   Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
-                       if (kprobe_status == KPROBE_HIT_SS) {
+                       if (kprobe_status == KPROBE_HIT_SS &&
+                               *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
                                regs->eflags &= ~TF_MASK;
                                regs->eflags |= kprobe_saved_rflags;
                                unlock_kprobes();
@@ -360,7 +362,10 @@ int kprobe_handler(struct pt_regs *regs)
                         * either a probepoint or a debugger breakpoint
                         * at this address.  In either case, no further
                         * handling of this interrupt is appropriate.
+                        * Back up over the (now missing) int3 and run
+                        * the original instruction.
                         */
+                       regs->rip = (unsigned long)addr;
                        ret = 1;
                }
                /* Not one of ours: let kernel handle it */
@@ -399,7 +404,7 @@ no_kprobe:
 /*
  * Called when we hit the probe point at kretprobe_trampoline
  */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
@@ -478,7 +483,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  * that is atop the stack is the address following the copied instruction.
  * We need to make it the address following the original instruction.
  */
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        unsigned long *tos = (unsigned long *)regs->rsp;
        unsigned long next_rip = 0;
@@ -536,7 +541,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
  * remain disabled thoroughout this function.  And we hold kprobe lock.
  */
-int post_kprobe_handler(struct pt_regs *regs)
+int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        if (!kprobe_running())
                return 0;
@@ -571,7 +576,7 @@ out:
 }
 
 /* Interrupts disabled, kprobe_lock held. */
-int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        if (current_kprobe->fault_handler
            && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
@@ -590,8 +595,8 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 /*
  * Wrapper routine for handling exceptions.
  */
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
-                            void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
 {
        struct die_args *args = (struct die_args *)data;
        switch (val) {
@@ -619,7 +624,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        return NOTIFY_DONE;
 }
 
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct jprobe *jp = container_of(p, struct jprobe, kp);
        unsigned long addr;
@@ -640,7 +645,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
 {
        preempt_enable_no_resched();
        asm volatile ("       xchg   %%rbx,%%rsp     \n"
@@ -651,7 +656,7 @@ void jprobe_return(void)
                      (jprobe_saved_rsp):"memory");
 }
 
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        u8 *addr = (u8 *) (regs->rip - 1);
        unsigned long stack_addr = (unsigned long)jprobe_saved_rsp;
index 64a8e05d5811b82fd258365d539ea37c72ed0b2c..caf164959e197d25f100b54c1195ef19257e9c72 100644 (file)
@@ -463,6 +463,8 @@ void touch_nmi_watchdog (void)
         */
        for (i = 0; i < NR_CPUS; i++)
                per_cpu(nmi_touch, i) = 1;
+
+       touch_softlockup_watchdog();
 }
 
 void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
@@ -522,14 +524,14 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 
        nmi_enter();
        add_pda(__nmi_count,1);
-       if (!nmi_callback(regs, cpu))
+       if (!rcu_dereference(nmi_callback)(regs, cpu))
                default_do_nmi(regs);
        nmi_exit();
 }
 
 void set_nmi_callback(nmi_callback_t callback)
 {
-       nmi_callback = callback;
+       rcu_assign_pointer(nmi_callback, callback);
 }
 
 void unset_nmi_callback(void)
index 7577f9d7a75d8373f1a79be83c4e30c63b867f19..8661f82ac70b409d96a70b31b84ad87c485fbd30 100644 (file)
@@ -310,6 +310,7 @@ void __show_regs(struct pt_regs * regs)
 
 void show_regs(struct pt_regs *regs)
 {
+       printk("CPU %d:", smp_processor_id());
        __show_regs(regs);
        show_trace(&regs->rsp);
 }
index 116a491e2961bbca273d7319559e285be6e2aed0..b356f8e6adfe974f94cd890cd1ddd1d9cc17dd08 100644 (file)
@@ -65,7 +65,7 @@
  * Machine setup..
  */
 
-struct cpuinfo_x86 boot_cpu_data;
+struct cpuinfo_x86 boot_cpu_data __read_mostly;
 
 unsigned long mmu_cr4_features;
 
index 34082c1cc41e397f4254de5a6d22ba474ffeb90d..e3ffcacc8c90bf40d17a778c684401a9d66b17d3 100644 (file)
@@ -36,7 +36,7 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
 
 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
 
-unsigned long __supported_pte_mask = ~0UL;
+unsigned long __supported_pte_mask __read_mostly = ~0UL;
 static int do_not_nx __initdata = 0;
 
 /* noexec=on|off
index fa25e39fe54dfc4aab4390c95b45039da0202558..90aeccd1519074c27b65524c6fa8bc601f0efb09 100644 (file)
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
 /* Package ID of each logical CPU */
-u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
-u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
 EXPORT_SYMBOL(phys_proc_id);
 EXPORT_SYMBOL(cpu_core_id);
 
 /* Bitmask of currently online CPUs */
-cpumask_t cpu_online_map;
+cpumask_t cpu_online_map __read_mostly;
 
 EXPORT_SYMBOL(cpu_online_map);
 
@@ -88,8 +88,8 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_core_map);
 
 /*
index 66bf6ddeb0c334a956c6bc2e75beeca9262b5f9e..7b6abe0582536f54f5c5aea12587d22d3ab92f1d 100644 (file)
@@ -176,10 +176,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
 
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
@@ -471,7 +468,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  * off) isn't likely to go away much sooner anyway.
  */
 
-       if ((~time_status & STA_UNSYNC) && xtime.tv_sec > rtc_update &&
+       if (ntp_synced() && xtime.tv_sec > rtc_update &&
                abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
                set_rtc_mmss(xtime.tv_sec);
                rtc_update = xtime.tv_sec + 660;
@@ -1041,6 +1038,7 @@ static int timer_resume(struct sys_device *dev)
        write_sequnlock_irqrestore(&xtime_lock,flags);
        jiffies += sleep_length;
        wall_jiffies += sleep_length;
+       touch_softlockup_watchdog();
        return 0;
 }
 
index 6ead433a38851783a915e1abd44269a69cd90d90..f238d6078a5a921fcf94c935903b9aaa3aac5bf0 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/nmi.h>
+#include <linux/kprobes.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -419,8 +420,9 @@ void die_nmi(char *str, struct pt_regs *regs)
        do_exit(SIGSEGV);
 }
 
-static void do_trap(int trapnr, int signr, char *str, 
-                          struct pt_regs * regs, long error_code, siginfo_t *info)
+static void __kprobes do_trap(int trapnr, int signr, char *str,
+                             struct pt_regs * regs, long error_code,
+                             siginfo_t *info)
 {
        conditional_sti(regs);
 
@@ -504,7 +506,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
 
-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+                                               long error_code)
 {
        conditional_sti(regs);
 
@@ -622,7 +625,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
                io_check_error(reason, regs);
 }
 
-asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
 {
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
                return;
@@ -653,7 +656,8 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
 }
 
 /* runs on IST stack. */
-asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
+asmlinkage void __kprobes do_debug(struct pt_regs * regs,
+                                  unsigned long error_code)
 {
        unsigned long condition;
        struct task_struct *tsk = current;
index 2a94f9b60b2dd3eec9937cab4799f793582129f5..d4abb07af52dbef72da991331845b4438251a60b 100644 (file)
@@ -21,6 +21,7 @@ SECTIONS
        *(.text)
        SCHED_TEXT
        LOCK_TEXT
+       KPROBES_TEXT
        *(.fixup)
        *(.gnu.warning)
        } = 0x9090
index ca914c3bd49cf9ee3042a06426facc57516830fe..816732d8858c3195c7b6d78419b2b0b537de3f10 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/compiler.h>
 #include <linux/module.h>
+#include <linux/kprobes.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -294,7 +295,8 @@ int exception_trace = 1;
  *     bit 2 == 0 means kernel, 1 means user-mode
  *      bit 3 == 1 means fault was an instruction fetch
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+                                       unsigned long error_code)
 {
        struct task_struct *tsk;
        struct mm_struct *mm;
index 6a156f5692ae78a520a4dc0694a78f70b4a6c71a..04f7a33e144c4bbbd05befd65d6c396184e6e75d 100644 (file)
 #define Dprintk(x...)
 #endif
 
-struct pglist_data *node_data[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 
 int memnode_shift;
 u8  memnodemap[NODEMAPSIZE];
 
-unsigned char cpu_to_node[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
-cpumask_t     node_to_cpumask[MAX_NUMNODES];
+unsigned char cpu_to_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
+cpumask_t     node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
 
index e07287db5a40da91f6ce377e14cd9b356843a9f9..1ac7d5ce7456659ecf771df51580aacdb8282454 100644 (file)
@@ -122,10 +122,7 @@ int do_settimeofday(struct timespec *tv)
        set_normalized_timespec(&xtime, sec, nsec);
        set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
+       ntp_clear();
        write_sequnlock_irq(&xtime_lock);
        return 0;
 }
@@ -184,7 +181,7 @@ again:
                next += CCOUNT_PER_JIFFY;
                do_timer (regs); /* Linux handler in kernel/timer.c */
 
-               if ((time_status & STA_UNSYNC) == 0 &&
+               if (ntp_synced() &&
                    xtime.tv_sec - last_rtc_update >= 659 &&
                    abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
                    jiffies - wall_jiffies == 1) {
index 3df47f93c9db01e0a19da8af237ab800ae9d34b1..dfd4bcfc59758332d8ae82fc1d0db2e009c9b26a 100644 (file)
@@ -191,6 +191,8 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
        u8 *iv = desc->info;
        unsigned int done = 0;
 
+       nbytes -= bsize;
+
        do {
                xor(iv, src);
                fn(crypto_tfm_ctx(tfm), dst, iv);
@@ -198,7 +200,7 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
 
                src += bsize;
                dst += bsize;
-       } while ((done += bsize) < nbytes);
+       } while ((done += bsize) <= nbytes);
 
        return done;
 }
@@ -219,6 +221,8 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
        u8 *iv = desc->info;
        unsigned int done = 0;
 
+       nbytes -= bsize;
+
        do {
                u8 *tmp_dst = *dst_p;
 
@@ -230,7 +234,7 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
 
                src += bsize;
                dst += bsize;
-       } while ((done += bsize) < nbytes);
+       } while ((done += bsize) <= nbytes);
 
        return done;
 }
@@ -243,12 +247,14 @@ static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
        void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
        unsigned int done = 0;
 
+       nbytes -= bsize;
+
        do {
                fn(crypto_tfm_ctx(tfm), dst, src);
 
                src += bsize;
                dst += bsize;
-       } while ((done += bsize) < nbytes);
+       } while ((done += bsize) <= nbytes);
 
        return done;
 }
index 652281402c923860d449ec7a652ff81fa6903447..5bfa2e9a7c2678efade79213aa5bd203054613b8 100644 (file)
@@ -28,6 +28,7 @@ enum {
        FW_STATUS_DONE,
        FW_STATUS_ABORT,
        FW_STATUS_READY,
+       FW_STATUS_READY_NOHOTPLUG,
 };
 
 static int loading_timeout = 10;       /* In seconds */
@@ -344,7 +345,7 @@ error_kfree:
 
 static int
 fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
-                     const char *fw_name, struct device *device)
+                     const char *fw_name, struct device *device, int hotplug)
 {
        struct class_device *class_dev;
        struct firmware_priv *fw_priv;
@@ -376,7 +377,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
                goto error_unreg;
        }
 
-       set_bit(FW_STATUS_READY, &fw_priv->status);
+       if (hotplug)
+                set_bit(FW_STATUS_READY, &fw_priv->status);
+        else
+                set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
        *class_dev_p = class_dev;
        goto out;
 
@@ -386,21 +390,9 @@ out:
        return retval;
 }
 
-/**
- * request_firmware: - request firmware to hotplug and wait for it
- * Description:
- *     @firmware will be used to return a firmware image by the name
- *     of @name for device @device.
- *
- *     Should be called from user context where sleeping is allowed.
- *
- *     @name will be use as $FIRMWARE in the hotplug environment and
- *     should be distinctive enough not to be confused with any other
- *     firmware image for this or any other device.
- **/
-int
-request_firmware(const struct firmware **firmware_p, const char *name,
-                struct device *device)
+static int
+_request_firmware(const struct firmware **firmware_p, const char *name,
+                struct device *device, int hotplug)
 {
        struct class_device *class_dev;
        struct firmware_priv *fw_priv;
@@ -419,22 +411,25 @@ request_firmware(const struct firmware **firmware_p, const char *name,
        }
        memset(firmware, 0, sizeof (*firmware));
 
-       retval = fw_setup_class_device(firmware, &class_dev, name, device);
+       retval = fw_setup_class_device(firmware, &class_dev, name, device,
+               hotplug);
        if (retval)
                goto error_kfree_fw;
 
        fw_priv = class_get_devdata(class_dev);
 
-       if (loading_timeout > 0) {
-               fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
-               add_timer(&fw_priv->timeout);
-       }
-
-       kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
-       wait_for_completion(&fw_priv->completion);
-       set_bit(FW_STATUS_DONE, &fw_priv->status);
+       if (hotplug) {
+               if (loading_timeout > 0) {
+                       fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
+                       add_timer(&fw_priv->timeout);
+               }
 
-       del_timer_sync(&fw_priv->timeout);
+               kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+               wait_for_completion(&fw_priv->completion);
+               set_bit(FW_STATUS_DONE, &fw_priv->status);
+               del_timer_sync(&fw_priv->timeout);
+       } else
+               wait_for_completion(&fw_priv->completion);
 
        down(&fw_lock);
        if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -454,6 +449,26 @@ out:
        return retval;
 }
 
+/**
+ * request_firmware: - request firmware to hotplug and wait for it
+ * Description:
+ *      @firmware will be used to return a firmware image by the name
+ *      of @name for device @device.
+ *
+ *      Should be called from user context where sleeping is allowed.
+ *
+ *      @name will be use as $FIRMWARE in the hotplug environment and
+ *      should be distinctive enough not to be confused with any other
+ *      firmware image for this or any other device.
+ **/
+int
+request_firmware(const struct firmware **firmware_p, const char *name,
+                 struct device *device)
+{
+        int hotplug = 1;
+        return _request_firmware(firmware_p, name, device, hotplug);
+}
+
 /**
  * release_firmware: - release the resource associated with a firmware image
  **/
@@ -491,6 +506,7 @@ struct firmware_work {
        struct device *device;
        void *context;
        void (*cont)(const struct firmware *fw, void *context);
+       int hotplug;
 };
 
 static int
@@ -503,7 +519,8 @@ request_firmware_work_func(void *arg)
                return 0;
        }
        daemonize("%s/%s", "firmware", fw_work->name);
-       request_firmware(&fw, fw_work->name, fw_work->device);
+       _request_firmware(&fw, fw_work->name, fw_work->device,
+               fw_work->hotplug);
        fw_work->cont(fw, fw_work->context);
        release_firmware(fw);
        module_put(fw_work->module);
@@ -518,6 +535,9 @@ request_firmware_work_func(void *arg)
  *     Asynchronous variant of request_firmware() for contexts where
  *     it is not possible to sleep.
  *
+ *      @hotplug invokes hotplug event to copy the firmware image if this flag
+ *      is non-zero else the firmware copy must be done manually.
+ *
  *     @cont will be called asynchronously when the firmware request is over.
  *
  *     @context will be passed over to @cont.
@@ -527,7 +547,7 @@ request_firmware_work_func(void *arg)
  **/
 int
 request_firmware_nowait(
-       struct module *module,
+       struct module *module, int hotplug,
        const char *name, struct device *device, void *context,
        void (*cont)(const struct firmware *fw, void *context))
 {
@@ -548,6 +568,7 @@ request_firmware_nowait(
                .device = device,
                .context = context,
                .cont = cont,
+               .hotplug = hotplug,
        };
 
        ret = kernel_thread(request_firmware_work_func, fw_work,
index 6b736364cc5b886589c54a21bfdc8afdda448fe9..51b0af1cebee15f0406ceaf4517538bb9a39edb3 100644 (file)
@@ -6,7 +6,7 @@ menu "Block devices"
 
 config BLK_DEV_FD
        tristate "Normal floppy disk support"
-       depends on (!ARCH_S390 && !M68K && !IA64 && !UML && !ARM) || Q40 || (SUN3X && BROKEN) || ARCH_RPC || ARCH_EBSA285
+       depends on ARCH_MAY_HAVE_PC_FDC
        ---help---
          If you want to use the floppy disk drive(s) of your PC under Linux,
          say Y. Information about this driver, especially important for IBM
index 6e231c5a119958dd3549e5d825f4706f9d04f9ec..ded33ba31accfccf0df29072903cad7493447470 100644 (file)
@@ -35,7 +35,7 @@ aoedev_newdev(ulong nframes)
        struct aoedev *d;
        struct frame *f, *e;
 
-       d = kcalloc(1, sizeof *d, GFP_ATOMIC);
+       d = kzalloc(sizeof *d, GFP_ATOMIC);
        if (d == NULL)
                return NULL;
        f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
index cd056e7e64ec15d5cf81f16068623e29e07ad187..30c0903c7cddfdd46dbdd0de9c8e999c1ed7f349 100644 (file)
@@ -2260,8 +2260,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
        if (!atomic_dec_and_test(&cfqd->ref))
                return;
 
-       blk_put_queue(q);
-
        cfq_shutdown_timer_wq(cfqd);
        q->elevator->elevator_data = NULL;
 
@@ -2318,7 +2316,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        e->elevator_data = cfqd;
 
        cfqd->queue = q;
-       atomic_inc(&q->refcnt);
 
        cfqd->max_queued = q->nr_requests / 4;
        q->nr_batching = cfq_queued;
index ff5201e021534693987f30597817ef7cdb2de317..24594c57c3230e5a095eb10ddb282137ed9161ba 100644 (file)
@@ -507,18 +507,12 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
        const int reads = !list_empty(&dd->fifo_list[READ]);
        const int writes = !list_empty(&dd->fifo_list[WRITE]);
        struct deadline_rq *drq;
-       int data_dir, other_dir;
+       int data_dir;
 
        /*
         * batches are currently reads XOR writes
         */
-       drq = NULL;
-
-       if (dd->next_drq[READ])
-               drq = dd->next_drq[READ];
-
-       if (dd->next_drq[WRITE])
-               drq = dd->next_drq[WRITE];
+       drq = dd->next_drq[WRITE] ? : dd->next_drq[READ];
 
        if (drq) {
                /* we have a "next request" */
@@ -544,7 +538,6 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
                        goto dispatch_writes;
 
                data_dir = READ;
-               other_dir = WRITE;
 
                goto dispatch_find_request;
        }
@@ -560,7 +553,6 @@ dispatch_writes:
                dd->starved = 0;
 
                data_dir = WRITE;
-               other_dir = READ;
 
                goto dispatch_find_request;
        }
index 47fd3659a061786967d2d150b5e9ba3212057bc9..d42840cc0d1dfcd0fad18fca25041c04ac69661a 100644 (file)
@@ -45,7 +45,7 @@ int get_blkdev_list(char *p, int used)
        struct blk_major_name *n;
        int i, len;
 
-       len = sprintf(p, "\nBlock devices:\n");
+       len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n");
 
        down(&block_subsys_sem);
        for (i = 0; i < ARRAY_SIZE(major_names); i++) {
index 3c818544475ea857d249f1afc8f259028c163a2b..b4b17958d1018aab5943caef30e0721ce99b5f78 100644 (file)
@@ -235,8 +235,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
         * set defaults
         */
        q->nr_requests = BLKDEV_MAX_RQ;
-       q->max_phys_segments = MAX_PHYS_SEGMENTS;
-       q->max_hw_segments = MAX_HW_SEGMENTS;
+       blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+       blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
        q->make_request_fn = mfn;
        q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
        q->backing_dev_info.state = 0;
index a1de06d76de63e8742558f0f20e587e1fcfa3cf6..2bc9d64db106cc40df4cf709db77405f66258c9d 100644 (file)
@@ -138,7 +138,7 @@ config CYZ_INTR
 
 config DIGIEPCA
        tristate "Digiboard Intelligent Async Support"
-       depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN)
+       depends on SERIAL_NONSTANDARD
        ---help---
          This is a driver for Digi International's Xx, Xeve, and Xem series
          of cards which provide multiple serial ports. You would need
index 184378d23f8ce1598827da50ca87041d5c21e24f..94d4eab5d3ca30e494e6cf90feab98607725d48b 100644 (file)
@@ -1,46 +1,46 @@
 /*          Definitions for DigiBoard ditty(1) command.                 */
 
 #if !defined(TIOCMODG)
-#define        TIOCMODG        ('d'<<8) | 250          /* get modem ctrl state */
-#define        TIOCMODS        ('d'<<8) | 251          /* set modem ctrl state */
+#define        TIOCMODG        (('d'<<8) | 250)        /* get modem ctrl state */
+#define        TIOCMODS        (('d'<<8) | 251)        /* set modem ctrl state */
 #endif
 
 #if !defined(TIOCMSET)
-#define        TIOCMSET        ('d'<<8) | 252          /* set modem ctrl state */
-#define        TIOCMGET        ('d'<<8) | 253          /* set modem ctrl state */
+#define        TIOCMSET        (('d'<<8) | 252)        /* set modem ctrl state */
+#define        TIOCMGET        (('d'<<8) | 253)        /* set modem ctrl state */
 #endif
 
 #if !defined(TIOCMBIC)
-#define        TIOCMBIC        ('d'<<8) | 254          /* set modem ctrl state */
-#define        TIOCMBIS        ('d'<<8) | 255          /* set modem ctrl state */
+#define        TIOCMBIC        (('d'<<8) | 254)        /* set modem ctrl state */
+#define        TIOCMBIS        (('d'<<8) | 255)        /* set modem ctrl state */
 #endif
 
 #if !defined(TIOCSDTR)
-#define        TIOCSDTR        ('e'<<8) | 0            /* set DTR              */
-#define        TIOCCDTR        ('e'<<8) | 1            /* clear DTR            */
+#define        TIOCSDTR        (('e'<<8) | 0)          /* set DTR              */
+#define        TIOCCDTR        (('e'<<8) | 1)          /* clear DTR            */
 #endif
 
 /************************************************************************
  * Ioctl command arguments for DIGI parameters.
  ************************************************************************/
-#define DIGI_GETA      ('e'<<8) | 94           /* Read params          */
+#define DIGI_GETA      (('e'<<8) | 94)         /* Read params          */
 
-#define DIGI_SETA      ('e'<<8) | 95           /* Set params           */
-#define DIGI_SETAW     ('e'<<8) | 96           /* Drain & set params   */
-#define DIGI_SETAF     ('e'<<8) | 97           /* Drain, flush & set params */
+#define DIGI_SETA      (('e'<<8) | 95)         /* Set params           */
+#define DIGI_SETAW     (('e'<<8) | 96)         /* Drain & set params   */
+#define DIGI_SETAF     (('e'<<8) | 97)         /* Drain, flush & set params */
 
-#define        DIGI_GETFLOW    ('e'<<8) | 99           /* Get startc/stopc flow */
+#define        DIGI_GETFLOW    (('e'<<8) | 99)         /* Get startc/stopc flow */
                                                /* control characters    */
-#define        DIGI_SETFLOW    ('e'<<8) | 100          /* Set startc/stopc flow */
+#define        DIGI_SETFLOW    (('e'<<8) | 100)        /* Set startc/stopc flow */
                                                /* control characters    */
-#define        DIGI_GETAFLOW   ('e'<<8) | 101          /* Get Aux. startc/stopc */
+#define        DIGI_GETAFLOW   (('e'<<8) | 101)        /* Get Aux. startc/stopc */
                                                /* flow control chars    */
-#define        DIGI_SETAFLOW   ('e'<<8) | 102          /* Set Aux. startc/stopc */
+#define        DIGI_SETAFLOW   (('e'<<8) | 102)        /* Set Aux. startc/stopc */
                                                /* flow control chars    */
 
-#define        DIGI_GETINFO    ('e'<<8) | 103          /* Fill in digi_info */
-#define        DIGI_POLLER     ('e'<<8) | 104          /* Turn on/off poller */
-#define        DIGI_INIT       ('e'<<8) | 105          /* Allow things to run. */
+#define        DIGI_GETINFO    (('e'<<8) | 103)        /* Fill in digi_info */
+#define        DIGI_POLLER     (('e'<<8) | 104)        /* Turn on/off poller */
+#define        DIGI_INIT       (('e'<<8) | 105)        /* Allow things to run. */
 
 struct digiflow_struct 
 {
index c47d7fcb840017fe9372f079e0ffec0452cd2280..3c1f1922c798a4cff9dea622efc537bbfd885b40 100644 (file)
 
 struct global_data 
 {
-       volatile ushort cin;
-       volatile ushort cout;
-       volatile ushort cstart;
-       volatile ushort cmax;
-       volatile ushort ein;
-       volatile ushort eout;
-       volatile ushort istart;
-       volatile ushort imax;
+       u16 cin;
+       u16 cout;
+       u16 cstart;
+       u16 cmax;
+       u16 ein;
+       u16 eout;
+       u16 istart;
+       u16 imax;
 };
 
 
 struct board_chan 
 {
-       int filler1; 
-       int filler2;
-       volatile ushort tseg;
-       volatile ushort tin;
-       volatile ushort tout;
-       volatile ushort tmax;
-       
-       volatile ushort rseg;
-       volatile ushort rin;
-       volatile ushort rout;
-       volatile ushort rmax;
-       
-       volatile ushort tlow;
-       volatile ushort rlow;
-       volatile ushort rhigh;
-       volatile ushort incr;
-       
-       volatile ushort etime;
-       volatile ushort edelay;
-       volatile unchar *dev;
-       
-       volatile ushort iflag;
-       volatile ushort oflag;
-       volatile ushort cflag;
-       volatile ushort gmask;
-       
-       volatile ushort col;
-       volatile ushort delay;
-       volatile ushort imask;
-       volatile ushort tflush;
-
-       int filler3;
-       int filler4;
-       int filler5;
-       int filler6;
-       
-       volatile unchar num;
-       volatile unchar ract;
-       volatile unchar bstat;
-       volatile unchar tbusy;
-       volatile unchar iempty;
-       volatile unchar ilow;
-       volatile unchar idata;
-       volatile unchar eflag;
-       
-       volatile unchar tflag;
-       volatile unchar rflag;
-       volatile unchar xmask;
-       volatile unchar xval;
-       volatile unchar mstat;
-       volatile unchar mchange;
-       volatile unchar mint;
-       volatile unchar lstat;
-
-       volatile unchar mtran;
-       volatile unchar orun;
-       volatile unchar startca;
-       volatile unchar stopca;
-       volatile unchar startc;
-       volatile unchar stopc;
-       volatile unchar vnext;
-       volatile unchar hflow;
-
-       volatile unchar fillc;
-       volatile unchar ochar;
-       volatile unchar omask;
-
-       unchar filler7;
-       unchar filler8[28];
+       u32 filler1;
+       u32 filler2;
+       u16 tseg;
+       u16 tin;
+       u16 tout;
+       u16 tmax;
+
+       u16 rseg;
+       u16 rin;
+       u16 rout;
+       u16 rmax;
+
+       u16 tlow;
+       u16 rlow;
+       u16 rhigh;
+       u16 incr;
+
+       u16 etime;
+       u16 edelay;
+       unchar *dev;
+
+       u16 iflag;
+       u16 oflag;
+       u16 cflag;
+       u16 gmask;
+
+       u16 col;
+       u16 delay;
+       u16 imask;
+       u16 tflush;
+
+       u32 filler3;
+       u32 filler4;
+       u32 filler5;
+       u32 filler6;
+
+       u8 num;
+       u8 ract;
+       u8 bstat;
+       u8 tbusy;
+       u8 iempty;
+       u8 ilow;
+       u8 idata;
+       u8 eflag;
+
+       u8 tflag;
+       u8 rflag;
+       u8 xmask;
+       u8 xval;
+       u8 mstat;
+       u8 mchange;
+       u8 mint;
+       u8 lstat;
+
+       u8 mtran;
+       u8 orun;
+       u8 startca;
+       u8 stopca;
+       u8 startc;
+       u8 stopc;
+       u8 vnext;
+       u8 hflow;
+
+       u8 fillc;
+       u8 ochar;
+       u8 omask;
+
+       u8 filler7;
+       u8 filler8[28];
 }; 
 
 
index 6025e1866c7e5e0afeb74dbd74a979b77795da5d..58d3738a2b7fd4eab9d51cd783fba8bf98ceb562 100644 (file)
@@ -6,6 +6,8 @@
        For technical support please email digiLinux@dgii.com or
        call Digi tech support at (612) 912-3456
 
+       ** This driver is no longer supported by Digi **
+
        Much of this design and code came from epca.c which was 
        copyright (C) 1994, 1995 Troy De Jongh, and subsquently 
        modified by David Nugent, Christoph Lameter, Mike McLagan. 
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif /* CONFIG_PCI */
-
-#define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2)
-#define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2)
-
-#ifdef ENABLE_PCI
+#include <linux/spinlock.h>
 #include <linux/pci.h>
 #include "digiPCI.h"
-#endif /* ENABLE_PCI */
+
 
 #include "digi1.h"
 #include "digiFep1.h"
 #include "epca.h"
 #include "epcaconfig.h"
 
-#if BITS_PER_LONG != 32
-#  error FIXME: this driver only works on 32-bit platforms
-#endif
-
 /* ---------------------- Begin defines ------------------------ */
 
-#define VERSION            "1.3.0.1-LK"
+#define VERSION            "1.3.0.1-LK2.6"
 
 /* This major needs to be submitted to Linux to join the majors list */
 
 
 /* ----------------- Begin global definitions ------------------- */
 
-static char mesg[100];
 static int nbdevs, num_cards, liloconfig;
 static int digi_poller_inhibited = 1 ;
 
 static int setup_error_code;
 static int invalid_lilo_config;
 
+/* The ISA boards do window flipping into the same spaces so its only sane
+   with a single lock. It's still pretty efficient */
+
+static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED;
+
 /* -----------------------------------------------------------------------
        MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 
        7 below.
@@ -129,58 +123,58 @@ static struct timer_list epca_timer;
        configured.
 ----------------------------------------------------------------------- */
        
-static inline void memwinon(struct board_info *b, unsigned int win);
-static inline void memwinoff(struct board_info *b, unsigned int win);
-static inline void globalwinon(struct channel *ch);
-static inline void rxwinon(struct channel *ch);
-static inline void txwinon(struct channel *ch);
-static inline void memoff(struct channel *ch);
-static inline void assertgwinon(struct channel *ch);
-static inline void assertmemoff(struct channel *ch);
+static void memwinon(struct board_info *b, unsigned int win);
+static void memwinoff(struct board_info *b, unsigned int win);
+static void globalwinon(struct channel *ch);
+static void rxwinon(struct channel *ch);
+static void txwinon(struct channel *ch);
+static void memoff(struct channel *ch);
+static void assertgwinon(struct channel *ch);
+static void assertmemoff(struct channel *ch);
 
 /* ---- Begin more 'specific' memory functions for cx_like products --- */
 
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxem_globalwinon(struct channel *ch);
-static inline void pcxem_rxwinon(struct channel *ch);
-static inline void pcxem_txwinon(struct channel *ch);
-static inline void pcxem_memoff(struct channel *ch);
+static void pcxem_memwinon(struct board_info *b, unsigned int win);
+static void pcxem_memwinoff(struct board_info *b, unsigned int win);
+static void pcxem_globalwinon(struct channel *ch);
+static void pcxem_rxwinon(struct channel *ch);
+static void pcxem_txwinon(struct channel *ch);
+static void pcxem_memoff(struct channel *ch);
 
 /* ------ Begin more 'specific' memory functions for the pcxe ------- */
 
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxe_globalwinon(struct channel *ch);
-static inline void pcxe_rxwinon(struct channel *ch);
-static inline void pcxe_txwinon(struct channel *ch);
-static inline void pcxe_memoff(struct channel *ch);
+static void pcxe_memwinon(struct board_info *b, unsigned int win);
+static void pcxe_memwinoff(struct board_info *b, unsigned int win);
+static void pcxe_globalwinon(struct channel *ch);
+static void pcxe_rxwinon(struct channel *ch);
+static void pcxe_txwinon(struct channel *ch);
+static void pcxe_memoff(struct channel *ch);
 
 /* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
 /* Note : pc64xe and pcxi share the same windowing routines */
 
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxi_globalwinon(struct channel *ch);
-static inline void pcxi_rxwinon(struct channel *ch);
-static inline void pcxi_txwinon(struct channel *ch);
-static inline void pcxi_memoff(struct channel *ch);
+static void pcxi_memwinon(struct board_info *b, unsigned int win);
+static void pcxi_memwinoff(struct board_info *b, unsigned int win);
+static void pcxi_globalwinon(struct channel *ch);
+static void pcxi_rxwinon(struct channel *ch);
+static void pcxi_txwinon(struct channel *ch);
+static void pcxi_memoff(struct channel *ch);
 
 /* - Begin 'specific' do nothing memory functions needed for some cards - */
 
-static inline void dummy_memwinon(struct board_info *b, unsigned int win);
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win);
-static inline void dummy_globalwinon(struct channel *ch);
-static inline void dummy_rxwinon(struct channel *ch);
-static inline void dummy_txwinon(struct channel *ch);
-static inline void dummy_memoff(struct channel *ch);
-static inline void dummy_assertgwinon(struct channel *ch);
-static inline void dummy_assertmemoff(struct channel *ch);
+static void dummy_memwinon(struct board_info *b, unsigned int win);
+static void dummy_memwinoff(struct board_info *b, unsigned int win);
+static void dummy_globalwinon(struct channel *ch);
+static void dummy_rxwinon(struct channel *ch);
+static void dummy_txwinon(struct channel *ch);
+static void dummy_memoff(struct channel *ch);
+static void dummy_assertgwinon(struct channel *ch);
+static void dummy_assertmemoff(struct channel *ch);
 
 /* ------------------- Begin declare functions ----------------------- */
 
-static inline struct channel *verifyChannel(register struct tty_struct *);
-static inline void pc_sched_event(struct channel *, int);
+static struct channel *verifyChannel(struct tty_struct *);
+static void pc_sched_event(struct channel *, int);
 static void epca_error(int, char *);
 static void pc_close(struct tty_struct *, struct file *);
 static void shutdown(struct channel *);
@@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty);
 static void digi_send_break(struct channel *ch, int msec);
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
 void epca_setup(char *, int *);
-void console_print(const char *);
 
 static int get_termio(struct tty_struct *, struct termio __user *);
 static int pc_write(struct tty_struct *, const unsigned char *, int);
-int pc_init(void);
-
-#ifdef ENABLE_PCI
+static int pc_init(void);
 static int init_PCI(void);
-#endif /* ENABLE_PCI */
 
 
 /* ------------------------------------------------------------------
@@ -237,41 +227,41 @@ static int init_PCI(void);
        making direct calls deserves what they get.
 -------------------------------------------------------------------- */
 
-static inline void memwinon(struct board_info *b, unsigned int win)
+static void memwinon(struct board_info *b, unsigned int win)
 {
        (b->memwinon)(b, win);
 }
 
-static inline void memwinoff(struct board_info *b, unsigned int win)
+static void memwinoff(struct board_info *b, unsigned int win)
 {
        (b->memwinoff)(b, win);
 }
 
-static inline void globalwinon(struct channel *ch)
+static void globalwinon(struct channel *ch)
 {
        (ch->board->globalwinon)(ch);
 }
 
-static inline void rxwinon(struct channel *ch)
+static void rxwinon(struct channel *ch)
 {
        (ch->board->rxwinon)(ch);
 }
 
-static inline void txwinon(struct channel *ch)
+static void txwinon(struct channel *ch)
 {
        (ch->board->txwinon)(ch);
 }
 
-static inline void memoff(struct channel *ch)
+static void memoff(struct channel *ch)
 {
        (ch->board->memoff)(ch);
 }
-static inline void assertgwinon(struct channel *ch)
+static void assertgwinon(struct channel *ch)
 {
        (ch->board->assertgwinon)(ch);
 }
 
-static inline void assertmemoff(struct channel *ch)
+static void assertmemoff(struct channel *ch)
 {
        (ch->board->assertmemoff)(ch);
 }
@@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch)
        and CX series cards.
 ------------------------------------------------------------ */
 
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win)
+static void pcxem_memwinon(struct board_info *b, unsigned int win)
 {
-        outb_p(FEPWIN|win, (int)b->port + 1);
+        outb_p(FEPWIN|win, b->port + 1);
 }
 
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win)
+static void pcxem_memwinoff(struct board_info *b, unsigned int win)
 {
-       outb_p(0, (int)b->port + 1);
+       outb_p(0, b->port + 1);
 }
 
-static inline void pcxem_globalwinon(struct channel *ch)
+static void pcxem_globalwinon(struct channel *ch)
 {
        outb_p( FEPWIN, (int)ch->board->port + 1);
 }
 
-static inline void pcxem_rxwinon(struct channel *ch)
+static void pcxem_rxwinon(struct channel *ch)
 {
        outb_p(ch->rxwin, (int)ch->board->port + 1);
 }
 
-static inline void pcxem_txwinon(struct channel *ch)
+static void pcxem_txwinon(struct channel *ch)
 {
        outb_p(ch->txwin, (int)ch->board->port + 1);
 }
 
-static inline void pcxem_memoff(struct channel *ch)
+static void pcxem_memoff(struct channel *ch)
 {
        outb_p(0, (int)ch->board->port + 1);
 }
 
 /* ----------------- Begin pcxe memory window stuff ------------------ */
 
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win)
+static void pcxe_memwinon(struct board_info *b, unsigned int win)
 {
-               outb_p(FEPWIN | win, (int)b->port + 1);
+               outb_p(FEPWIN | win, b->port + 1);
 }
 
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win)
+static void pcxe_memwinoff(struct board_info *b, unsigned int win)
 {
-       outb_p(inb((int)b->port) & ~FEPMEM,
-                  (int)b->port + 1);
-       outb_p(0, (int)b->port + 1);
+       outb_p(inb(b->port) & ~FEPMEM,
+                  b->port + 1);
+       outb_p(0, b->port + 1);
 }
 
-static inline void pcxe_globalwinon(struct channel *ch)
+static void pcxe_globalwinon(struct channel *ch)
 {
        outb_p( FEPWIN, (int)ch->board->port + 1);
 }
 
-static inline void pcxe_rxwinon(struct channel *ch)
+static void pcxe_rxwinon(struct channel *ch)
 {
                outb_p(ch->rxwin, (int)ch->board->port + 1);
 }
 
-static inline void pcxe_txwinon(struct channel *ch)
+static void pcxe_txwinon(struct channel *ch)
 {
                outb_p(ch->txwin, (int)ch->board->port + 1);
 }
 
-static inline void pcxe_memoff(struct channel *ch)
+static void pcxe_memoff(struct channel *ch)
 {
        outb_p(0, (int)ch->board->port);
        outb_p(0, (int)ch->board->port + 1);
@@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch)
 
 /* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
 
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win)
+static void pcxi_memwinon(struct board_info *b, unsigned int win)
 {
-               outb_p(inb((int)b->port) | FEPMEM, (int)b->port);
+               outb_p(inb(b->port) | FEPMEM, b->port);
 }
 
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win)
+static void pcxi_memwinoff(struct board_info *b, unsigned int win)
 {
-       outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port);
+       outb_p(inb(b->port) & ~FEPMEM, b->port);
 }
 
-static inline void pcxi_globalwinon(struct channel *ch)
+static void pcxi_globalwinon(struct channel *ch)
 {
-       outb_p(FEPMEM, (int)ch->board->port);
+       outb_p(FEPMEM, ch->board->port);
 }
 
-static inline void pcxi_rxwinon(struct channel *ch)
+static void pcxi_rxwinon(struct channel *ch)
 {
-               outb_p(FEPMEM, (int)ch->board->port);
+               outb_p(FEPMEM, ch->board->port);
 }
 
-static inline void pcxi_txwinon(struct channel *ch)
+static void pcxi_txwinon(struct channel *ch)
 {
-               outb_p(FEPMEM, (int)ch->board->port);
+               outb_p(FEPMEM, ch->board->port);
 }
 
-static inline void pcxi_memoff(struct channel *ch)
+static void pcxi_memoff(struct channel *ch)
 {
-       outb_p(0, (int)ch->board->port);
+       outb_p(0, ch->board->port);
 }
 
-static inline void pcxi_assertgwinon(struct channel *ch)
+static void pcxi_assertgwinon(struct channel *ch)
 {
-       epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off");
+       epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
 }
 
-static inline void pcxi_assertmemoff(struct channel *ch)
+static void pcxi_assertmemoff(struct channel *ch)
 {
-       epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on");
+       epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
 }
 
 
@@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch)
        may or may not do anything.
 ---------------------------------------------------------------------------*/
 
-static inline void dummy_memwinon(struct board_info *b, unsigned int win)
+static void dummy_memwinon(struct board_info *b, unsigned int win)
 {
 }
 
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win)
+static void dummy_memwinoff(struct board_info *b, unsigned int win)
 {
 }
 
-static inline void dummy_globalwinon(struct channel *ch)
+static void dummy_globalwinon(struct channel *ch)
 {
 }
 
-static inline void dummy_rxwinon(struct channel *ch)
+static void dummy_rxwinon(struct channel *ch)
 {
 }
 
-static inline void dummy_txwinon(struct channel *ch)
+static void dummy_txwinon(struct channel *ch)
 {
 }
 
-static inline void dummy_memoff(struct channel *ch)
+static void dummy_memoff(struct channel *ch)
 {
 }
 
-static inline void dummy_assertgwinon(struct channel *ch)
+static void dummy_assertgwinon(struct channel *ch)
 {
 }
 
-static inline void dummy_assertmemoff(struct channel *ch)
+static void dummy_assertmemoff(struct channel *ch)
 {
 }
 
 /* ----------------- Begin verifyChannel function ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *tty)
+static struct channel *verifyChannel(struct tty_struct *tty)
 { /* Begin verifyChannel */
-
        /* --------------------------------------------------------------------
                This routine basically provides a sanity check.  It insures that
                the channel returned is within the proper range of addresses as
                well as properly initialized.  If some bogus info gets passed in
                through tty->driver_data this should catch it.
-       --------------------------------------------------------------------- */
-
-       if (tty) 
-       { /* Begin if tty */
-
-               register struct channel *ch = (struct channel *)tty->driver_data;
-
-               if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) 
-               {
+               --------------------------------------------------------------------- */
+       if (tty) {
+               struct channel *ch = (struct channel *)tty->driver_data;
+               if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
                        if (ch->magic == EPCA_MAGIC)
                                return ch;
                }
-
-       } /* End if tty */
-
-       /* Else return a NULL for invalid */
+       }
        return NULL;
 
 } /* End verifyChannel */
 
 /* ------------------ Begin pc_sched_event ------------------------- */
 
-static inline void pc_sched_event(struct channel *ch, int event)
-{ /* Begin pc_sched_event */
-
-
+static void pc_sched_event(struct channel *ch, int event)
+{
        /* ----------------------------------------------------------------------
                We call this to schedule interrupt processing on some event.  The 
                kernel sees our request and calls the related routine in OUR driver.
        -------------------------------------------------------------------------*/
-
        ch->event |= 1 << event;
        schedule_work(&ch->tqueue);
-
-
 } /* End pc_sched_event */
 
 /* ------------------ Begin epca_error ------------------------- */
 
 static void epca_error(int line, char *msg)
-{ /* Begin epca_error */
-
+{
        printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
-       return;
-
-} /* End epca_error */
+}
 
 /* ------------------ Begin pc_close ------------------------- */
 static void pc_close(struct tty_struct * tty, struct file * filp)
-{ /* Begin pc_close */
-
+{
        struct channel *ch;
        unsigned long flags;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if ch != NULL */
-
-               save_flags(flags);
-               cli();
-
-               if (tty_hung_up_p(filp)) 
-               {
-                       restore_flags(flags);
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if ch != NULL */
+               spin_lock_irqsave(&epca_lock, flags);
+               if (tty_hung_up_p(filp)) {
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        return;
                }
-
                /* Check to see if the channel is open more than once */
-               if (ch->count-- > 1) 
-               { /* Begin channel is open more than once */
-
+               if (ch->count-- > 1)  {
+                       /* Begin channel is open more than once */
                        /* -------------------------------------------------------------
                                Return without doing anything.  Someone might still be using
                                the channel.
                        ---------------------------------------------------------------- */
-
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        return;
                } /* End channel is open more than once */
 
                /* Port open only once go ahead with shutdown & reset */
-
-               if (ch->count < 0) 
-               {
-                       ch->count = 0;
-               }
+               if (ch->count < 0)
+                       BUG();
 
                /* ---------------------------------------------------------------
                        Let the rest of the driver know the channel is being closed.
                        This becomes important if an open is attempted before close 
                        is finished.
                ------------------------------------------------------------------ */
-
                ch->asyncflags |= ASYNC_CLOSING;
-       
                tty->closing = 1;
 
-               if (ch->asyncflags & ASYNC_INITIALIZED) 
-               {
+               spin_unlock_irqrestore(&epca_lock, flags);
+
+               if (ch->asyncflags & ASYNC_INITIALIZED)  {
                        /* Setup an event to indicate when the transmit buffer empties */
                        setup_empty_event(tty, ch);             
                        tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
                }
-       
                if (tty->driver->flush_buffer)
                        tty->driver->flush_buffer(tty);
 
                tty_ldisc_flush(tty);
                shutdown(ch);
+
+               spin_lock_irqsave(&epca_lock, flags);
                tty->closing = 0;
                ch->event = 0;
                ch->tty = NULL;
+               spin_unlock_irqrestore(&epca_lock, flags);
 
-               if (ch->blocked_open) 
-               { /* Begin if blocked_open */
-
+               if (ch->blocked_open)  { /* Begin if blocked_open */
                        if (ch->close_delay) 
-                       {
                                msleep_interruptible(jiffies_to_msecs(ch->close_delay));
-                       }
-
                        wake_up_interruptible(&ch->open_wait);
-
                } /* End if blocked_open */
-
                ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | 
                                      ASYNC_CLOSING);
                wake_up_interruptible(&ch->close_wait);
-
-
-               restore_flags(flags);
-
        } /* End if ch != NULL */
-
 } /* End pc_close */ 
 
 /* ------------------ Begin shutdown  ------------------------- */
@@ -586,15 +534,14 @@ static void shutdown(struct channel *ch)
 
        unsigned long flags;
        struct tty_struct *tty;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
 
        if (!(ch->asyncflags & ASYNC_INITIALIZED)) 
                return;
 
-       save_flags(flags);
-       cli();
-       globalwinon(ch);
+       spin_lock_irqsave(&epca_lock, flags);
 
+       globalwinon(ch);
        bc = ch->brdchan;
 
        /* ------------------------------------------------------------------
@@ -604,20 +551,17 @@ static void shutdown(struct channel *ch)
        --------------------------------------------------------------------- */ 
 
        if (bc)
-               bc->idata = 0;
-
+               writeb(0, &bc->idata);
        tty = ch->tty;
 
        /* ----------------------------------------------------------------
           If we're a modem control device and HUPCL is on, drop RTS & DTR.
        ------------------------------------------------------------------ */
 
-       if (tty->termios->c_cflag & HUPCL) 
-       {
+       if (tty->termios->c_cflag & HUPCL)  {
                ch->omodem &= ~(ch->m_rts | ch->m_dtr);
                fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
        }
-
        memoff(ch);
 
        /* ------------------------------------------------------------------
@@ -628,7 +572,7 @@ static void shutdown(struct channel *ch)
        /* Prevent future Digi programmed interrupts from coming active */
 
        ch->asyncflags &= ~ASYNC_INITIALIZED;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&epca_lock, flags);
 
 } /* End shutdown */
 
@@ -636,7 +580,6 @@ static void shutdown(struct channel *ch)
 
 static void pc_hangup(struct tty_struct *tty)
 { /* Begin pc_hangup */
-
        struct channel *ch;
        
        /* ---------------------------------------------------------
@@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty)
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
 
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if ch != NULL */
-
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if ch != NULL */
                unsigned long flags;
 
-               save_flags(flags);
-               cli();
                if (tty->driver->flush_buffer)
                        tty->driver->flush_buffer(tty);
                tty_ldisc_flush(tty);
                shutdown(ch);
 
+               spin_lock_irqsave(&epca_lock, flags);
                ch->tty   = NULL;
                ch->event = 0;
                ch->count = 0;
-               restore_flags(flags);
                ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
+               spin_unlock_irqrestore(&epca_lock, flags);
                wake_up_interruptible(&ch->open_wait);
-
        } /* End if ch != NULL */
 
 } /* End pc_hangup */
@@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty)
 static int pc_write(struct tty_struct * tty,
                     const unsigned char *buf, int bytesAvailable)
 { /* Begin pc_write */
-
-       register unsigned int head, tail;
-       register int dataLen;
-       register int size;
-       register int amountCopied;
-
-
+       unsigned int head, tail;
+       int dataLen;
+       int size;
+       int amountCopied;
        struct channel *ch;
        unsigned long flags;
        int remain;
-       volatile struct board_chan *bc;
-
+       struct board_chan *bc;
 
        /* ----------------------------------------------------------------
                pc_write is primarily called directly by the kernel routine
@@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty,
 
        bc   = ch->brdchan;
        size = ch->txbufsize;
-
        amountCopied = 0;
-       save_flags(flags);
-       cli();
 
+       spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
 
-       head = bc->tin & (size - 1);
-       tail = bc->tout;
+       head = readw(&bc->tin) & (size - 1);
+       tail = readw(&bc->tout);
 
-       if (tail != bc->tout)
-               tail = bc->tout;
+       if (tail != readw(&bc->tout))
+               tail = readw(&bc->tout);
        tail &= (size - 1);
 
        /*      If head >= tail, head has not wrapped around. */ 
-       if (head >= tail) 
-       { /* Begin head has not wrapped */
-
+       if (head >= tail)  { /* Begin head has not wrapped */
                /* ---------------------------------------------------------------
                        remain (much like dataLen above) represents the total amount of
                        space available on the card for data.  Here dataLen represents
@@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty,
                        buffer.  This is important because a memcpy cannot be told to
                        automatically wrap around when it hits the buffer end.
                ------------------------------------------------------------------ */ 
-
                dataLen = size - head;
                remain = size - (head - tail) - 1;
-
-       } /* End head has not wrapped */
-       else 
-       { /* Begin head has wrapped around */
+       } else { /* Begin head has wrapped around */
 
                remain = tail - head - 1;
                dataLen = remain;
 
        } /* End head has wrapped around */
-
        /* -------------------------------------------------------------------
                        Check the space on the card.  If we have more data than 
                        space; reduce the amount of data to fit the space.
        ---------------------------------------------------------------------- */
-
        bytesAvailable = min(remain, bytesAvailable);
-
        txwinon(ch);
        while (bytesAvailable > 0) 
        { /* Begin while there is data to copy onto card */
@@ -767,26 +691,21 @@ static int pc_write(struct tty_struct * tty,
                amountCopied += dataLen;
                bytesAvailable -= dataLen;
 
-               if (head >= size) 
-               {
+               if (head >= size) {
                        head = 0;
                        dataLen = tail;
                }
-
        } /* End while there is data to copy onto card */
-
        ch->statusflags |= TXBUSY;
        globalwinon(ch);
-       bc->tin = head;
+       writew(head, &bc->tin);
 
-       if ((ch->statusflags & LOWWAIT) == 0) 
-       {
+       if ((ch->statusflags & LOWWAIT) == 0)  {
                ch->statusflags |= LOWWAIT;
-               bc->ilow = 1;
+               writeb(1, &bc->ilow);
        }
        memoff(ch);
-       restore_flags(flags);
-
+       spin_unlock_irqrestore(&epca_lock, flags);
        return(amountCopied);
 
 } /* End pc_write */
@@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty,
 
 static void pc_put_char(struct tty_struct *tty, unsigned char c)
 { /* Begin pc_put_char */
-
-   
        pc_write(tty, &c, 1);
-       return;
-
 } /* End pc_put_char */
 
 /* ------------------ Begin pc_write_room  ------------------------- */
@@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
        struct channel *ch;
        unsigned long flags;
        unsigned int head, tail;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
 
        remain = 0;
 
@@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty)
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
 
-       if ((ch = verifyChannel(tty)) != NULL) 
-       {
-               save_flags(flags);
-               cli();
+       if ((ch = verifyChannel(tty)) != NULL)  {
+               spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
 
                bc   = ch->brdchan;
-               head = bc->tin & (ch->txbufsize - 1);
-               tail = bc->tout;
+               head = readw(&bc->tin) & (ch->txbufsize - 1);
+               tail = readw(&bc->tout);
 
-               if (tail != bc->tout)
-                       tail = bc->tout;
+               if (tail != readw(&bc->tout))
+                       tail = readw(&bc->tout);
                /* Wrap tail if necessary */
                tail &= (ch->txbufsize - 1);
 
                if ((remain = tail - head - 1) < 0 )
                        remain += ch->txbufsize;
 
-               if (remain && (ch->statusflags & LOWWAIT) == 0) 
-               {
+               if (remain && (ch->statusflags & LOWWAIT) == 0) {
                        ch->statusflags |= LOWWAIT;
-                       bc->ilow = 1;
+                       writeb(1, &bc->ilow);
                }
                memoff(ch);
-               restore_flags(flags);
+               spin_unlock_irqrestore(&epca_lock, flags);
        }
-
        /* Return how much room is left on card */
        return remain;
 
@@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        int remain;
        unsigned long flags;
        struct channel *ch;
-       volatile struct board_chan *bc;
-
+       struct board_chan *bc;
 
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
@@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        if ((ch = verifyChannel(tty)) == NULL)
                return(0);
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
 
        bc = ch->brdchan;
-       tail = bc->tout;
-       head = bc->tin;
-       ctail = ch->mailbox->cout;
+       tail = readw(&bc->tout);
+       head = readw(&bc->tin);
+       ctail = readw(&ch->mailbox->cout);
 
-       if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
+       if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
                chars = 0;
-       else 
-       { /* Begin if some space on the card has been used */
-
-               head = bc->tin & (ch->txbufsize - 1);
+       else  { /* Begin if some space on the card has been used */
+               head = readw(&bc->tin) & (ch->txbufsize - 1);
                tail &= (ch->txbufsize - 1);
-
                /*  --------------------------------------------------------------
                        The logic here is basically opposite of the above pc_write_room
                        here we are finding the amount of bytes in the buffer filled.
                        Not the amount of bytes empty.
                ------------------------------------------------------------------- */
-
                if ((remain = tail - head - 1) < 0 )
                        remain += ch->txbufsize;
-
                chars = (int)(ch->txbufsize - remain);
-
                /* -------------------------------------------------------------  
                        Make it possible to wakeup anything waiting for output
                        in tty_ioctl.c, etc.
@@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
                        If not already set.  Setup an event to indicate when the
                        transmit buffer empties 
                ----------------------------------------------------------------- */
-
                if (!(ch->statusflags & EMPTYWAIT))
                        setup_empty_event(tty,ch);
 
        } /* End if some space on the card has been used */
-
        memoff(ch);
-       restore_flags(flags);
-
+       spin_unlock_irqrestore(&epca_lock, flags);
        /* Return number of characters residing on card. */
        return(chars);
 
@@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty)
        unsigned int tail;
        unsigned long flags;
        struct channel *ch;
-       volatile struct board_chan *bc;
-
-
+       struct board_chan *bc;
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
        if ((ch = verifyChannel(tty)) == NULL)
                return;
 
-       save_flags(flags);
-       cli();
-
+       spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
-
        bc   = ch->brdchan;
-       tail = bc->tout;
-
+       tail = readw(&bc->tout);
        /* Have FEP move tout pointer; effectively flushing transmit buffer */
-
        fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-
        memoff(ch);
-       restore_flags(flags);
-
+       spin_unlock_irqrestore(&epca_lock, flags);
        wake_up_interruptible(&tty->write_wait);
        tty_wakeup(tty);
-
 } /* End pc_flush_buffer */
 
 /* ------------------ Begin pc_flush_chars  ---------------------- */
 
 static void pc_flush_chars(struct tty_struct *tty)
 { /* Begin pc_flush_chars */
-
        struct channel * ch;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       {
+       if ((ch = verifyChannel(tty)) != NULL) {
                unsigned long flags;
-
-               save_flags(flags);
-               cli();
-
+               spin_lock_irqsave(&epca_lock, flags);
                /* ----------------------------------------------------------------
                        If not already set and the transmitter is busy setup an event
                        to indicate when the transmit empties.
                ------------------------------------------------------------------- */
-
                if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
                        setup_empty_event(tty,ch);
-
-               restore_flags(flags);
+               spin_unlock_irqrestore(&epca_lock, flags);
        }
-
 } /* End pc_flush_chars */
 
 /* ------------------ Begin block_til_ready  ---------------------- */
@@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty)
 static int block_til_ready(struct tty_struct *tty, 
                            struct file *filp, struct channel *ch)
 { /* Begin block_til_ready */
-
        DECLARE_WAITQUEUE(wait,current);
        int     retval, do_clocal = 0;
        unsigned long flags;
 
-
-       if (tty_hung_up_p(filp))
-       {
+       if (tty_hung_up_p(filp)) {
                if (ch->asyncflags & ASYNC_HUP_NOTIFY)
                        retval = -EAGAIN;
                else
@@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty,
                If the device is in the middle of being closed, then block
                until it's done, and then try again.
        -------------------------------------------------------------------- */
-       if (ch->asyncflags & ASYNC_CLOSING) 
-       {
+       if (ch->asyncflags & ASYNC_CLOSING) {
                interruptible_sleep_on(&ch->close_wait);
 
                if (ch->asyncflags & ASYNC_HUP_NOTIFY)
@@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty,
                        return -ERESTARTSYS;
        }
 
-       if (filp->f_flags & O_NONBLOCK) 
-       {
+       if (filp->f_flags & O_NONBLOCK)  {
                /* ----------------------------------------------------------------- 
                 If non-blocking mode is set, then make the check up front
                 and then exit.
                -------------------------------------------------------------------- */
-
                ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
                return 0;
        }
-
-
        if (tty->termios->c_cflag & CLOCAL)
                do_clocal = 1;
-       
-   /* Block waiting for the carrier detect and the line to become free */
+       /* Block waiting for the carrier detect and the line to become free */
        
        retval = 0;
        add_wait_queue(&ch->open_wait, &wait);
-       save_flags(flags);
-       cli();
-
 
+       spin_lock_irqsave(&epca_lock, flags);
        /* We dec count so that pc_close will know when to free things */
        if (!tty_hung_up_p(filp))
                ch->count--;
-
-       restore_flags(flags);
-
        ch->blocked_open++;
-
        while(1) 
        { /* Begin forever while  */
-
                set_current_state(TASK_INTERRUPTIBLE);
-
                if (tty_hung_up_p(filp) ||
                    !(ch->asyncflags & ASYNC_INITIALIZED)) 
                {
@@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty,
                                retval = -ERESTARTSYS;  
                        break;
                }
-
                if (!(ch->asyncflags & ASYNC_CLOSING) && 
                          (do_clocal || (ch->imodem & ch->dcd)))
                        break;
-
-               if (signal_pending(current)) 
-               {
+               if (signal_pending(current)) {
                        retval = -ERESTARTSYS;
                        break;
                }
-
+               spin_unlock_irqrestore(&epca_lock, flags);
                /* ---------------------------------------------------------------
                        Allow someone else to be scheduled.  We will occasionally go
                        through this loop until one of the above conditions change.
@@ -1091,25 +949,23 @@ static int block_til_ready(struct tty_struct *tty,
                        prevent this loop from hogging the cpu.
                ------------------------------------------------------------------ */
                schedule();
+               spin_lock_irqsave(&epca_lock, flags);
 
        } /* End forever while  */
 
        current->state = TASK_RUNNING;
        remove_wait_queue(&ch->open_wait, &wait);
-       cli();
        if (!tty_hung_up_p(filp))
                ch->count++;
-       restore_flags(flags);
-
        ch->blocked_open--;
 
+       spin_unlock_irqrestore(&epca_lock, flags);
+
        if (retval)
                return retval;
 
        ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
        return 0;
-
 } /* End block_til_ready */    
 
 /* ------------------ Begin pc_open  ---------------------- */
@@ -1120,17 +976,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
        struct channel *ch;
        unsigned long flags;
        int line, retval, boardnum;
-       volatile struct board_chan *bc;
-       volatile unsigned int head;
+       struct board_chan *bc;
+       unsigned int head;
 
        line = tty->index;
-       if (line < 0 || line >= nbdevs) 
-       {
-               printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n");
-               tty->driver_data = NULL;
-               return(-ENODEV);
-       }
-
+       if (line < 0 || line >= nbdevs)
+               return -ENODEV;
 
        ch = &digi_channels[line];
        boardnum = ch->boardnum;
@@ -1143,66 +994,49 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
                goes here.
        ---------------------------------------------------------------------- */
 
-       if (invalid_lilo_config)
-       {
+       if (invalid_lilo_config) {
                if (setup_error_code & INVALID_BOARD_TYPE)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid board type specified in LILO command\n");
-
+                       printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
                if (setup_error_code & INVALID_NUM_PORTS)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid number of ports specified in LILO command\n");
-
+                       printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
                if (setup_error_code & INVALID_MEM_BASE)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid board memory address specified in LILO command\n");
-
+                       printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
                if (setup_error_code & INVALID_PORT_BASE)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid board port address specified in LILO command\n");
-
+                       printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
                if (setup_error_code & INVALID_BOARD_STATUS)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid board status specified in LILO command\n");
-
+                       printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
                if (setup_error_code & INVALID_ALTPIN)
-                       printk(KERN_ERR "<Error> - pc_open: Invalid board altpin specified in LILO command\n");
-
+                       printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
                tty->driver_data = NULL;   /* Mark this device as 'down' */
-               return(-ENODEV);
+               return -ENODEV;
        }
-
-       if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED)) 
-       {
+       if (boardnum >= num_cards || boards[boardnum].status == DISABLED)  {
                tty->driver_data = NULL;   /* Mark this device as 'down' */
                return(-ENODEV);
        }
        
-       if (( bc = ch->brdchan) == 0) 
-       {
+       if ((bc = ch->brdchan) == 0) {
                tty->driver_data = NULL;
-               return(-ENODEV);
+               return -ENODEV;
        }
 
+       spin_lock_irqsave(&epca_lock, flags);
        /* ------------------------------------------------------------------
                Every time a channel is opened, increment a counter.  This is 
                necessary because we do not wish to flush and shutdown the channel
                until the last app holding the channel open, closes it.         
        --------------------------------------------------------------------- */
-
        ch->count++;
-
        /* ----------------------------------------------------------------
                Set a kernel structures pointer to our local channel 
                structure.  This way we can get to it when passed only
                a tty struct.
        ------------------------------------------------------------------ */
-
        tty->driver_data = ch;
-       
        /* ----------------------------------------------------------------
                If this is the first time the channel has been opened, initialize
                the tty->termios struct otherwise let pc_close handle it.
        -------------------------------------------------------------------- */
-
-       save_flags(flags);
-       cli();
-
        globalwinon(ch);
        ch->statusflags = 0;
 
@@ -1213,8 +1047,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
           Set receive head and tail ptrs to each other.  This indicates
           no data available to read.
        ----------------------------------------------------------------- */
-       head = bc->rin;
-       bc->rout = head;
+       head = readw(&bc->rin);
+       writew(head, &bc->rout);
 
        /* Set the channels associated tty structure */
        ch->tty = tty;
@@ -1224,122 +1058,74 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
                issues, etc.... It effect both control flags and input flags.
        -------------------------------------------------------------------- */
        epcaparam(tty,ch);
-
        ch->asyncflags |= ASYNC_INITIALIZED;
        memoff(ch);
-
-       restore_flags(flags);
+       spin_unlock_irqrestore(&epca_lock, flags);
 
        retval = block_til_ready(tty, filp, ch);
        if (retval)
-       {
                return retval;
-       }
-
        /* -------------------------------------------------------------
                Set this again in case a hangup set it to zero while this 
                open() was waiting for the line...
        --------------------------------------------------------------- */
+       spin_lock_irqsave(&epca_lock, flags);
        ch->tty = tty;
-
-       save_flags(flags);
-       cli();
        globalwinon(ch);
-
        /* Enable Digi Data events */
-       bc->idata = 1;
-
+       writeb(1, &bc->idata);
        memoff(ch);
-       restore_flags(flags);
-
+       spin_unlock_irqrestore(&epca_lock, flags);
        return 0;
-
 } /* End pc_open */
 
-#ifdef MODULE
 static int __init epca_module_init(void)
 { /* Begin init_module */
-
-       unsigned long   flags;
-
-       save_flags(flags);
-       cli();
-
-       pc_init();
-
-       restore_flags(flags);
-
-       return(0);
+       return pc_init();
 }
 
 module_init(epca_module_init);
-#endif
 
-#ifdef ENABLE_PCI
 static struct pci_driver epca_driver;
-#endif
-
-#ifdef MODULE
-/* -------------------- Begin cleanup_module  ---------------------- */
 
 static void __exit epca_module_exit(void)
 {
-
        int               count, crd;
        struct board_info *bd;
        struct channel    *ch;
-       unsigned long     flags;
 
        del_timer_sync(&epca_timer);
 
-       save_flags(flags);
-       cli();
-
        if ((tty_unregister_driver(pc_driver)) ||  
            (tty_unregister_driver(pc_info)))
        {
-               printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
-               restore_flags(flags);
+               printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
                return;
        }
        put_tty_driver(pc_driver);
        put_tty_driver(pc_info);
 
-       for (crd = 0; crd < num_cards; crd++) 
-       { /* Begin for each card */
-
+       for (crd = 0; crd < num_cards; crd++)  { /* Begin for each card */
                bd = &boards[crd];
-
                if (!bd)
                { /* Begin sanity check */
                        printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
                        return;
                } /* End sanity check */
-
-               ch = card_ptr[crd]; 
-
+               ch = card_ptr[crd];
                for (count = 0; count < bd->numports; count++, ch++) 
                { /* Begin for each port */
-
-                       if (ch) 
-                       {
+                       if (ch) {
                                if (ch->tty)
                                        tty_hangup(ch->tty);
                                kfree(ch->tmp_buf);
                        }
-
                } /* End for each port */
        } /* End for each card */
-
-#ifdef ENABLE_PCI
        pci_unregister_driver (&epca_driver);
-#endif
-
-       restore_flags(flags);
-
 }
+
 module_exit(epca_module_exit);
-#endif /* MODULE */
 
 static struct tty_operations pc_ops = {
        .open = pc_open,
@@ -1371,34 +1157,15 @@ static struct tty_operations info_ops = {
 
 /* ------------------ Begin pc_init  ---------------------- */
 
-int __init pc_init(void)
+static int __init pc_init(void)
 { /* Begin pc_init */
-
-       /* ----------------------------------------------------------------
-               pc_init is called by the operating system during boot up prior to
-               any open calls being made.  In the older versions of Linux (Prior
-               to 2.0.0) an entry is made into tty_io.c.  A pointer to the last
-               memory location (from kernel space) used (kmem_start) is passed
-               to pc_init.  It is pc_inits responsibility to modify this value 
-               for any memory that the Digi driver might need and then return
-               this value to the operating system.  For example if the driver
-               wishes to allocate 1K of kernel memory, pc_init would return 
-               (kmem_start + 1024).  This memory (Between kmem_start and kmem_start
-               + 1024) would then be available for use exclusively by the driver.  
-               In this case our driver does not allocate any of this kernel 
-               memory.
-       ------------------------------------------------------------------*/
-
-       ulong flags;
        int crd;
        struct board_info *bd;
        unsigned char board_id = 0;
 
-#ifdef ENABLE_PCI
        int pci_boards_found, pci_count;
 
        pci_count = 0;
-#endif /* ENABLE_PCI */
 
        pc_driver = alloc_tty_driver(MAX_ALLOC);
        if (!pc_driver)
@@ -1416,8 +1183,7 @@ int __init pc_init(void)
                Note : If LILO has ran epca_setup then epca_setup will handle defining
                num_cards as well as copying the data into the board structure.
        -------------------------------------------------------------------------- */
-       if (!liloconfig)
-       { /* Begin driver has been configured via. epcaconfig */
+       if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */
 
                nbdevs = NBDEVS;
                num_cards = NUMCARDS;
@@ -1440,8 +1206,6 @@ int __init pc_init(void)
 
        printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
 
-#ifdef ENABLE_PCI
-
        /* ------------------------------------------------------------------
                NOTE : This code assumes that the number of ports found in 
                       the boards array is correct.  This could be wrong if
@@ -1467,8 +1231,6 @@ int __init pc_init(void)
                pci_boards_found += init_PCI();
        num_cards += pci_boards_found;
 
-#endif /* ENABLE_PCI */
-
        pc_driver->owner = THIS_MODULE;
        pc_driver->name = "ttyD"; 
        pc_driver->devfs_name = "tts/D";
@@ -1499,9 +1261,6 @@ int __init pc_init(void)
        tty_set_operations(pc_info, &info_ops);
 
 
-       save_flags(flags);
-       cli();
-
        for (crd = 0; crd < num_cards; crd++) 
        { /* Begin for each card */
 
@@ -1610,11 +1369,7 @@ int __init pc_init(void)
                                        if ((board_id & 0x30) == 0x30) 
                                                bd->memory_seg = 0x8000;
 
-                               } /* End it is an XI card */
-                               else
-                               {
-                                       printk(KERN_ERR "<Error> - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
-                               }
+                               } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
                        break;
 
                } /* End switch on bd->type */
@@ -1634,9 +1389,6 @@ int __init pc_init(void)
        init_timer(&epca_timer);
        epca_timer.function = epcapoll;
        mod_timer(&epca_timer, jiffies + HZ/25);
-
-       restore_flags(flags);
-
        return 0;
 
 } /* End pc_init */
@@ -1647,10 +1399,10 @@ static void post_fep_init(unsigned int crd)
 { /* Begin post_fep_init */
 
        int i;
-       unchar *memaddr;
-       volatile struct global_data *gd;
+       unsigned char *memaddr;
+       struct global_data *gd;
        struct board_info *bd;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
        struct channel *ch; 
        int shrinkmem = 0, lowwater ; 
  
@@ -1669,9 +1421,7 @@ static void post_fep_init(unsigned int crd)
                after DIGI_INIT has been called will return the proper values. 
        ------------------------------------------------------------------- */
 
-       if (bd->type >= PCIXEM) /* If the board in question is PCI */
-       { /* Begin get PCI number of ports */
-
+       if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
                /* --------------------------------------------------------------------
                        Below we use XEMPORTS as a memory offset regardless of which PCI
                        card it is.  This is because all of the supported PCI cards have
@@ -1685,15 +1435,15 @@ static void post_fep_init(unsigned int crd)
                        (FYI - The id should be located at 0x1ac (And may use up to 4 bytes
                        if the box in question is a XEM or CX)).  
                ------------------------------------------------------------------------ */ 
-
-               bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long)
-                                                       (bd->re_map_membase + XEMPORTS));
-
-               
+               /* PCI cards are already remapped at this point ISA are not */
+               bd->numports = readw(bd->re_map_membase + XEMPORTS);
                epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
                nbdevs += (bd->numports);
-
-       } /* End get PCI number of ports */
+       } else {
+               /* Fix up the mappings for ISA/EISA etc */
+               /* FIXME: 64K - can we be smarter ? */
+               bd->re_map_membase = ioremap(bd->membase, 0x10000);
+       }
 
        if (crd != 0)
                card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
@@ -1701,19 +1451,9 @@ static void post_fep_init(unsigned int crd)
                card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
 
        ch = card_ptr[crd];
-
-
        epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
 
-       memaddr = (unchar *)bd->re_map_membase;
-
-       /* 
-          The below command is necessary because newer kernels (2.1.x and
-          up) do not have a 1:1 virtual to physical mapping.  The below
-          call adjust for that.
-       */
-
-       memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
+       memaddr = bd->re_map_membase;
 
        /* -----------------------------------------------------------------
                The below assignment will set bc to point at the BEGINING of
@@ -1721,7 +1461,7 @@ static void post_fep_init(unsigned int crd)
                8 and 64 of these structures.
        -------------------------------------------------------------------- */
 
-       bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
+       bc = (struct board_chan *)(memaddr + CHANSTRUCT);
 
        /* -------------------------------------------------------------------
                The below assignment will set gd to point at the BEGINING of
@@ -1730,20 +1470,18 @@ static void post_fep_init(unsigned int crd)
                pointer begins at 0xd10.
        ---------------------------------------------------------------------- */
 
-       gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
+       gd = (struct global_data *)(memaddr + GLOBAL);
 
        /* --------------------------------------------------------------------
                XEPORTS (address 0xc22) points at the number of channels the
                card supports. (For 64XE, XI, XEM, and XR use 0xc02)
        ----------------------------------------------------------------------- */
 
-       if (((bd->type == PCXEVE) | (bd->type == PCXE)) &&
-           (*(ushort *)((ulong)memaddr + XEPORTS) < 3))
+       if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
                shrinkmem = 1;
        if (bd->type < PCIXEM)
                if (!request_region((int)bd->port, 4, board_desc[bd->type]))
                        return;         
-
        memwinon(bd, 0);
 
        /*  --------------------------------------------------------------------
@@ -1753,17 +1491,16 @@ static void post_fep_init(unsigned int crd)
 
        /* For every port on the card do ..... */
 
-       for (i = 0; i < bd->numports; i++, ch++, bc++) 
-       { /* Begin for each port */
+       for (i = 0; i < bd->numports; i++, ch++, bc++)  { /* Begin for each port */
+               unsigned long flags;
 
                ch->brdchan        = bc;
                ch->mailbox        = gd; 
                INIT_WORK(&ch->tqueue, do_softint, ch);
                ch->board          = &boards[crd];
 
-               switch (bd->type)
-               { /* Begin switch bd->type */
-
+               spin_lock_irqsave(&epca_lock, flags);
+               switch (bd->type) {
                        /* ----------------------------------------------------------------
                                Since some of the boards use different bitmaps for their
                                control signals we cannot hard code these values and retain
@@ -1796,14 +1533,12 @@ static void post_fep_init(unsigned int crd)
        
                } /* End switch bd->type */
 
-               if (boards[crd].altpin) 
-               {
+               if (boards[crd].altpin) {
                        ch->dsr = ch->m_dcd;
                        ch->dcd = ch->m_dsr;
                        ch->digiext.digi_flags |= DIGI_ALTPIN;
                }
-               else 
-               { 
+               else {
                        ch->dcd = ch->m_dcd;
                        ch->dsr = ch->m_dsr;
                }
@@ -1813,14 +1548,12 @@ static void post_fep_init(unsigned int crd)
                ch->magic      = EPCA_MAGIC;
                ch->tty        = NULL;
 
-               if (shrinkmem) 
-               {
+               if (shrinkmem) {
                        fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
                        shrinkmem = 0;
                }
 
-               switch (bd->type)
-               { /* Begin switch bd->type */
+               switch (bd->type) {
 
                        case PCIXEM:
                        case PCIXRJ:
@@ -1878,13 +1611,13 @@ static void post_fep_init(unsigned int crd)
 
                fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
 
-               bc->edelay = 100;
-               bc->idata = 1;
+               writew(100, &bc->edelay);
+               writeb(1, &bc->idata);
        
-               ch->startc  = bc->startc;
-               ch->stopc   = bc->stopc;
-               ch->startca = bc->startca;
-               ch->stopca  = bc->stopca;
+               ch->startc  = readb(&bc->startc);
+               ch->stopc   = readb(&bc->stopc);
+               ch->startca = readb(&bc->startca);
+               ch->stopca  = readb(&bc->stopca);
        
                ch->fepcflag = 0;
                ch->fepiflag = 0;
@@ -1899,27 +1632,23 @@ static void post_fep_init(unsigned int crd)
                ch->blocked_open = 0;
                init_waitqueue_head(&ch->open_wait);
                init_waitqueue_head(&ch->close_wait);
+
+               spin_unlock_irqrestore(&epca_lock, flags);
+
                ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
-               if (!(ch->tmp_buf))
-               {
+               if (!ch->tmp_buf) {
                        printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i);
                        release_region((int)bd->port, 4);
                        while(i-- > 0)
                                kfree((ch--)->tmp_buf);
                        return;
-               }
-               else 
+               } else
                        memset((void *)ch->tmp_buf,0,ch->txbufsize);
        } /* End for each port */
 
        printk(KERN_INFO 
                "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", 
                VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
-       sprintf(mesg, 
-               "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", 
-               VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
-       console_print(mesg);
-
        memwinoff(bd, 0);
 
 } /* End post_fep_init */
@@ -1943,9 +1672,6 @@ static void epcapoll(unsigned long ignored)
                buffer empty) and acts on those events.
        ----------------------------------------------------------------------- */
        
-       save_flags(flags);
-       cli();
-
        for (crd = 0; crd < num_cards; crd++) 
        { /* Begin for each card */
 
@@ -1961,6 +1687,8 @@ static void epcapoll(unsigned long ignored)
                        some legacy boards.
                ---------------------------------------------------------------- */
 
+               spin_lock_irqsave(&epca_lock, flags);
+
                assertmemoff(ch);
 
                globalwinon(ch);
@@ -1970,21 +1698,19 @@ static void epcapoll(unsigned long ignored)
                        the transmit or receive queue.
                ------------------------------------------------------------------- */
 
-               head = ch->mailbox->ein;
-               tail = ch->mailbox->eout;
+               head = readw(&ch->mailbox->ein);
+               tail = readw(&ch->mailbox->eout);
                
                /* If head isn't equal to tail we have an event */
 
                if (head != tail)
                        doevent(crd);
-
                memoff(ch);
 
-       } /* End for each card */
+               spin_unlock_irqrestore(&epca_lock, flags);
 
+       } /* End for each card */
        mod_timer(&epca_timer, jiffies + (HZ / 25));
-
-       restore_flags(flags);
 } /* End epcapoll */
 
 /* --------------------- Begin doevent  ------------------------ */
@@ -1992,53 +1718,42 @@ static void epcapoll(unsigned long ignored)
 static void doevent(int crd)
 { /* Begin doevent */
 
-       volatile unchar *eventbuf;
+       void *eventbuf;
        struct channel *ch, *chan0;
        static struct tty_struct *tty;
-       volatile struct board_info *bd;
-       volatile struct board_chan *bc;
-       register volatile unsigned int tail, head;
-       register int event, channel;
-       register int mstat, lstat;
+       struct board_info *bd;
+       struct board_chan *bc;
+       unsigned int tail, head;
+       int event, channel;
+       int mstat, lstat;
 
        /* -------------------------------------------------------------------
                This subroutine is called by epcapoll when an event is detected 
                in the event queue.  This routine responds to those events.
        --------------------------------------------------------------------- */
-
        bd = &boards[crd];
 
        chan0 = card_ptr[crd];
        epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-
        assertgwinon(chan0);
-
-       while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) 
+       while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein)))
        { /* Begin while something in event queue */
-
                assertgwinon(chan0);
-
-               eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART));
-
+               eventbuf = bd->re_map_membase + tail + ISTART;
                /* Get the channel the event occurred on */
-               channel = eventbuf[0];
-
+               channel = readb(eventbuf);
                /* Get the actual event code that occurred */
-               event = eventbuf[1];
-
+               event = readb(eventbuf + 1);
                /*  ----------------------------------------------------------------
                        The two assignments below get the current modem status (mstat)
                        and the previous modem status (lstat).  These are useful becuase
                        an event could signal a change in modem signals itself.
                ------------------------------------------------------------------- */
-
-               mstat = eventbuf[2];
-               lstat = eventbuf[3];
+               mstat = readb(eventbuf + 2);
+               lstat = readb(eventbuf + 3);
 
                ch = chan0 + channel;
-
-               if ((unsigned)channel >= bd->numports || !ch) 
-               { 
+               if ((unsigned)channel >= bd->numports || !ch)  {
                        if (channel >= bd->numports)
                                ch = chan0;
                        bc = ch->brdchan;
@@ -2048,97 +1763,53 @@ static void doevent(int crd)
                if ((bc = ch->brdchan) == NULL)
                        goto next;
 
-               if (event & DATA_IND) 
-               { /* Begin DATA_IND */
-
+               if (event & DATA_IND)  { /* Begin DATA_IND */
                        receive_data(ch);
                        assertgwinon(ch);
-
                } /* End DATA_IND */
                /* else *//* Fix for DCD transition missed bug */
-               if (event & MODEMCHG_IND) 
-               { /* Begin MODEMCHG_IND */
-
+               if (event & MODEMCHG_IND)  { /* Begin MODEMCHG_IND */
                        /* A modem signal change has been indicated */
-
                        ch->imodem = mstat;
-
-                       if (ch->asyncflags & ASYNC_CHECK_CD) 
-                       {
+                       if (ch->asyncflags & ASYNC_CHECK_CD)  {
                                if (mstat & ch->dcd)  /* We are now receiving dcd */
                                        wake_up_interruptible(&ch->open_wait);
                                else
                                        pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
                        }
-
                } /* End MODEMCHG_IND */
-
                tty = ch->tty;
-               if (tty) 
-               { /* Begin if valid tty */
-
-                       if (event & BREAK_IND) 
-                       { /* Begin if BREAK_IND */
-
+               if (tty)  { /* Begin if valid tty */
+                       if (event & BREAK_IND)  { /* Begin if BREAK_IND */
                                /* A break has been indicated */
-
                                tty->flip.count++;
                                *tty->flip.flag_buf_ptr++ = TTY_BREAK;
-
                                *tty->flip.char_buf_ptr++ = 0;
-
                                tty_schedule_flip(tty); 
-
-                       } /* End if BREAK_IND */
-                       else
-                       if (event & LOWTX_IND) 
-                       { /* Begin LOWTX_IND */
-
+                       } else if (event & LOWTX_IND)  { /* Begin LOWTX_IND */
                                if (ch->statusflags & LOWWAIT) 
                                { /* Begin if LOWWAIT */
-
                                        ch->statusflags &= ~LOWWAIT;
                                        tty_wakeup(tty);
                                        wake_up_interruptible(&tty->write_wait);
-
                                } /* End if LOWWAIT */
-
-                       } /* End LOWTX_IND */
-                       else
-                       if (event & EMPTYTX_IND) 
-                       { /* Begin EMPTYTX_IND */
-
+                       } else if (event & EMPTYTX_IND)  { /* Begin EMPTYTX_IND */
                                /* This event is generated by setup_empty_event */
-
                                ch->statusflags &= ~TXBUSY;
-                               if (ch->statusflags & EMPTYWAIT) 
-                               { /* Begin if EMPTYWAIT */
-
+                               if (ch->statusflags & EMPTYWAIT)  { /* Begin if EMPTYWAIT */
                                        ch->statusflags &= ~EMPTYWAIT;
                                        tty_wakeup(tty);
-
                                        wake_up_interruptible(&tty->write_wait);
-
                                } /* End if EMPTYWAIT */
-
                        } /* End EMPTYTX_IND */
-
                } /* End if valid tty */
-
-
        next:
                globalwinon(ch);
-
-               if (!bc)
-                       printk(KERN_ERR "<Error> - bc == NULL in doevent!\n");
-               else 
-                       bc->idata = 1;
-
-               chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4);
+               BUG_ON(!bc);
+               writew(1, &bc->idata);
+               writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
                globalwinon(chan0);
-
        } /* End while something in event queue */
-
 } /* End doevent */
 
 /* --------------------- Begin fepcmd  ------------------------ */
@@ -2146,7 +1817,6 @@ static void doevent(int crd)
 static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
                    int byte2, int ncmds, int bytecmd)
 { /* Begin fepcmd */
-
        unchar *memaddr;
        unsigned int head, cmdTail, cmdStart, cmdMax;
        long count;
@@ -2155,93 +1825,57 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
        /* This is the routine in which commands may be passed to the card. */
 
        if (ch->board->status == DISABLED)
-       {
                return;
-       }
-
        assertgwinon(ch);
-
        /* Remember head (As well as max) is just an offset not a base addr */
-       head = ch->mailbox->cin;
-
+       head = readw(&ch->mailbox->cin);
        /* cmdStart is a base address */
-       cmdStart = ch->mailbox->cstart;
-
+       cmdStart = readw(&ch->mailbox->cstart);
        /* ------------------------------------------------------------------
                We do the addition below because we do not want a max pointer 
                relative to cmdStart.  We want a max pointer that points at the 
                physical end of the command queue.
        -------------------------------------------------------------------- */
-
-       cmdMax = (cmdStart + 4 + (ch->mailbox->cmax));
-
+       cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
        memaddr = ch->board->re_map_membase;
 
-       /* 
-          The below command is necessary because newer kernels (2.1.x and
-          up) do not have a 1:1 virtual to physical mapping.  The below
-          call adjust for that.
-       */
-
-       memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
-
-       if (head >= (cmdMax - cmdStart) || (head & 03)) 
-       {
-               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, 
-              cmd, head);
-               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, 
-              cmdMax, cmdStart);
+       if (head >= (cmdMax - cmdStart) || (head & 03))  {
+               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__,  cmd, head);
+               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__,  cmdMax, cmdStart);
                return;
        }
-
-       if (bytecmd) 
-       {
-               *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
-
-               *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
+       if (bytecmd)  {
+               writeb(cmd, memaddr + head + cmdStart + 0);
+               writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
                /* Below word_or_byte is bits to set */
-               *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte;
+               writeb(word_or_byte,  memaddr + head + cmdStart + 2);
                /* Below byte2 is bits to reset */
-               *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2;
-
-       } 
-       else 
-       {
-               *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
-               *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
-               *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte;
+               writeb(byte2, memaddr + head + cmdStart + 3);
+       }  else {
+               writeb(cmd, memaddr + head + cmdStart + 0);
+               writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
+               writeb(word_or_byte,  memaddr + head + cmdStart + 2);
        }
-
        head = (head + 4) & (cmdMax - cmdStart - 4);
-       ch->mailbox->cin = head;
-
+       writew(head, &ch->mailbox->cin);
        count = FEPTIMEOUT;
 
-       for (;;) 
-       { /* Begin forever loop */
-
+       for (;;)  { /* Begin forever loop */
                count--;
-               if (count == 0) 
-               {
+               if (count == 0)  {
                        printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
                        return;
                }
-
-               head = ch->mailbox->cin;
-               cmdTail = ch->mailbox->cout;
-
+               head = readw(&ch->mailbox->cin);
+               cmdTail = readw(&ch->mailbox->cout);
                n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-
                /* ----------------------------------------------------------
                        Basically this will break when the FEP acknowledges the 
                        command by incrementing cmdTail (Making it equal to head).
                ------------------------------------------------------------- */
-
                if (n <= ncmds * (sizeof(short) * 4))
                        break; /* Well nearly forever :-) */
-
        } /* End forever loop */
-
 } /* End fepcmd */
 
 /* ---------------------------------------------------------------------
@@ -2255,11 +1889,9 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
 
 static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
 { /* Begin termios2digi_h */
-
        unsigned res = 0;
 
-       if (cflag & CRTSCTS) 
-       {
+       if (cflag & CRTSCTS) {
                ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
                res |= ((ch->m_cts) | (ch->m_rts));
        }
@@ -2295,7 +1927,6 @@ static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
 
        unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | 
                                INPCK | ISTRIP|IXON|IXANY|IXOFF);
-       
        if (ch->digiext.digi_flags & DIGI_AIXON)
                res |= IAIXON;
        return res;
@@ -2308,28 +1939,15 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
 { /* Begin termios2digi_c */
 
        unsigned res = 0;
-
-#ifdef SPEED_HACK
-       /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
-       if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200;
-       if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600;
-#endif /* SPEED_HACK */
-
-       if (cflag & CBAUDEX)
-       { /* Begin detected CBAUDEX */
-
+       if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */
                ch->digiext.digi_flags |= DIGI_FAST;
-
                /* -------------------------------------------------------------
                   HUPCL bit is used by FEP to indicate fast baud
                   table is to be used.
                ----------------------------------------------------------------- */
-
                res |= FEP_HUPCL;
-
        } /* End detected CBAUDEX */
        else ch->digiext.digi_flags &= ~DIGI_FAST; 
-
        /* -------------------------------------------------------------------
                CBAUD has bit position 0x1000 set these days to indicate Linux
                baud rate remap.  Digi hardware can't handle the bit assignment.
@@ -2337,7 +1955,6 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
                bit out.
        ---------------------------------------------------------------------- */
        res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
        /* -------------------------------------------------------------
                This gets a little confusing.  The Digi cards have their own
                representation of c_cflags controling baud rate.  For the most
@@ -2357,10 +1974,8 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
                should be checked for a screened out prior to termios2digi_c 
                returning.  Since CLOCAL isn't used by the board this can be
                ignored as long as the returned value is used only by Digi hardware. 
-       ----------------------------------------------------------------- */
-
-       if (cflag & CBAUDEX)
-       {
+               ----------------------------------------------------------------- */
+       if (cflag & CBAUDEX) {
                /* -------------------------------------------------------------
                        The below code is trying to guarantee that only baud rates
                        115200 and 230400 are remapped.  We use exclusive or because
@@ -2371,138 +1986,96 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
                                
                if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || 
                    (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
-               {
                        res += 1;
-               }
        }
-
        return res;
 
 } /* End termios2digi_c */
 
 /* --------------------- Begin epcaparam  ----------------------- */
 
+/* Caller must hold the locks */
 static void epcaparam(struct tty_struct *tty, struct channel *ch)
 { /* Begin epcaparam */
 
        unsigned int cmdHead;
        struct termios *ts;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
        unsigned mval, hflow, cflag, iflag;
 
        bc = ch->brdchan;
        epcaassert(bc !=0, "bc out of range");
 
        assertgwinon(ch);
-
        ts = tty->termios;
-
-       if ((ts->c_cflag & CBAUD) == 0) 
-       { /* Begin CBAUD detected */
-
-               cmdHead = bc->rin;
+       if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
+               cmdHead = readw(&bc->rin);
                bc->rout = cmdHead;
-               cmdHead = bc->tin;
-
+               cmdHead = readw(&bc->tin);
                /* Changing baud in mid-stream transmission can be wonderful */
                /* ---------------------------------------------------------------
                        Flush current transmit buffer by setting cmdTail pointer (tout)
                        to cmdHead pointer (tin).  Hopefully the transmit buffer is empty.
                ----------------------------------------------------------------- */
-
                fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
                mval = 0;
-
-       } /* End CBAUD detected */
-       else 
-       { /* Begin CBAUD not detected */
-
+       } else  { /* Begin CBAUD not detected */
                /* -------------------------------------------------------------------
                        c_cflags have changed but that change had nothing to do with BAUD.
                        Propagate the change to the card.
                ---------------------------------------------------------------------- */ 
-
                cflag = termios2digi_c(ch, ts->c_cflag);
-
-               if (cflag != ch->fepcflag) 
-               {
+               if (cflag != ch->fepcflag)  {
                        ch->fepcflag = cflag;
                        /* Set baud rate, char size, stop bits, parity */
                        fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
                }
-
-
                /* ----------------------------------------------------------------
                        If the user has not forced CLOCAL and if the device is not a 
                        CALLOUT device (Which is always CLOCAL) we set flags such that
                        the driver will wait on carrier detect.
                ------------------------------------------------------------------- */
-
                if (ts->c_cflag & CLOCAL)
-               { /* Begin it is a cud device or a ttyD device with CLOCAL on */
                        ch->asyncflags &= ~ASYNC_CHECK_CD;
-               } /* End it is a cud device or a ttyD device with CLOCAL on */
                else
-               { /* Begin it is a ttyD device */
                        ch->asyncflags |= ASYNC_CHECK_CD;
-               } /* End it is a ttyD device */
-
                mval = ch->m_dtr | ch->m_rts;
-
        } /* End CBAUD not detected */
-
        iflag = termios2digi_i(ch, ts->c_iflag);
-
        /* Check input mode flags */
-
-       if (iflag != ch->fepiflag) 
-       {
+       if (iflag != ch->fepiflag)  {
                ch->fepiflag = iflag;
-
                /* ---------------------------------------------------------------
                        Command sets channels iflag structure on the board. Such things 
                        as input soft flow control, handling of parity errors, and
                        break handling are all set here.
                ------------------------------------------------------------------- */
-
                /* break handling, parity handling, input stripping, flow control chars */
                fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
        }
-
        /* ---------------------------------------------------------------
                Set the board mint value for this channel.  This will cause hardware
                events to be generated each time the DCD signal (Described in mint) 
                changes.        
        ------------------------------------------------------------------- */
-       bc->mint = ch->dcd;
-
+       writeb(ch->dcd, &bc->mint);
        if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
                if (ch->digiext.digi_flags & DIGI_FORCEDCD)
-                       bc->mint = 0;
-
-       ch->imodem = bc->mstat;
-
+                       writeb(0, &bc->mint);
+       ch->imodem = readb(&bc->mstat);
        hflow = termios2digi_h(ch, ts->c_cflag);
-
-       if (hflow != ch->hflow) 
-       {
+       if (hflow != ch->hflow)  {
                ch->hflow = hflow;
-
                /* --------------------------------------------------------------
                        Hard flow control has been selected but the board is not
                        using it.  Activate hard flow control now.
                ----------------------------------------------------------------- */
-
                fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
        }
-       
-
        mval ^= ch->modemfake & (mval ^ ch->modem);
 
-       if (ch->omodem ^ mval) 
-       {
+       if (ch->omodem ^ mval)  {
                ch->omodem = mval;
-
                /* --------------------------------------------------------------
                        The below command sets the DTR and RTS mstat structure.  If
                        hard flow control is NOT active these changes will drive the
@@ -2514,87 +2087,65 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
                /* First reset DTR & RTS; then set them */
                fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
                fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-
        }
-
-       if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) 
-       {
+       if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)  {
                ch->fepstartc = ch->startc;
                ch->fepstopc = ch->stopc;
-
                /* ------------------------------------------------------------
                        The XON / XOFF characters have changed; propagate these
                        changes to the card.    
                --------------------------------------------------------------- */
-
                fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
        }
-
-       if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) 
-       {
+       if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)  {
                ch->fepstartca = ch->startca;
                ch->fepstopca = ch->stopca;
-
                /* ---------------------------------------------------------------
                        Similar to the above, this time the auxilarly XON / XOFF 
                        characters have changed; propagate these changes to the card.
                ------------------------------------------------------------------ */
-
                fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
        }
-
 } /* End epcaparam */
 
 /* --------------------- Begin receive_data  ----------------------- */
-
+/* Caller holds lock */
 static void receive_data(struct channel *ch)
 { /* Begin receive_data */
 
        unchar *rptr;
        struct termios *ts = NULL;
        struct tty_struct *tty;
-       volatile struct board_chan *bc;
-       register int dataToRead, wrapgap, bytesAvailable;
-       register unsigned int tail, head;
+       struct board_chan *bc;
+       int dataToRead, wrapgap, bytesAvailable;
+       unsigned int tail, head;
        unsigned int wrapmask;
        int rc;
 
-
        /* ---------------------------------------------------------------
                This routine is called by doint when a receive data event 
                has taken place.
        ------------------------------------------------------------------- */
 
        globalwinon(ch);
-
        if (ch->statusflags & RXSTOPPED)
                return;
-
        tty = ch->tty;
        if (tty)
                ts = tty->termios;
-
        bc = ch->brdchan;
-
-       if (!bc) 
-       {
-               printk(KERN_ERR "<Error> - bc is NULL in receive_data!\n");
-               return;
-       }
-
+       BUG_ON(!bc);
        wrapmask = ch->rxbufsize - 1;
 
        /* --------------------------------------------------------------------- 
                Get the head and tail pointers to the receiver queue.  Wrap the 
                head pointer if it has reached the end of the buffer.
        ------------------------------------------------------------------------ */
-
-       head = bc->rin;
+       head = readw(&bc->rin);
        head &= wrapmask;
-       tail = bc->rout & wrapmask;
+       tail = readw(&bc->rout) & wrapmask;
 
        bytesAvailable = (head - tail) & wrapmask;
-
        if (bytesAvailable == 0)
                return;
 
@@ -2602,8 +2153,7 @@ static void receive_data(struct channel *ch)
           If CREAD bit is off or device not open, set TX tail to head
        --------------------------------------------------------------------- */
 
-       if (!tty || !ts || !(ts->c_cflag & CREAD)) 
-       {
+       if (!tty || !ts || !(ts->c_cflag & CREAD))  {
                bc->rout = head;
                return;
        }
@@ -2611,64 +2161,45 @@ static void receive_data(struct channel *ch)
        if (tty->flip.count == TTY_FLIPBUF_SIZE) 
                return;
 
-       if (bc->orun) 
-       {
-               bc->orun = 0;
-               printk(KERN_WARNING "overrun! DigiBoard device %s\n",tty->name);
+       if (readb(&bc->orun)) {
+               writeb(0, &bc->orun);
+               printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
        }
-
        rxwinon(ch);
        rptr = tty->flip.char_buf_ptr;
        rc = tty->flip.count;
-
-       while (bytesAvailable > 0) 
-       { /* Begin while there is data on the card */
-
+       while (bytesAvailable > 0)  { /* Begin while there is data on the card */
                wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-
                /* ---------------------------------------------------------------
                        Even if head has wrapped around only report the amount of
                        data to be equal to the size - tail.  Remember memcpy can't
                        automaticly wrap around the receive buffer.
                ----------------------------------------------------------------- */
-
                dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
-
                /* --------------------------------------------------------------
                   Make sure we don't overflow the buffer
                ----------------------------------------------------------------- */
-
                if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
                        dataToRead = TTY_FLIPBUF_SIZE - rc;
-
                if (dataToRead == 0)
                        break;
-
                /* ---------------------------------------------------------------
                        Move data read from our card into the line disciplines buffer
                        for translation if necessary.
                ------------------------------------------------------------------ */
-
-               if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr)
-                       printk(KERN_ERR "<Error> - receive_data : memcpy failed\n");
-                       
+               memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
                rc   += dataToRead;
                rptr += dataToRead;
                tail = (tail + dataToRead) & wrapmask;
                bytesAvailable -= dataToRead;
-
        } /* End while there is data on the card */
-
-
        tty->flip.count = rc;
        tty->flip.char_buf_ptr = rptr;
        globalwinon(ch);
-       bc->rout = tail;
-
+       writew(tail, &bc->rout);
        /* Must be called with global data */
        tty_schedule_flip(ch->tty); 
        return;
-
 } /* End receive_data */
 
 static int info_ioctl(struct tty_struct *tty, struct file * file,
@@ -2676,17 +2207,15 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
 {
        switch (cmd) 
        { /* Begin switch cmd */
-
                case DIGI_GETINFO:
                { /* Begin case DIGI_GETINFO */
-
                        struct digi_info di ;
                        int brd;
 
-                       getUser(brd, (unsigned int __user *)arg);
-
-                       if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
-                               return (-ENODEV);
+                       if(get_user(brd, (unsigned int __user *)arg))
+                               return -EFAULT;
+                       if (brd < 0 || brd >= num_cards || num_cards == 0)
+                               return -ENODEV;
 
                        memset(&di, 0, sizeof(di));
 
@@ -2694,8 +2223,9 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
                        di.status = boards[brd].status;
                        di.type = boards[brd].type ;
                        di.numports = boards[brd].numports ;
-                       di.port = boards[brd].port ;
-                       di.membase = boards[brd].membase ;
+                       /* Legacy fixups - just move along nothing to see */
+                       di.port = (unsigned char *)boards[brd].port ;
+                       di.membase = (unsigned char *)boards[brd].membase ;
 
                        if (copy_to_user((void __user *)arg, &di, sizeof (di)))
                                return -EFAULT;
@@ -2709,39 +2239,29 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
                        int brd = arg & 0xff000000 >> 16 ; 
                        unsigned char state = arg & 0xff ; 
 
-                       if ((brd < 0) || (brd >= num_cards))
-                       {
-                               printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
+                       if (brd < 0 || brd >= num_cards) {
+                               printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
                                return (-ENODEV);
                        }
-
                        digi_poller_inhibited = state ;
                        break ; 
-
                } /* End case DIGI_POLLER */
 
                case DIGI_INIT:
                { /* Begin case DIGI_INIT */
-
                        /* ------------------------------------------------------------
                                This call is made by the apps to complete the initilization
                                of the board(s).  This routine is responsible for setting
                                the card to its initial state and setting the drivers control
                                fields to the sutianle settings for the card in question.
                        ---------------------------------------------------------------- */
-               
                        int crd ; 
                        for (crd = 0; crd < num_cards; crd++) 
                                post_fep_init (crd);
-
                        break ; 
-
                } /* End case DIGI_INIT */
-
-
                default:
-                       return -ENOIOCTLCMD;
-
+                       return -ENOTTY;
        } /* End switch cmd */
        return (0) ;
 }
@@ -2750,43 +2270,33 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
 static int pc_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct channel *ch = (struct channel *) tty->driver_data;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
        unsigned int mstat, mflag = 0;
        unsigned long flags;
 
        if (ch)
                bc = ch->brdchan;
        else
-       {
-               printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n");
-               return(-EINVAL);
-       }
+               return -EINVAL;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
-       mstat = bc->mstat;
+       mstat = readb(&bc->mstat);
        memoff(ch);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&epca_lock, flags);
 
        if (mstat & ch->m_dtr)
                mflag |= TIOCM_DTR;
-
        if (mstat & ch->m_rts)
                mflag |= TIOCM_RTS;
-
        if (mstat & ch->m_cts)
                mflag |= TIOCM_CTS;
-
        if (mstat & ch->dsr)
                mflag |= TIOCM_DSR;
-
        if (mstat & ch->m_ri)
                mflag |= TIOCM_RI;
-
        if (mstat & ch->dcd)
                mflag |= TIOCM_CD;
-
        return mflag;
 }
 
@@ -2796,13 +2306,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
        struct channel *ch = (struct channel *) tty->driver_data;
        unsigned long flags;
 
-       if (!ch) {
-               printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n");
-               return(-EINVAL);
-       }
+       if (!ch)
+               return -EINVAL;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&epca_lock, flags);
        /*
         * I think this modemfake stuff is broken.  It doesn't
         * correctly reflect the behaviour desired by the TIOCM*
@@ -2824,17 +2331,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
                ch->modemfake |= ch->m_dtr;
                ch->modem &= ~ch->m_dtr;
        }
-
        globalwinon(ch);
-
        /*  --------------------------------------------------------------
                The below routine generally sets up parity, baud, flow control
                issues, etc.... It effect both control flags and input flags.
        ------------------------------------------------------------------ */
-
        epcaparam(tty,ch);
        memoff(ch);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&epca_lock, flags);
        return 0;
 }
 
@@ -2847,19 +2351,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
        unsigned long flags;
        unsigned int mflag, mstat;
        unsigned char startc, stopc;
-       volatile struct board_chan *bc;
+       struct board_chan *bc;
        struct channel *ch = (struct channel *) tty->driver_data;
        void __user *argp = (void __user *)arg;
        
        if (ch)
                bc = ch->brdchan;
        else 
-       {
-               printk(KERN_ERR "<Error> - ch is NULL in pc_ioctl!\n");
-               return(-EINVAL);
-       }
-
-       save_flags(flags);
+               return -EINVAL;
 
        /* -------------------------------------------------------------------
                For POSIX compliance we need to add more ioctls.  See tty_ioctl.c
@@ -2871,46 +2370,39 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
        { /* Begin switch cmd */
 
                case TCGETS:
-                       if (copy_to_user(argp, 
-                                        tty->termios, sizeof(struct termios)))
+                       if (copy_to_user(argp, tty->termios, sizeof(struct termios)))
                                return -EFAULT;
-                       return(0);
-
+                       return 0;
                case TCGETA:
                        return get_termio(tty, argp);
-
                case TCSBRK:    /* SVID version: non-zero arg --> no break */
-
                        retval = tty_check_change(tty);
                        if (retval)
                                return retval;
-
                        /* Setup an event to indicate when the transmit buffer empties */
-
+                       spin_lock_irqsave(&epca_lock, flags);
                        setup_empty_event(tty,ch);              
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        tty_wait_until_sent(tty, 0);
                        if (!arg)
                                digi_send_break(ch, HZ/4);    /* 1/4 second */
                        return 0;
-
                case TCSBRKP:   /* support for POSIX tcsendbreak() */
-
                        retval = tty_check_change(tty);
                        if (retval)
                                return retval;
 
                        /* Setup an event to indicate when the transmit buffer empties */
-
+                       spin_lock_irqsave(&epca_lock, flags);
                        setup_empty_event(tty,ch);              
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        tty_wait_until_sent(tty, 0);
                        digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
                        return 0;
-
                case TIOCGSOFTCAR:
                        if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
                                return -EFAULT;
                        return 0;
-
                case TIOCSSOFTCAR:
                {
                        unsigned int value;
@@ -2922,75 +2414,63 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                                 (value ? CLOCAL : 0));
                        return 0;
                }
-
                case TIOCMODG:
                        mflag = pc_tiocmget(tty, file);
                        if (put_user(mflag, (unsigned long __user *)argp))
                                return -EFAULT;
                        break;
-
                case TIOCMODS:
                        if (get_user(mstat, (unsigned __user *)argp))
                                return -EFAULT;
                        return pc_tiocmset(tty, file, mstat, ~mstat);
-
                case TIOCSDTR:
+                       spin_lock_irqsave(&epca_lock, flags);
                        ch->omodem |= ch->m_dtr;
-                       cli();
                        globalwinon(ch);
                        fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
                        memoff(ch);
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        break;
 
                case TIOCCDTR:
+                       spin_lock_irqsave(&epca_lock, flags);
                        ch->omodem &= ~ch->m_dtr;
-                       cli();
                        globalwinon(ch);
                        fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
                        memoff(ch);
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        break;
-
                case DIGI_GETA:
                        if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
                                return -EFAULT;
                        break;
-
                case DIGI_SETAW:
                case DIGI_SETAF:
-                       if ((cmd) == (DIGI_SETAW)) 
-                       {
+                       if (cmd == DIGI_SETAW) {
                                /* Setup an event to indicate when the transmit buffer empties */
-
+                               spin_lock_irqsave(&epca_lock, flags);
                                setup_empty_event(tty,ch);              
+                               spin_unlock_irqrestore(&epca_lock, flags);
                                tty_wait_until_sent(tty, 0);
-                       }
-                       else 
-                       {
+                       } else  {
                                /* ldisc lock already held in ioctl */
                                if (tty->ldisc.flush_buffer)
                                        tty->ldisc.flush_buffer(tty);
                        }
-
                        /* Fall Thru */
-
                case DIGI_SETA:
                        if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
                                return -EFAULT;
                        
-                       if (ch->digiext.digi_flags & DIGI_ALTPIN) 
-                       {
+                       if (ch->digiext.digi_flags & DIGI_ALTPIN)  {
                                ch->dcd = ch->m_dsr;
                                ch->dsr = ch->m_dcd;
-                       } 
-                       else 
-                       {
+                       } else {
                                ch->dcd = ch->m_dcd;
                                ch->dsr = ch->m_dsr;
                        }
                
-                       cli();
+                       spin_lock_irqsave(&epca_lock, flags);
                        globalwinon(ch);
 
                        /* -----------------------------------------------------------------
@@ -3000,25 +2480,22 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
 
                        epcaparam(tty,ch);
                        memoff(ch);
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&epca_lock, flags);
                        break;
 
                case DIGI_GETFLOW:
                case DIGI_GETAFLOW:
-                       cli();  
+                       spin_lock_irqsave(&epca_lock, flags);
                        globalwinon(ch);
-                       if ((cmd) == (DIGI_GETFLOW)) 
-                       {
-                               dflow.startc = bc->startc;
-                               dflow.stopc = bc->stopc;
-                       }
-                       else 
-                       {
-                               dflow.startc = bc->startca;
-                               dflow.stopc = bc->stopca;
+                       if (cmd == DIGI_GETFLOW) {
+                               dflow.startc = readb(&bc->startc);
+                               dflow.stopc = readb(&bc->stopc);
+                       } else {
+                               dflow.startc = readb(&bc->startca);
+                               dflow.stopc = readb(&bc->stopca);
                        }
                        memoff(ch);
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&epca_lock, flags);
 
                        if (copy_to_user(argp, &dflow, sizeof(dflow)))
                                return -EFAULT;
@@ -3026,13 +2503,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
 
                case DIGI_SETAFLOW:
                case DIGI_SETFLOW:
-                       if ((cmd) == (DIGI_SETFLOW)) 
-                       {
+                       if (cmd == DIGI_SETFLOW) {
                                startc = ch->startc;
                                stopc = ch->stopc;
-                       } 
-                       else 
-                       {
+                       } else {
                                startc = ch->startca;
                                stopc = ch->stopca;
                        }
@@ -3040,40 +2514,31 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                        if (copy_from_user(&dflow, argp, sizeof(dflow)))
                                return -EFAULT;
 
-                       if (dflow.startc != startc || dflow.stopc != stopc) 
-                       { /* Begin  if setflow toggled */
-                               cli();
+                       if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin  if setflow toggled */
+                               spin_lock_irqsave(&epca_lock, flags);
                                globalwinon(ch);
 
-                               if ((cmd) == (DIGI_SETFLOW)) 
-                               {
+                               if (cmd == DIGI_SETFLOW) {
                                        ch->fepstartc = ch->startc = dflow.startc;
                                        ch->fepstopc = ch->stopc = dflow.stopc;
                                        fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
-                               } 
-                               else 
-                               {
+                               } else {
                                        ch->fepstartca = ch->startca = dflow.startc;
                                        ch->fepstopca  = ch->stopca = dflow.stopc;
                                        fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
                                }
 
-                               if      (ch->statusflags & TXSTOPPED)
+                               if (ch->statusflags & TXSTOPPED)
                                        pc_start(tty);
 
                                memoff(ch);
-                               restore_flags(flags);
-
+                               spin_unlock_irqrestore(&epca_lock, flags);
                        } /* End if setflow toggled */
                        break;
-
                default:
                        return -ENOIOCTLCMD;
-
        } /* End switch cmd */
-
        return 0;
-
 } /* End pc_ioctl */
 
 /* --------------------- Begin pc_set_termios  ----------------------- */
@@ -3083,20 +2548,16 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
 
        struct channel *ch;
        unsigned long flags;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if channel valid */
-
-               save_flags(flags);
-               cli();
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if channel valid */
+               spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
                epcaparam(tty, ch);
                memoff(ch);
+               spin_unlock_irqrestore(&epca_lock, flags);
 
                if ((old_termios->c_cflag & CRTSCTS) &&
                         ((tty->termios->c_cflag & CRTSCTS) == 0))
@@ -3106,8 +2567,6 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
                         (tty->termios->c_cflag & CLOCAL))
                        wake_up_interruptible(&ch->open_wait);
 
-               restore_flags(flags);
-
        } /* End if channel valid */
 
 } /* End pc_set_termios */
@@ -3116,29 +2575,18 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
 
 static void do_softint(void *private_)
 { /* Begin do_softint */
-
        struct channel *ch = (struct channel *) private_;
-       
-
        /* Called in response to a modem change event */
-
-       if (ch && ch->magic == EPCA_MAGIC) 
-       { /* Begin EPCA_MAGIC */
-
+       if (ch && ch->magic == EPCA_MAGIC)  { /* Begin EPCA_MAGIC */
                struct tty_struct *tty = ch->tty;
 
-               if (tty && tty->driver_data) 
-               { 
-                       if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) 
-                       { /* Begin if clear_bit */
-
+               if (tty && tty->driver_data) {
+                       if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */
                                tty_hangup(tty);        /* FIXME: module removal race here - AKPM */
                                wake_up_interruptible(&ch->open_wait);
                                ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-
                        } /* End if clear_bit */
                }
-
        } /* End EPCA_MAGIC */
 } /* End do_softint */
 
@@ -3154,82 +2602,49 @@ static void pc_stop(struct tty_struct *tty)
 
        struct channel *ch;
        unsigned long flags;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if valid channel */
-
-               save_flags(flags); 
-               cli();
-
-               if ((ch->statusflags & TXSTOPPED) == 0) 
-               { /* Begin if transmit stop requested */
-
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if valid channel */
+               spin_lock_irqsave(&epca_lock, flags);
+               if ((ch->statusflags & TXSTOPPED) == 0)  { /* Begin if transmit stop requested */
                        globalwinon(ch);
-
                        /* STOP transmitting now !! */
-
                        fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-
                        ch->statusflags |= TXSTOPPED;
                        memoff(ch);
-
                } /* End if transmit stop requested */
-
-               restore_flags(flags);
-
+               spin_unlock_irqrestore(&epca_lock, flags);
        } /* End if valid channel */
-
 } /* End pc_stop */
 
 /* --------------------- Begin pc_start  ----------------------- */
 
 static void pc_start(struct tty_struct *tty)
 { /* Begin pc_start */
-
        struct channel *ch;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if channel valid */
-
+       if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
                unsigned long flags;
-
-               save_flags(flags);
-               cli();
-
+               spin_lock_irqsave(&epca_lock, flags);
                /* Just in case output was resumed because of a change in Digi-flow */
-               if (ch->statusflags & TXSTOPPED) 
-               { /* Begin transmit resume requested */
-
-                       volatile struct board_chan *bc;
-
+               if (ch->statusflags & TXSTOPPED)  { /* Begin transmit resume requested */
+                       struct board_chan *bc;
                        globalwinon(ch);
                        bc = ch->brdchan;
                        if (ch->statusflags & LOWWAIT)
-                               bc->ilow = 1;
-
+                               writeb(1, &bc->ilow);
                        /* Okay, you can start transmitting again... */
-
                        fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-
                        ch->statusflags &= ~TXSTOPPED;
                        memoff(ch);
-
                } /* End transmit resume requested */
-
-               restore_flags(flags);
-
+               spin_unlock_irqrestore(&epca_lock, flags);
        } /* End if channel valid */
-
 } /* End pc_start */
 
 /* ------------------------------------------------------------------
@@ -3244,86 +2659,55 @@ ______________________________________________________________________ */
 
 static void pc_throttle(struct tty_struct * tty)
 { /* Begin pc_throttle */
-
        struct channel *ch;
        unsigned long flags;
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if channel valid */
-
-
-               save_flags(flags);
-               cli();
-
-               if ((ch->statusflags & RXSTOPPED) == 0)
-               {
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if channel valid */
+               spin_lock_irqsave(&epca_lock, flags);
+               if ((ch->statusflags & RXSTOPPED) == 0) {
                        globalwinon(ch);
                        fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-
                        ch->statusflags |= RXSTOPPED;
                        memoff(ch);
                }
-               restore_flags(flags);
-
+               spin_unlock_irqrestore(&epca_lock, flags);
        } /* End if channel valid */
-
 } /* End pc_throttle */
 
 /* --------------------- Begin unthrottle  ----------------------- */
 
 static void pc_unthrottle(struct tty_struct *tty)
 { /* Begin pc_unthrottle */
-
        struct channel *ch;
        unsigned long flags;
-       volatile struct board_chan *bc;
-
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
        ------------------------------------------------------------- */
-
-       if ((ch = verifyChannel(tty)) != NULL) 
-       { /* Begin if channel valid */
-
-
+       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if channel valid */
                /* Just in case output was resumed because of a change in Digi-flow */
-               save_flags(flags);
-               cli();
-
-               if (ch->statusflags & RXSTOPPED) 
-               {
-
+               spin_lock_irqsave(&epca_lock, flags);
+               if (ch->statusflags & RXSTOPPED) {
                        globalwinon(ch);
-                       bc = ch->brdchan;
                        fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-
                        ch->statusflags &= ~RXSTOPPED;
                        memoff(ch);
                }
-               restore_flags(flags);
-
+               spin_unlock_irqrestore(&epca_lock, flags);
        } /* End if channel valid */
-
 } /* End pc_unthrottle */
 
 /* --------------------- Begin digi_send_break  ----------------------- */
 
 void digi_send_break(struct channel *ch, int msec)
 { /* Begin digi_send_break */
-
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
-
        /* -------------------------------------------------------------------- 
           Maybe I should send an infinite break here, schedule() for
           msec amount of time, and then stop the break.  This way,
@@ -3331,36 +2715,28 @@ void digi_send_break(struct channel *ch, int msec)
           to be called (i.e. via an ioctl()) more than once in msec amount 
           of time.  Try this for now...
        ------------------------------------------------------------------------ */
-
        fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
        memoff(ch);
-
-       restore_flags(flags);
-
+       spin_unlock_irqrestore(&epca_lock, flags);
 } /* End digi_send_break */
 
 /* --------------------- Begin setup_empty_event  ----------------------- */
 
+/* Caller MUST hold the lock */
+
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
 { /* Begin setup_empty_event */
 
-       volatile struct board_chan *bc = ch->brdchan;
-       unsigned long int flags;
+       struct board_chan *bc = ch->brdchan;
 
-       save_flags(flags);
-       cli();
        globalwinon(ch);
        ch->statusflags |= EMPTYWAIT;
-       
        /* ------------------------------------------------------------------
                When set the iempty flag request a event to be generated when the 
                transmit buffer is empty (If there is no BREAK in progress).
        --------------------------------------------------------------------- */
-
-       bc->iempty = 1;
+       writeb(1, &bc->iempty);
        memoff(ch);
-       restore_flags(flags);
-
 } /* End setup_empty_event */
 
 /* --------------------- Begin get_termio ----------------------- */
@@ -3369,10 +2745,10 @@ static int get_termio(struct tty_struct * tty, struct termio __user * termio)
 { /* Begin get_termio */
        return kernel_termios_to_user_termio(termio, tty->termios);
 } /* End get_termio */
+
 /* ---------------------- Begin epca_setup  -------------------------- */
 void epca_setup(char *str, int *ints)
 { /* Begin epca_setup */
-
        struct board_info board;
        int               index, loop, last;
        char              *temp, *t2;
@@ -3394,49 +2770,41 @@ void epca_setup(char *str, int *ints)
        for (last = 0, index = 1; index <= ints[0]; index++)
                switch(index)
                { /* Begin parse switch */
-
                        case 1:
                                board.status = ints[index];
-                               
                                /* ---------------------------------------------------------
                                        We check for 2 (As opposed to 1; because 2 is a flag
                                        instructing the driver to ignore epcaconfig.)  For this
                                        reason we check for 2.
                                ------------------------------------------------------------ */ 
-                               if (board.status == 2)
-                               { /* Begin ignore epcaconfig as well as lilo cmd line */
+                               if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
                                        nbdevs = 0;
                                        num_cards = 0;
                                        return;
                                } /* End ignore epcaconfig as well as lilo cmd line */
        
-                               if (board.status > 2)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid board status 0x%x\n", board.status);
+                               if (board.status > 2) {
+                                       printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_BOARD_STATUS;
                                        return;
                                }
                                last = index;
                                break;
-
                        case 2:
                                board.type = ints[index];
-                               if (board.type >= PCIXEM) 
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid board type 0x%x\n", board.type);
+                               if (board.type >= PCIXEM)  {
+                                       printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_BOARD_TYPE;
                                        return;
                                }
                                last = index;
                                break;
-
                        case 3:
                                board.altpin = ints[index];
-                               if (board.altpin > 1)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid board altpin 0x%x\n", board.altpin);
+                               if (board.altpin > 1) {
+                                       printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_ALTPIN;
                                        return;
@@ -3446,9 +2814,8 @@ void epca_setup(char *str, int *ints)
 
                        case 4:
                                board.numports = ints[index];
-                               if ((board.numports < 2) || (board.numports > 256))
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid board numports 0x%x\n", board.numports);
+                               if (board.numports < 2 || board.numports > 256) {
+                                       printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_NUM_PORTS;
                                        return;
@@ -3458,10 +2825,9 @@ void epca_setup(char *str, int *ints)
                                break;
 
                        case 5:
-                               board.port = (unsigned char *)ints[index];
-                               if (ints[index] <= 0)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
+                               board.port = ints[index];
+                               if (ints[index] <= 0) {
+                                       printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_PORT_BASE;
                                        return;
@@ -3470,10 +2836,9 @@ void epca_setup(char *str, int *ints)
                                break;
 
                        case 6:
-                               board.membase = (unsigned char *)ints[index];
-                               if (ints[index] <= 0)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+                               board.membase = ints[index];
+                               if (ints[index] <= 0) {
+                                       printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_MEM_BASE;
                                        return;
@@ -3487,21 +2852,16 @@ void epca_setup(char *str, int *ints)
 
                } /* End parse switch */
 
-       while (str && *str) 
-       { /* Begin while there is a string arg */
-
+       while (str && *str)  { /* Begin while there is a string arg */
                /* find the next comma or terminator */
                temp = str;
-
                /* While string is not null, and a comma hasn't been found */
                while (*temp && (*temp != ','))
                        temp++;
-
                if (!*temp)
                        temp = NULL;
                else
                        *temp++ = 0;
-
                /* Set index to the number of args + 1 */
                index = last + 1;
 
@@ -3511,12 +2871,10 @@ void epca_setup(char *str, int *ints)
                                len = strlen(str);
                                if (strncmp("Disable", str, len) == 0) 
                                        board.status = 0;
-                               else
-                               if (strncmp("Enable", str, len) == 0)
+                               else if (strncmp("Enable", str, len) == 0)
                                        board.status = 1;
-                               else
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid status %s\n", str);
+                               else {
+                                       printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_BOARD_STATUS;
                                        return;
@@ -3525,22 +2883,17 @@ void epca_setup(char *str, int *ints)
                                break;
 
                        case 2:
-
                                for(loop = 0; loop < EPCA_NUM_TYPES; loop++)
                                        if (strcmp(board_desc[loop], str) == 0)
                                                break;
-
-
                                /* ---------------------------------------------------------------
                                        If the index incremented above refers to a legitamate board 
                                        type set it here. 
                                ------------------------------------------------------------------*/
-
                                if (index < EPCA_NUM_TYPES) 
                                        board.type = loop;
-                               else
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid board type: %s\n", str);
+                               else {
+                                       printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_BOARD_TYPE;
                                        return;
@@ -3552,12 +2905,10 @@ void epca_setup(char *str, int *ints)
                                len = strlen(str);
                                if (strncmp("Disable", str, len) == 0) 
                                        board.altpin = 0;
-                               else
-                               if (strncmp("Enable", str, len) == 0)
+                               else if (strncmp("Enable", str, len) == 0)
                                        board.altpin = 1;
-                               else
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid altpin %s\n", str);
+                               else {
+                                       printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_ALTPIN;
                                        return;
@@ -3570,9 +2921,8 @@ void epca_setup(char *str, int *ints)
                                while (isdigit(*t2))
                                        t2++;
 
-                               if (*t2)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid port count %s\n", str);
+                               if (*t2) {
+                                       printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_NUM_PORTS;
                                        return;
@@ -3601,15 +2951,14 @@ void epca_setup(char *str, int *ints)
                                while (isxdigit(*t2))
                                        t2++;
 
-                               if (*t2)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid i/o address %s\n", str);
+                               if (*t2) {
+                                       printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_PORT_BASE;
                                        return;
                                }
 
-                               board.port = (unsigned char *)simple_strtoul(str, NULL, 16);
+                               board.port = simple_strtoul(str, NULL, 16);
                                last = index;
                                break;
 
@@ -3618,52 +2967,38 @@ void epca_setup(char *str, int *ints)
                                while (isxdigit(*t2))
                                        t2++;
 
-                               if (*t2)
-                               {
-                                       printk(KERN_ERR "<Error> - epca_setup: Invalid memory base %s\n",str);
+                               if (*t2) {
+                                       printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
                                        invalid_lilo_config = 1;
                                        setup_error_code |= INVALID_MEM_BASE;
                                        return;
                                }
-
-                               board.membase = (unsigned char *)simple_strtoul(str, NULL, 16);
+                               board.membase = simple_strtoul(str, NULL, 16);
                                last = index;
                                break;
-
                        default:
-                               printk(KERN_ERR "PC/Xx: Too many string parms\n");
+                               printk(KERN_ERR "epca: Too many string parms\n");
                                return;
                }
                str = temp;
-
        } /* End while there is a string arg */
 
-
-       if (last < 6)  
-       {
-               printk(KERN_ERR "PC/Xx: Insufficient parms specified\n");
+       if (last < 6) {
+               printk(KERN_ERR "epca: Insufficient parms specified\n");
                return;
        }
  
        /* I should REALLY validate the stuff here */
-
        /* Copies our local copy of board into boards */
        memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
-
-
        /* Does this get called once per lilo arg are what ? */
-
        printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", 
                num_cards, board_desc[board.type], 
                board.numports, (int)board.port, (unsigned int) board.membase);
-
        num_cards++;
-
 } /* End epca_setup */
 
 
-
-#ifdef ENABLE_PCI
 /* ------------------------ Begin init_PCI  --------------------------- */
 
 enum epic_board_types {
@@ -3685,7 +3020,6 @@ static struct {
        { PCIXRJ, 2, },
 };
 
-
 static int __devinit epca_init_one (struct pci_dev *pdev,
                                 const struct pci_device_id *ent)
 {
@@ -3711,10 +3045,8 @@ static int __devinit epca_init_one (struct pci_dev *pdev,
        boards[board_idx].status = ENABLED;
        boards[board_idx].type = epca_info_tbl[info_idx].board_type;
        boards[board_idx].numports = 0x0;
-       boards[board_idx].port =
-               (unsigned char *)((char *) addr + PCI_IO_OFFSET);
-       boards[board_idx].membase =
-               (unsigned char *)((char *) addr);
+       boards[board_idx].port = addr + PCI_IO_OFFSET;
+       boards[board_idx].membase = addr;
 
        if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
                printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
@@ -3775,15 +3107,13 @@ static struct pci_device_id epca_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
 
 int __init init_PCI (void)
-{ /* Begin init_PCI */
+{      /* Begin init_PCI */
        memset (&epca_driver, 0, sizeof (epca_driver));
        epca_driver.name = "epca";
        epca_driver.id_table = epca_pci_tbl;
        epca_driver.probe = epca_init_one;
 
        return pci_register_driver(&epca_driver);
-} /* End init_PCI */
-
-#endif /* ENABLE_PCI */
+}
 
 MODULE_LICENSE("GPL");
index 52205ef7131483ae59a17a0220c3803fe0939741..20eeb5a70e1ad841c9b73490df25d82d6c7f8786 100644 (file)
@@ -85,73 +85,73 @@ static char *board_desc[] =
 struct channel 
 {
        long   magic;
-       unchar boardnum;
-       unchar channelnum;
-       unchar omodem;         /* FEP output modem status     */
-       unchar imodem;         /* FEP input modem status      */
-       unchar modemfake;      /* Modem values to be forced   */
-       unchar modem;          /* Force values                */
-       unchar hflow;
-       unchar dsr;
-       unchar dcd;
-       unchar m_rts ;          /* The bits used in whatever FEP */
-       unchar m_dcd ;          /* is indiginous to this board to */
-       unchar m_dsr ;          /* represent each of the physical */
-       unchar m_cts ;          /* handshake lines */
-       unchar m_ri ;
-       unchar m_dtr ;
-       unchar stopc;
-       unchar startc;
-       unchar stopca;
-       unchar startca;
-       unchar fepstopc;
-       unchar fepstartc;
-       unchar fepstopca;
-       unchar fepstartca;
-       unchar txwin;
-       unchar rxwin;
-       ushort fepiflag;
-       ushort fepcflag;
-       ushort fepoflag;
-       ushort txbufhead;
-       ushort txbufsize;
-       ushort rxbufhead;
-       ushort rxbufsize;
+       unsigned char boardnum;
+       unsigned char channelnum;
+       unsigned char omodem;         /* FEP output modem status     */
+       unsigned char imodem;         /* FEP input modem status      */
+       unsigned char modemfake;      /* Modem values to be forced   */
+       unsigned char modem;          /* Force values                */
+       unsigned char hflow;
+       unsigned char dsr;
+       unsigned char dcd;
+       unsigned char m_rts ;           /* The bits used in whatever FEP */
+       unsigned char m_dcd ;           /* is indiginous to this board to */
+       unsigned char m_dsr ;           /* represent each of the physical */
+       unsigned char m_cts ;           /* handshake lines */
+       unsigned char m_ri ;
+       unsigned char m_dtr ;
+       unsigned char stopc;
+       unsigned char startc;
+       unsigned char stopca;
+       unsigned char startca;
+       unsigned char fepstopc;
+       unsigned char fepstartc;
+       unsigned char fepstopca;
+       unsigned char fepstartca;
+       unsigned char txwin;
+       unsigned char rxwin;
+       unsigned short fepiflag;
+       unsigned short fepcflag;
+       unsigned short fepoflag;
+       unsigned short txbufhead;
+       unsigned short txbufsize;
+       unsigned short rxbufhead;
+       unsigned short rxbufsize;
        int    close_delay;
        int    count;
        int    blocked_open;
-       ulong  event;
+       unsigned long  event;
        int    asyncflags;
        uint   dev;
-       ulong  statusflags;
-       ulong  c_iflag;
-       ulong  c_cflag;
-       ulong  c_lflag;
-       ulong  c_oflag;
-       unchar *txptr;
-       unchar *rxptr;
-       unchar *tmp_buf;
+       unsigned long  statusflags;
+       unsigned long  c_iflag;
+       unsigned long  c_cflag;
+       unsigned long  c_lflag;
+       unsigned long  c_oflag;
+       unsigned char *txptr;
+       unsigned char *rxptr;
+       unsigned char *tmp_buf;
        struct board_info           *board;
-       volatile struct board_chan  *brdchan;
+       struct board_chan           *brdchan;
        struct digi_struct          digiext;
        struct tty_struct           *tty;
        wait_queue_head_t           open_wait;
        wait_queue_head_t           close_wait;
-       struct work_struct            tqueue;
-       volatile struct global_data *mailbox;
+       struct work_struct          tqueue;
+       struct global_data          *mailbox;
 };
 
 struct board_info      
 {
-       unchar status;
-       unchar type;
-       unchar altpin;
-       ushort numports;
-       unchar *port;
-       unchar *membase;
-       unchar __iomem *re_map_port;
-       unchar *re_map_membase;
-       ulong  memory_seg;
+       unsigned char status;
+       unsigned char type;
+       unsigned char altpin;
+       unsigned short numports;
+       unsigned long port;
+       unsigned long membase;
+       unsigned char __iomem *re_map_port;
+       unsigned char *re_map_membase;
+       unsigned long  memory_seg;
        void ( * memwinon )     (struct board_info *, unsigned int) ;
        void ( * memwinoff )    (struct board_info *, unsigned int) ;
        void ( * globalwinon )  (struct channel *) ;
@@ -160,6 +160,6 @@ struct board_info
        void ( * memoff )       (struct channel *) ;
        void ( * assertgwinon ) (struct channel *) ;
        void ( * assertmemoff ) (struct channel *) ;
-       unchar poller_inhibited ;
+       unsigned char poller_inhibited ;
 };
 
index 762fa430fb5be3b6a7615eed705e741509475ba7..a695f25e4497b647cb20c776f1f2f0a0e6b4d545 100644 (file)
@@ -44,7 +44,7 @@
 /*
  * The High Precision Event Timer driver.
  * This driver is closely modelled after the rtc.c driver.
- * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
+ * http://www.intel.com/hardwaredesign/hpetspec.htm
  */
 #define        HPET_USER_FREQ  (64)
 #define        HPET_DRIFT      (500)
@@ -712,7 +712,7 @@ static void hpet_register_interpolator(struct hpets *hpetp)
        ti->shift = 10;
        ti->addr = &hpetp->hp_hpet->hpet_mc;
        ti->frequency = hpet_time_div(hpets->hp_period);
-       ti->drift = ti->frequency * HPET_DRIFT / 1000000;
+       ti->drift = HPET_DRIFT;
        ti->mask = -1;
 
        hpetp->hp_interpolator = ti;
index 5ce9c62690334cdf50ada526ec2c2a123b087849..33862670e285542fe7f4733fc299aef0346db31c 100644 (file)
@@ -31,8 +31,6 @@
 #include <linux/ipmi_msgdefs.h>                /* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_BT_VERSION "v33"
-
 static int bt_debug = 0x00;    /* Production value 0, see following flags */
 
 #define        BT_DEBUG_ENABLE 1
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
 {
        unsigned int i;
 
-       if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1;
+       if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+              return -1;
 
        if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
                return -2;
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
        if (bt_debug & BT_DEBUG_MSG) {
                printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
                printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
-               for (i = 0; i < size; i ++) printk (" %02x", data[i]);
+               for (i = 0; i < size; i ++)
+                      printk (" %02x", data[i]);
                printk("\n");
        }
        bt->write_data[0] = size + 1;   /* all data plus seq byte */
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt,
        } else {
                data[0] = bt->read_data[1];
                data[1] = bt->read_data[3];
-               if (length < msg_len) bt->truncated = 1;
+               if (length < msg_len)
+                      bt->truncated = 1;
                if (bt->truncated) {    /* can be set in read_all_bytes() */
                        data[2] = IPMI_ERR_MSG_TRUNCATED;
                        msg_len = 3;
-               } else memcpy(data + 2, bt->read_data + 4, msg_len - 2);
+               } else
+                      memcpy(data + 2, bt->read_data + 4, msg_len - 2);
 
                if (bt_debug & BT_DEBUG_MSG) {
                        printk (KERN_WARNING "BT: res (raw)");
-                       for (i = 0; i < msg_len; i++) printk(" %02x", data[i]);
+                       for (i = 0; i < msg_len; i++)
+                              printk(" %02x", data[i]);
                        printk ("\n");
                }
        }
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt,
 
 static void reset_flags(struct si_sm_data *bt)
 {
-       if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY);
-       if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
+       if (BT_STATUS & BT_H_BUSY)
+              BT_CONTROL(BT_H_BUSY);
+       if (BT_STATUS & BT_B_BUSY)
+              BT_CONTROL(BT_B_BUSY);
        BT_CONTROL(BT_CLR_WR_PTR);
        BT_CONTROL(BT_SMS_ATN);
 #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt)
                BT_CONTROL(BT_H_BUSY);
                BT_CONTROL(BT_B2H_ATN);
                BT_CONTROL(BT_CLR_RD_PTR);
-               for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST;
+               for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++)
+                      BMC2HOST;
                BT_CONTROL(BT_H_BUSY);
        }
 #endif
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt)
                        printk (" %02x", bt->write_data[i]);
                printk ("\n");
        }
-       for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]);
+       for (i = 0; i < bt->write_count; i++)
+              HOST2BMC(bt->write_data[i]);
 }
 
 static inline int read_all_bytes(struct si_sm_data *bt)
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
                bt->truncated = 1;
                return 1;       /* let next XACTION START clean it up */
        }
-       for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST;
+       for (i = 1; i <= bt->read_count; i++)
+              bt->read_data[i] = BMC2HOST;
        bt->read_count++;       /* account for the length byte */
 
        if (bt_debug & BT_DEBUG_MSG) {
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
                ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
                        return 1;
 
-       if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: "
+       if (bt_debug & BT_DEBUG_MSG)
+              printk(KERN_WARNING "BT: bad packet: "
                "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
                bt->write_data[1], bt->write_data[2], bt->write_data[3],
                bt->read_data[1],  bt->read_data[2],  bt->read_data[3]);
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                        time);
        bt->last_state = bt->state;
 
-       if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED;
+       if (bt->state == BT_STATE_HOSED)
+              return SI_SM_HOSED;
 
        if (bt->state != BT_STATE_IDLE) {       /* do timeout test */
 
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
        /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
               (noticed in ipmi_smic_sm.c January 2004) */
 
-               if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100;
+               if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
+                      time = 100;
                bt->timeout -= time;
                if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
                        error_recovery(bt, "timed out");
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                        BT_CONTROL(BT_H_BUSY);
                        break;
                }
-               if (status & BT_B2H_ATN) break;
+               if (status & BT_B2H_ATN)
+                      break;
                bt->state = BT_STATE_WRITE_BYTES;
                return SI_SM_CALL_WITHOUT_DELAY;        /* for logging */
 
        case BT_STATE_WRITE_BYTES:
-               if (status & (BT_B_BUSY | BT_H2B_ATN)) break;
+               if (status & (BT_B_BUSY | BT_H2B_ATN))
+                      break;
                BT_CONTROL(BT_CLR_WR_PTR);
                write_all_bytes(bt);
                BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
 
        case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
-               if (status & (BT_H2B_ATN | BT_B_BUSY)) break;
+               if (status & (BT_H2B_ATN | BT_B_BUSY))
+                      break;
                bt->state = BT_STATE_B2H_WAIT;
                /* fall through with status */
 
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
           generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
 
        case BT_STATE_B2H_WAIT:
-               if (!(status & BT_B2H_ATN)) break;
+               if (!(status & BT_B2H_ATN))
+                      break;
 
                /* Assume ordered, uncached writes: no need to wait */
-               if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */
+               if (!(status & BT_H_BUSY))
+                      BT_CONTROL(BT_H_BUSY); /* set */
                BT_CONTROL(BT_B2H_ATN);         /* clear it, ACK to the BMC */
                BT_CONTROL(BT_CLR_RD_PTR);      /* reset the queue */
                i = read_all_bytes(bt);
                BT_CONTROL(BT_H_BUSY);          /* clear */
-               if (!i) break;                  /* Try this state again */
+               if (!i)                         /* Try this state again */
+                      break;
                bt->state = BT_STATE_READ_END;
                return SI_SM_CALL_WITHOUT_DELAY;        /* for logging */
 
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
 
 #ifdef MAKE_THIS_TRUE_IF_NECESSARY
 
-               if (status & BT_H_BUSY) break;
+               if (status & BT_H_BUSY)
+                      break;
 #endif
                bt->seq++;
                bt->state = BT_STATE_IDLE;
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                break;
 
        case BT_STATE_RESET3:
-               if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY;
+               if (bt->timeout > 0)
+                      return SI_SM_CALL_WITH_DELAY;
                bt->state = BT_STATE_RESTART;   /* printk in debug modes */
                break;
 
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt)
           but that's what you get from reading a bogus address, so we
           test that first.  The calling routine uses negative logic. */
 
-       if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1;
+       if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
+              return 1;
        reset_flags(bt);
        return 0;
 }
@@ -501,7 +521,6 @@ static int bt_size(void)
 
 struct si_sm_handlers bt_smi_handlers =
 {
-       .version           = IPMI_BT_VERSION,
        .init_data         = bt_init_data,
        .start_transaction = bt_start_transaction,
        .get_result        = bt_get_result,
index e0a53570fea1a755485a90f1aa59c8778d753b26..883ac4352be49e4e1606e361d763a8503199a058 100644 (file)
@@ -47,8 +47,6 @@
 #include <linux/device.h>
 #include <linux/compat.h>
 
-#define IPMI_DEVINTF_VERSION "v33"
-
 struct ipmi_file_private
 {
        ipmi_user_t          user;
@@ -411,6 +409,7 @@ static int ipmi_ioctl(struct inode  *inode,
                break;
        }
 
+       /* The next four are legacy, not per-channel. */
        case IPMICTL_SET_MY_ADDRESS_CMD:
        {
                unsigned int val;
@@ -420,22 +419,25 @@ static int ipmi_ioctl(struct inode  *inode,
                        break;
                }
 
-               ipmi_set_my_address(priv->user, val);
-               rv = 0;
+               rv = ipmi_set_my_address(priv->user, 0, val);
                break;
        }
 
        case IPMICTL_GET_MY_ADDRESS_CMD:
        {
-               unsigned int val;
+               unsigned int  val;
+               unsigned char rval;
+
+               rv = ipmi_get_my_address(priv->user, 0, &rval);
+               if (rv)
+                       break;
 
-               val = ipmi_get_my_address(priv->user);
+               val = rval;
 
                if (copy_to_user(arg, &val, sizeof(val))) {
                        rv = -EFAULT;
                        break;
                }
-               rv = 0;
                break;
        }
 
@@ -448,24 +450,94 @@ static int ipmi_ioctl(struct inode  *inode,
                        break;
                }
 
-               ipmi_set_my_LUN(priv->user, val);
-               rv = 0;
+               rv = ipmi_set_my_LUN(priv->user, 0, val);
                break;
        }
 
        case IPMICTL_GET_MY_LUN_CMD:
        {
-               unsigned int val;
+               unsigned int  val;
+               unsigned char rval;
 
-               val = ipmi_get_my_LUN(priv->user);
+               rv = ipmi_get_my_LUN(priv->user, 0, &rval);
+               if (rv)
+                       break;
+
+               val = rval;
+
+               if (copy_to_user(arg, &val, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               break;
+       }
+
+       case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
+       {
+               struct ipmi_channel_lun_address_set val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               return ipmi_set_my_address(priv->user, val.channel, val.value);
+               break;
+       }
+
+       case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
+       {
+               struct ipmi_channel_lun_address_set val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
+               if (rv)
+                       break;
+
+               if (copy_to_user(arg, &val, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               break;
+       }
+
+       case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
+       {
+               struct ipmi_channel_lun_address_set val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
+               break;
+       }
+
+       case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
+       {
+               struct ipmi_channel_lun_address_set val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
+               if (rv)
+                       break;
 
                if (copy_to_user(arg, &val, sizeof(val))) {
                        rv = -EFAULT;
                        break;
                }
-               rv = 0;
                break;
        }
+
        case IPMICTL_SET_TIMING_PARMS_CMD:
        {
                struct ipmi_timing_parms parms;
@@ -748,8 +820,7 @@ static __init int init_ipmi_devintf(void)
        if (ipmi_major < 0)
                return -EINVAL;
 
-       printk(KERN_INFO "ipmi device interface version "
-              IPMI_DEVINTF_VERSION "\n");
+       printk(KERN_INFO "ipmi device interface\n");
 
        ipmi_class = class_create(THIS_MODULE, "ipmi");
        if (IS_ERR(ipmi_class)) {
@@ -792,3 +863,5 @@ static __exit void cleanup_ipmi(void)
 module_exit(cleanup_ipmi);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
index 48cce24329bea516b62a0f3578ea162a48b73556..d21853a594a3b74c2354988d523f8cdd0bbcf71d 100644 (file)
@@ -42,8 +42,6 @@
 #include <linux/ipmi_msgdefs.h>                /* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_KCS_VERSION "v33"
-
 /* Set this if you want a printout of why the state machine was hosed
    when it gets hosed. */
 #define DEBUG_HOSED_REASON
@@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs)
 
 struct si_sm_handlers kcs_smi_handlers =
 {
-       .version           = IPMI_KCS_VERSION,
        .init_data         = init_kcs_data,
        .start_transaction = start_kcs_transaction,
        .get_result        = get_kcs_result,
index e16c13fe698dff7c71ad27508d64904f84be80be..463351d4f9423c388d424231326b8bbe23a60cd0 100644 (file)
@@ -47,7 +47,8 @@
 #include <linux/proc_fs.h>
 
 #define PFX "IPMI message handler: "
-#define IPMI_MSGHANDLER_VERSION "v33"
+
+#define IPMI_DRIVER_VERSION "36.0"
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -116,7 +117,7 @@ struct seq_table
        do {                                                            \
                seq = ((msgid >> 26) & 0x3f);                           \
                seqid = (msgid & 0x3fffff);                             \
-        } while(0)
+        } while (0)
 
 #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
 
@@ -124,6 +125,14 @@ struct ipmi_channel
 {
        unsigned char medium;
        unsigned char protocol;
+
+       /* My slave address.  This is initialized to IPMI_BMC_SLAVE_ADDR,
+          but may be changed by the user. */
+       unsigned char address;
+
+       /* My LUN.  This should generally stay the SMS LUN, but just in
+          case... */
+       unsigned char lun;
 };
 
 #ifdef CONFIG_PROC_FS
@@ -135,7 +144,7 @@ struct ipmi_proc_entry
 #endif
 
 #define IPMI_IPMB_NUM_SEQ      64
-#define IPMI_MAX_CHANNELS       8
+#define IPMI_MAX_CHANNELS       16
 struct ipmi_smi
 {
        /* What interface number are we? */
@@ -193,20 +202,6 @@ struct ipmi_smi
        struct list_head waiting_events;
        unsigned int     waiting_events_count; /* How many events in queue? */
 
-       /* This will be non-null if someone registers to receive all
-          IPMI commands (this is for interface emulation).  There
-          may not be any things in the cmd_rcvrs list above when
-          this is registered. */
-       ipmi_user_t all_cmd_rcvr;
-
-       /* My slave address.  This is initialized to IPMI_BMC_SLAVE_ADDR,
-          but may be changed by the user. */
-       unsigned char my_address;
-
-       /* My LUN.  This should generally stay the SMS LUN, but just in
-          case... */
-       unsigned char my_lun;
-
        /* The event receiver for my BMC, only really used at panic
           shutdown as a place to store this. */
        unsigned char event_receiver;
@@ -218,7 +213,7 @@ struct ipmi_smi
           interface comes in with a NULL user, call this routine with
           it.  Note that the message will still be freed by the
           caller.  This only works on the system interface. */
-       void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
+       void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);
 
        /* When we are scanning the channels for an SMI, this will
           tell which channel we are scanning. */
@@ -325,7 +320,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
        down_read(&interfaces_sem);
        down_write(&smi_watchers_sem);
        list_add(&(watcher->link), &smi_watchers);
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                if (ipmi_interfaces[i] != NULL) {
                        watcher->new_smi(i);
                }
@@ -458,7 +453,27 @@ unsigned int ipmi_addr_length(int addr_type)
 
 static void deliver_response(struct ipmi_recv_msg *msg)
 {
-       msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
+       if (! msg->user) {
+               ipmi_smi_t    intf = msg->user_msg_data;
+               unsigned long flags;
+
+               /* Special handling for NULL users. */
+               if (intf->null_user_handler) {
+                       intf->null_user_handler(intf, msg);
+                       spin_lock_irqsave(&intf->counter_lock, flags);
+                       intf->handled_local_responses++;
+                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+               } else {
+                       /* No handler, so give up. */
+                       spin_lock_irqsave(&intf->counter_lock, flags);
+                       intf->unhandled_local_responses++;
+                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+               }
+               ipmi_free_recv_msg(msg);
+       } else {
+               msg->user->handler->ipmi_recv_hndl(msg,
+                                                  msg->user->handler_data);
+       }
 }
 
 /* Find the next sequence number not being used and add the given
@@ -475,9 +490,9 @@ static int intf_next_seq(ipmi_smi_t           intf,
        int          rv = 0;
        unsigned int i;
 
-       for (i=intf->curr_seq;
+       for (i = intf->curr_seq;
             (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
-            i=(i+1)%IPMI_IPMB_NUM_SEQ)
+            i = (i+1)%IPMI_IPMB_NUM_SEQ)
        {
                if (! intf->seq_table[i].inuse)
                        break;
@@ -712,7 +727,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user)
 
        /* Remove the user from the interfaces sequence table. */
        spin_lock_irqsave(&(user->intf->seq_lock), flags);
-       for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+       for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
                if (user->intf->seq_table[i].inuse
                    && (user->intf->seq_table[i].recv_msg->user == user))
                {
@@ -766,26 +781,44 @@ void ipmi_get_version(ipmi_user_t   user,
        *minor = user->intf->version_minor;
 }
 
-void ipmi_set_my_address(ipmi_user_t   user,
-                        unsigned char address)
+int ipmi_set_my_address(ipmi_user_t   user,
+                       unsigned int  channel,
+                       unsigned char address)
 {
-       user->intf->my_address = address;
+       if (channel >= IPMI_MAX_CHANNELS)
+               return -EINVAL;
+       user->intf->channels[channel].address = address;
+       return 0;
 }
 
-unsigned char ipmi_get_my_address(ipmi_user_t user)
+int ipmi_get_my_address(ipmi_user_t   user,
+                       unsigned int  channel,
+                       unsigned char *address)
 {
-       return user->intf->my_address;
+       if (channel >= IPMI_MAX_CHANNELS)
+               return -EINVAL;
+       *address = user->intf->channels[channel].address;
+       return 0;
 }
 
-void ipmi_set_my_LUN(ipmi_user_t   user,
-                    unsigned char LUN)
+int ipmi_set_my_LUN(ipmi_user_t   user,
+                   unsigned int  channel,
+                   unsigned char LUN)
 {
-       user->intf->my_lun = LUN & 0x3;
+       if (channel >= IPMI_MAX_CHANNELS)
+               return -EINVAL;
+       user->intf->channels[channel].lun = LUN & 0x3;
+       return 0;
 }
 
-unsigned char ipmi_get_my_LUN(ipmi_user_t user)
+int ipmi_get_my_LUN(ipmi_user_t   user,
+                   unsigned int  channel,
+                   unsigned char *address)
 {
-       return user->intf->my_lun;
+       if (channel >= IPMI_MAX_CHANNELS)
+               return -EINVAL;
+       *address = user->intf->channels[channel].lun;
+       return 0;
 }
 
 int ipmi_set_gets_events(ipmi_user_t user, int val)
@@ -828,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
 
        read_lock(&(user->intf->users_lock));
        write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
-       if (user->intf->all_cmd_rcvr != NULL) {
-               rv = -EBUSY;
-               goto out_unlock;
-       }
-
        /* Make sure the command/netfn is not already registered. */
        list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {
                if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
@@ -847,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
                rcvr->user = user;
                list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
        }
- out_unlock:
+
        write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
        read_unlock(&(user->intf->users_lock));
 
@@ -1213,7 +1241,7 @@ static inline int i_ipmi_request(ipmi_user_t          user,
                unsigned char         ipmb_seq;
                long                  seqid;
 
-               if (addr->channel > IPMI_NUM_CHANNELS) {
+               if (addr->channel >= IPMI_NUM_CHANNELS) {
                        spin_lock_irqsave(&intf->counter_lock, flags);
                        intf->sent_invalid_commands++;
                        spin_unlock_irqrestore(&intf->counter_lock, flags);
@@ -1331,7 +1359,7 @@ static inline int i_ipmi_request(ipmi_user_t          user,
 #ifdef DEBUG_MSGING
        {
                int m;
-               for (m=0; m<smi_msg->data_size; m++)
+               for (m = 0; m < smi_msg->data_size; m++)
                        printk(" %2.2x", smi_msg->data[m]);
                printk("\n");
        }
@@ -1346,6 +1374,18 @@ static inline int i_ipmi_request(ipmi_user_t          user,
        return rv;
 }
 
+static int check_addr(ipmi_smi_t       intf,
+                     struct ipmi_addr *addr,
+                     unsigned char    *saddr,
+                     unsigned char    *lun)
+{
+       if (addr->channel >= IPMI_MAX_CHANNELS)
+               return -EINVAL;
+       *lun = intf->channels[addr->channel].lun;
+       *saddr = intf->channels[addr->channel].address;
+       return 0;
+}
+
 int ipmi_request_settime(ipmi_user_t      user,
                         struct ipmi_addr *addr,
                         long             msgid,
@@ -1355,6 +1395,14 @@ int ipmi_request_settime(ipmi_user_t      user,
                         int              retries,
                         unsigned int     retry_time_ms)
 {
+       unsigned char saddr, lun;
+       int           rv;
+
+       if (! user)
+               return -EINVAL;
+       rv = check_addr(user->intf, addr, &saddr, &lun);
+       if (rv)
+               return rv;
        return i_ipmi_request(user,
                              user->intf,
                              addr,
@@ -1363,8 +1411,8 @@ int ipmi_request_settime(ipmi_user_t      user,
                              user_msg_data,
                              NULL, NULL,
                              priority,
-                             user->intf->my_address,
-                             user->intf->my_lun,
+                             saddr,
+                             lun,
                              retries,
                              retry_time_ms);
 }
@@ -1378,6 +1426,14 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                             struct ipmi_recv_msg *supplied_recv,
                             int                  priority)
 {
+       unsigned char saddr, lun;
+       int           rv;
+
+       if (! user)
+               return -EINVAL;
+       rv = check_addr(user->intf, addr, &saddr, &lun);
+       if (rv)
+               return rv;
        return i_ipmi_request(user,
                              user->intf,
                              addr,
@@ -1387,8 +1443,8 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                              supplied_smi,
                              supplied_recv,
                              priority,
-                             user->intf->my_address,
-                             user->intf->my_lun,
+                             saddr,
+                             lun,
                              -1, 0);
 }
 
@@ -1397,8 +1453,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off,
 {
        char       *out = (char *) page;
        ipmi_smi_t intf = data;
+       int        i;
+       int        rv= 0;
 
-       return sprintf(out, "%x\n", intf->my_address);
+       for (i = 0; i < IPMI_MAX_CHANNELS; i++)
+               rv += sprintf(out+rv, "%x ", intf->channels[i].address);
+       out[rv-1] = '\n'; /* Replace the final space with a newline */
+       out[rv] = '\0';
+       rv++;
+       return rv;
 }
 
 static int version_file_read_proc(char *page, char **start, off_t off,
@@ -1588,29 +1651,30 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan)
                              (struct ipmi_addr *) &si,
                              0,
                              &msg,
-                             NULL,
+                             intf,
                              NULL,
                              NULL,
                              0,
-                             intf->my_address,
-                             intf->my_lun,
+                             intf->channels[0].address,
+                             intf->channels[0].lun,
                              -1, 0);
 }
 
 static void
-channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
 {
        int rv = 0;
        int chan;
 
-       if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
-           && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD))
+       if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+           && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+           && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
        {
                /* It's the one we want */
-               if (msg->rsp[2] != 0) {
+               if (msg->msg.data[0] != 0) {
                        /* Got an error from the channel, just go on. */
 
-                       if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {
+                       if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
                                /* If the MC does not support this
                                   command, that is legal.  We just
                                   assume it has one IPMB at channel
@@ -1627,13 +1691,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
                        }
                        goto next_channel;
                }
-               if (msg->rsp_size < 6) {
+               if (msg->msg.data_len < 4) {
                        /* Message not big enough, just go on. */
                        goto next_channel;
                }
                chan = intf->curr_channel;
-               intf->channels[chan].medium = msg->rsp[4] & 0x7f;
-               intf->channels[chan].protocol = msg->rsp[5] & 0x1f;
+               intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
+               intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
 
        next_channel:
                intf->curr_channel++;
@@ -1691,22 +1755,24 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        rv = -ENOMEM;
 
        down_write(&interfaces_sem);
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                if (ipmi_interfaces[i] == NULL) {
                        new_intf->intf_num = i;
                        new_intf->version_major = version_major;
                        new_intf->version_minor = version_minor;
-                       if (slave_addr == 0)
-                               new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
-                       else
-                               new_intf->my_address = slave_addr;
-                       new_intf->my_lun = 2;  /* the SMS LUN. */
+                       for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
+                               new_intf->channels[j].address
+                                       = IPMI_BMC_SLAVE_ADDR;
+                               new_intf->channels[j].lun = 2;
+                       }
+                       if (slave_addr != 0)
+                               new_intf->channels[0].address = slave_addr;
                        rwlock_init(&(new_intf->users_lock));
                        INIT_LIST_HEAD(&(new_intf->users));
                        new_intf->handlers = handlers;
                        new_intf->send_info = send_info;
                        spin_lock_init(&(new_intf->seq_lock));
-                       for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+                       for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
                                new_intf->seq_table[j].inuse = 0;
                                new_intf->seq_table[j].seqid = 0;
                        }
@@ -1722,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                        rwlock_init(&(new_intf->cmd_rcvr_lock));
                        init_waitqueue_head(&new_intf->waitq);
                        INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
-                       new_intf->all_cmd_rcvr = NULL;
 
                        spin_lock_init(&(new_intf->counter_lock));
 
@@ -1814,7 +1879,7 @@ static void clean_up_interface_data(ipmi_smi_t intf)
        free_recv_msg_list(&(intf->waiting_events));
        free_cmd_rcvr_list(&(intf->cmd_rcvrs));
 
-       for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+       for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
                if ((intf->seq_table[i].inuse)
                    && (intf->seq_table[i].recv_msg))
                {
@@ -1833,7 +1898,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
        down_write(&interfaces_sem);
        if (list_empty(&(intf->users)))
        {
-               for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+               for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                        if (ipmi_interfaces[i] == intf) {
                                remove_proc_entries(intf);
                                spin_lock_irqsave(&interfaces_lock, flags);
@@ -1960,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
 
        read_lock(&(intf->cmd_rcvr_lock));
        
-       if (intf->all_cmd_rcvr) {
-               user = intf->all_cmd_rcvr;
-       } else {
-               /* Find the command/netfn. */
-               list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
-                       if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
-                               user = rcvr->user;
-                               break;
-                       }
+       /* Find the command/netfn. */
+       list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+               if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+                       user = rcvr->user;
+                       break;
                }
        }
        read_unlock(&(intf->cmd_rcvr_lock));
@@ -1985,7 +2046,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                msg->data[3] = msg->rsp[6];
                 msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
                msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
-               msg->data[6] = intf->my_address;
+               msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
                 /* rqseq/lun */
                 msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
                msg->data[8] = msg->rsp[8]; /* cmd */
@@ -1997,7 +2058,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
        {
                int m;
                printk("Invalid command:");
-               for (m=0; m<msg->data_size; m++)
+               for (m = 0; m < msg->data_size; m++)
                        printk(" %2.2x", msg->data[m]);
                printk("\n");
        }
@@ -2145,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
 
        read_lock(&(intf->cmd_rcvr_lock));
 
-       if (intf->all_cmd_rcvr) {
-               user = intf->all_cmd_rcvr;
-       } else {
-               /* Find the command/netfn. */
-               list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
-                       if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
-                               user = rcvr->user;
-                               break;
-                       }
+       /* Find the command/netfn. */
+       list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+               if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+                       user = rcvr->user;
+                       break;
                }
        }
        read_unlock(&(intf->cmd_rcvr_lock));
@@ -2330,6 +2387,14 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
        unsigned long        flags;
 
        recv_msg = (struct ipmi_recv_msg *) msg->user_data;
+       if (recv_msg == NULL)
+       {
+               printk(KERN_WARNING"IPMI message received with no owner. This\n"
+                       "could be because of a malformed message, or\n"
+                       "because of a hardware error.  Contact your\n"
+                       "hardware vender for assistance\n");
+               return 0;
+       }
 
        /* Make sure the user still exists. */
        list_for_each_entry(user, &(intf->users), link) {
@@ -2340,19 +2405,11 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
                }
        }
 
-       if (!found) {
-               /* Special handling for NULL users. */
-               if (!recv_msg->user && intf->null_user_handler){
-                       intf->null_user_handler(intf, msg);
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->handled_local_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
-               }else{
-                       /* The user for the message went away, so give up. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->unhandled_local_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
-               }
+       if ((! found) && recv_msg->user) {
+               /* The user for the message went away, so give up. */
+               spin_lock_irqsave(&intf->counter_lock, flags);
+               intf->unhandled_local_responses++;
+               spin_unlock_irqrestore(&intf->counter_lock, flags);
                ipmi_free_recv_msg(recv_msg);
        } else {
                struct ipmi_system_interface_addr *smi_addr;
@@ -2392,7 +2449,7 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
 #ifdef DEBUG_MSGING
        int m;
        printk("Recv:");
-       for (m=0; m<msg->rsp_size; m++)
+       for (m = 0; m < msg->rsp_size; m++)
                printk(" %2.2x", msg->rsp[m]);
        printk("\n");
 #endif
@@ -2626,7 +2683,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
        {
                int m;
                printk("Resend: ");
-               for (m=0; m<smi_msg->data_size; m++)
+               for (m = 0; m < smi_msg->data_size; m++)
                        printk(" %2.2x", smi_msg->data[m]);
                printk("\n");
        }
@@ -2647,7 +2704,7 @@ ipmi_timeout_handler(long timeout_period)
        INIT_LIST_HEAD(&timeouts);
 
        spin_lock(&interfaces_lock);
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                intf = ipmi_interfaces[i];
                if (intf == NULL)
                        continue;
@@ -2672,7 +2729,7 @@ ipmi_timeout_handler(long timeout_period)
                   have timed out, putting them in the timeouts
                   list. */
                spin_lock_irqsave(&(intf->seq_lock), flags);
-               for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+               for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
                        struct seq_table *ent = &(intf->seq_table[j]);
                        if (!ent->inuse)
                                continue;
@@ -2712,7 +2769,7 @@ ipmi_timeout_handler(long timeout_period)
                                spin_unlock(&intf->counter_lock);
                                smi_msg = smi_from_recv_msg(intf,
                                                ent->recv_msg, j, ent->seqid);
-                               if(!smi_msg)
+                               if (! smi_msg)
                                        continue;
 
                                spin_unlock_irqrestore(&(intf->seq_lock),flags);
@@ -2743,7 +2800,7 @@ static void ipmi_request_event(void)
        int        i;
 
        spin_lock(&interfaces_lock);
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                intf = ipmi_interfaces[i];
                if (intf == NULL)
                        continue;
@@ -2838,28 +2895,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
 }
 
 #ifdef CONFIG_IPMI_PANIC_STRING
-static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
 {
-       if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
-           && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
-           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+       if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+           && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE)
+           && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD)
+           && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
        {
                /* A get event receiver command, save it. */
-               intf->event_receiver = msg->rsp[3];
-               intf->event_receiver_lun = msg->rsp[4] & 0x3;
+               intf->event_receiver = msg->msg.data[1];
+               intf->event_receiver_lun = msg->msg.data[2] & 0x3;
        }
 }
 
-static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
 {
-       if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
-           && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
-           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+       if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+           && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+           && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD)
+           && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
        {
                /* A get device id command, save if we are an event
                   receiver or generator. */
-               intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
-               intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
+               intf->local_sel_device = (msg->msg.data[6] >> 2) & 1;
+               intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
        }
 }
 #endif
@@ -2903,7 +2962,7 @@ static void send_panic_events(char *str)
        recv_msg.done = dummy_recv_done_handler;
 
        /* For every registered interface, send the event. */
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                intf = ipmi_interfaces[i];
                if (intf == NULL)
                        continue;
@@ -2915,12 +2974,12 @@ static void send_panic_events(char *str)
                               &addr,
                               0,
                               &msg,
-                              NULL,
+                              intf,
                               &smi_msg,
                               &recv_msg,
                               0,
-                              intf->my_address,
-                              intf->my_lun,
+                              intf->channels[0].address,
+                              intf->channels[0].lun,
                               0, 1); /* Don't retry, and don't wait. */
        }
 
@@ -2930,7 +2989,7 @@ static void send_panic_events(char *str)
        if (!str) 
                return;
 
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                char                  *p = str;
                struct ipmi_ipmb_addr *ipmb;
                int                   j;
@@ -2961,12 +3020,12 @@ static void send_panic_events(char *str)
                               &addr,
                               0,
                               &msg,
-                              NULL,
+                              intf,
                               &smi_msg,
                               &recv_msg,
                               0,
-                              intf->my_address,
-                              intf->my_lun,
+                              intf->channels[0].address,
+                              intf->channels[0].lun,
                               0, 1); /* Don't retry, and don't wait. */
 
                if (intf->local_event_generator) {
@@ -2981,12 +3040,12 @@ static void send_panic_events(char *str)
                                       &addr,
                                       0,
                                       &msg,
-                                      NULL,
+                                      intf,
                                       &smi_msg,
                                       &recv_msg,
                                       0,
-                                      intf->my_address,
-                                      intf->my_lun,
+                                      intf->channels[0].address,
+                                      intf->channels[0].lun,
                                       0, 1); /* no retry, and no wait. */
                }
                intf->null_user_handler = NULL;
@@ -2996,7 +3055,7 @@ static void send_panic_events(char *str)
                   be zero, and it must not be my address. */
                 if (((intf->event_receiver & 1) == 0)
                    && (intf->event_receiver != 0)
-                   && (intf->event_receiver != intf->my_address))
+                   && (intf->event_receiver != intf->channels[0].address))
                {
                        /* The event receiver is valid, send an IPMB
                           message. */
@@ -3031,7 +3090,7 @@ static void send_panic_events(char *str)
                        data[0] = 0;
                        data[1] = 0;
                        data[2] = 0xf0; /* OEM event without timestamp. */
-                       data[3] = intf->my_address;
+                       data[3] = intf->channels[0].address;
                        data[4] = j++; /* sequence # */
                        /* Always give 11 bytes, so strncpy will fill
                           it with zeroes for me. */
@@ -3043,12 +3102,12 @@ static void send_panic_events(char *str)
                                       &addr,
                                       0,
                                       &msg,
-                                      NULL,
+                                      intf,
                                       &smi_msg,
                                       &recv_msg,
                                       0,
-                                      intf->my_address,
-                                      intf->my_lun,
+                                      intf->channels[0].address,
+                                      intf->channels[0].lun,
                                       0, 1); /* no retry, and no wait. */
                }
        }       
@@ -3070,7 +3129,7 @@ static int panic_event(struct notifier_block *this,
        has_paniced = 1;
 
        /* For every registered interface, set it to run to completion. */
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                intf = ipmi_interfaces[i];
                if (intf == NULL)
                        continue;
@@ -3099,9 +3158,9 @@ static int ipmi_init_msghandler(void)
                return 0;
 
        printk(KERN_INFO "ipmi message handler version "
-              IPMI_MSGHANDLER_VERSION "\n");
+              IPMI_DRIVER_VERSION "\n");
 
-       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
                ipmi_interfaces[i] = NULL;
        }
 
@@ -3171,6 +3230,9 @@ module_exit(cleanup_ipmi);
 
 module_init(ipmi_init_msghandler_mod);
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface.");
+MODULE_VERSION(IPMI_DRIVER_VERSION);
 
 EXPORT_SYMBOL(ipmi_create_user);
 EXPORT_SYMBOL(ipmi_destroy_user);
index f951c30236c98aac5ed60473073118793a242924..e82a96ba396bb8ea49a460b26f2a71d4570f5284 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ipmi_smi.h>
 
 #define PFX "IPMI poweroff: "
-#define IPMI_POWEROFF_VERSION  "v33"
 
 /* Where to we insert our poweroff function? */
 extern void (*pm_power_off)(void);
@@ -53,16 +52,17 @@ extern void (*pm_power_off)(void);
 #define IPMI_CHASSIS_POWER_CYCLE       0x02    /* power cycle */
 
 /* the IPMI data command */
-static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+static int poweroff_powercycle;
 
 /* parameter definition to allow user to flag power cycle */
-module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
-MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+module_param(poweroff_powercycle, int, 0);
+MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
 
 /* Stuff from the get device id command. */
 static unsigned int mfg_id;
 static unsigned int prod_id;
 static unsigned char capabilities;
+static unsigned char ipmi_version;
 
 /* We use our own messages for this operation, we don't let the system
    allocate them, since we may be in a panic situation.  The whole
@@ -337,6 +337,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
        return;
 }
 
+/*
+ * ipmi_dell_chassis_detect()
+ * Dell systems with IPMI < 1.5 don't set the chassis capability bit
+ * but they can handle a chassis poweroff or powercycle command.
+ */
+
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static int ipmi_dell_chassis_detect (ipmi_user_t user)
+{
+       const char ipmi_version_major = ipmi_version & 0xF;
+       const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
+       const char mfr[3]=DELL_IANA_MFR_ID;
+       if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
+           ipmi_version_major <= 1 &&
+           ipmi_version_minor < 5)
+               return 1;
+       return 0;
+}
+
 /*
  * Standard chassis support
  */
@@ -366,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
 
  powercyclefailed:
        printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
-               ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
+               (poweroff_powercycle ? "cycle" : "down"));
 
        /*
         * Power down
         */
        send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
        send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
-       data[0] = poweroff_control;
+       if (poweroff_powercycle)
+               data[0] = IPMI_CHASSIS_POWER_CYCLE;
+       else
+               data[0] = IPMI_CHASSIS_POWER_DOWN;
        send_msg.data = data;
        send_msg.data_len = sizeof(data);
        rv = ipmi_request_in_rc_mode(user,
                                     (struct ipmi_addr *) &smi_addr,
                                     &send_msg);
        if (rv) {
-               switch (poweroff_control) {
-                       case IPMI_CHASSIS_POWER_CYCLE:
-                               /* power cycle failed, default to power down */
-                               printk(KERN_ERR PFX "Unable to send chassis power " \
-                                       "cycle message, IPMI error 0x%x\n", rv);
-                               poweroff_control = IPMI_CHASSIS_POWER_DOWN;
-                               goto powercyclefailed;
-
-                       case IPMI_CHASSIS_POWER_DOWN:
-                       default:
-                               printk(KERN_ERR PFX "Unable to send chassis power " \
-                                       "down message, IPMI error 0x%x\n", rv);
-                               break;
+               if (poweroff_powercycle) {
+                       /* power cycle failed, default to power down */
+                       printk(KERN_ERR PFX "Unable to send chassis power " \
+                              "cycle message, IPMI error 0x%x\n", rv);
+                       poweroff_powercycle = 0;
+                       goto powercyclefailed;
                }
-       }
 
-       return;
+               printk(KERN_ERR PFX "Unable to send chassis power " \
+                      "down message, IPMI error 0x%x\n", rv);
+       }
 }
 
 
@@ -414,6 +430,9 @@ static struct poweroff_function poweroff_functions[] = {
        { .platform_type        = "CPI1",
          .detect               = ipmi_cpi1_detect,
          .poweroff_func        = ipmi_poweroff_cpi1 },
+       { .platform_type        = "chassis",
+         .detect               = ipmi_dell_chassis_detect,
+         .poweroff_func        = ipmi_poweroff_chassis },
        /* Chassis should generally be last, other things should override
           it. */
        { .platform_type        = "chassis",
@@ -499,10 +518,11 @@ static void ipmi_po_new_smi(int if_num)
        prod_id = (halt_recv_msg.msg.data[10]
                   | (halt_recv_msg.msg.data[11] << 8));
        capabilities = halt_recv_msg.msg.data[6];
+       ipmi_version = halt_recv_msg.msg.data[5];
 
 
        /* Scan for a poweroff method */
-       for (i=0; i<NUM_PO_FUNCS; i++) {
+       for (i = 0; i < NUM_PO_FUNCS; i++) {
                if (poweroff_functions[i].detect(ipmi_user))
                        goto found;
        }
@@ -538,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher =
 
 
 #ifdef CONFIG_PROC_FS
-/* displays properties to proc */
-static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
-                              int *eof, void *data)
-{
-       return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
-                       poweroff_control);
-}
+#include <linux/sysctl.h>
+
+static ctl_table ipmi_table[] = {
+       { .ctl_name     = DEV_IPMI_POWEROFF_POWERCYCLE,
+         .procname     = "poweroff_powercycle",
+         .data         = &poweroff_powercycle,
+         .maxlen       = sizeof(poweroff_powercycle),
+         .mode         = 0644,
+         .proc_handler = &proc_dointvec },
+       { }
+};
 
-/* process property writes from proc */
-static int proc_write_chassctrl(struct file *file, const char *buffer,
-                               unsigned long count, void *data)
-{
-       int          rv = count;
-       unsigned int newval = 0;
-
-       sscanf(buffer, "%d", &newval);
-       switch (newval) {
-               case IPMI_CHASSIS_POWER_CYCLE:
-                       printk(KERN_INFO PFX "power cycle is now enabled\n");
-                       poweroff_control = newval;
-                       break;
-
-               case IPMI_CHASSIS_POWER_DOWN:
-                       poweroff_control = IPMI_CHASSIS_POWER_DOWN;
-                       break;
-
-               default:
-                       rv = -EINVAL;
-                       break;
-       }
+static ctl_table ipmi_dir_table[] = {
+       { .ctl_name     = DEV_IPMI,
+         .procname     = "ipmi",
+         .mode         = 0555,
+         .child        = ipmi_table },
+       { }
+};
 
-       return rv;
-}
+static ctl_table ipmi_root_table[] = {
+       { .ctl_name     = CTL_DEV,
+         .procname     = "dev",
+         .mode         = 0555,
+         .child        = ipmi_dir_table },
+       { }
+};
+
+static struct ctl_table_header *ipmi_table_header;
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -578,42 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer,
  */
 static int ipmi_poweroff_init (void)
 {
-       int                   rv;
-       struct proc_dir_entry *file;
+       int rv;
 
        printk ("Copyright (C) 2004 MontaVista Software -"
-               " IPMI Powerdown via sys_reboot version "
-               IPMI_POWEROFF_VERSION ".\n");
-
-       switch (poweroff_control) {
-               case IPMI_CHASSIS_POWER_CYCLE:
-                       printk(KERN_INFO PFX "Power cycle is enabled.\n");
-                       break;
-
-               case IPMI_CHASSIS_POWER_DOWN:
-               default:
-                       poweroff_control = IPMI_CHASSIS_POWER_DOWN;
-                       break;
+               " IPMI Powerdown via sys_reboot.\n");
+
+       if (poweroff_powercycle)
+               printk(KERN_INFO PFX "Power cycle is enabled.\n");
+
+#ifdef CONFIG_PROC_FS
+       ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
+       if (!ipmi_table_header) {
+               printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
+               rv = -ENOMEM;
+               goto out_err;
        }
+#endif
 
+#ifdef CONFIG_PROC_FS
        rv = ipmi_smi_watcher_register(&smi_watcher);
+#endif
        if (rv) {
+               unregister_sysctl_table(ipmi_table_header);
                printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
                goto out_err;
        }
 
-#ifdef CONFIG_PROC_FS
-       file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
-       if (!file) {
-               printk(KERN_ERR PFX "Unable to create proc power control\n");
-       } else {
-               file->nlink = 1;
-               file->read_proc = proc_read_chassctrl;
-               file->write_proc = proc_write_chassctrl;
-               file->owner = THIS_MODULE;
-       }
-#endif
-
  out_err:
        return rv;
 }
@@ -624,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void)
        int rv;
 
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry("poweroff_control", proc_ipmi_root);
+       unregister_sysctl_table(ipmi_table_header);
 #endif
 
        ipmi_smi_watcher_unregister(&smi_watcher);
@@ -642,3 +648,5 @@ module_exit(ipmi_poweroff_cleanup);
 
 module_init(ipmi_poweroff_init);
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");
index a44b97304e95a6e38426e973428f744b1764dd61..1abec687865cf5b4862d26f4552abc39e748094d 100644 (file)
 # endif
 static inline void add_usec_to_timer(struct timer_list *t, long v)
 {
-       t->sub_expires += nsec_to_arch_cycle(v * 1000);
-       while (t->sub_expires >= arch_cycles_per_jiffy)
+       t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000);
+       while (t->arch_cycle_expires >= arch_cycles_per_jiffy)
        {
                t->expires++;
-               t->sub_expires -= arch_cycles_per_jiffy;
+               t->arch_cycle_expires -= arch_cycles_per_jiffy;
        }
 }
 #endif
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v)
 #include <asm/io.h>
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
-
-#define IPMI_SI_VERSION "v33"
+#include <linux/dmi.h>
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -109,6 +108,21 @@ enum si_type {
     SI_KCS, SI_SMIC, SI_BT
 };
 
+struct ipmi_device_id {
+       unsigned char device_id;
+       unsigned char device_revision;
+       unsigned char firmware_revision_1;
+       unsigned char firmware_revision_2;
+       unsigned char ipmi_version;
+       unsigned char additional_device_support;
+       unsigned char manufacturer_id[3];
+       unsigned char product_id[2];
+       unsigned char aux_firmware_revision[4];
+} __attribute__((packed));
+
+#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
+#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
+
 struct smi_info
 {
        ipmi_smi_t             intf;
@@ -131,12 +145,24 @@ struct smi_info
        void (*irq_cleanup)(struct smi_info *info);
        unsigned int io_size;
 
+       /* Per-OEM handler, called from handle_flags().
+          Returns 1 when handle_flags() needs to be re-run
+          or 0 indicating it set si_state itself.
+       */
+       int (*oem_data_avail_handler)(struct smi_info *smi_info);
+
        /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
           is set to hold the flags until we are done handling everything
           from the flags. */
 #define RECEIVE_MSG_AVAIL      0x01
 #define EVENT_MSG_BUFFER_FULL  0x02
 #define WDT_PRE_TIMEOUT_INT    0x08
+#define OEM0_DATA_AVAIL     0x20
+#define OEM1_DATA_AVAIL     0x40
+#define OEM2_DATA_AVAIL     0x80
+#define OEM_DATA_AVAIL      (OEM0_DATA_AVAIL | \
+                             OEM1_DATA_AVAIL | \
+                             OEM2_DATA_AVAIL)
        unsigned char       msg_flags;
 
        /* If set to true, this will request events the next time the
@@ -175,11 +201,7 @@ struct smi_info
           interrupts. */
        int interrupt_disabled;
 
-       unsigned char ipmi_si_dev_rev;
-       unsigned char ipmi_si_fw_rev_major;
-       unsigned char ipmi_si_fw_rev_minor;
-       unsigned char ipmi_version_major;
-       unsigned char ipmi_version_minor;
+       struct ipmi_device_id device_id;
 
        /* Slave address, could be reported from DMI. */
        unsigned char slave_addr;
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
                entry = smi_info->xmit_msgs.next;
        }
 
-       if (!entry) {
+       if (! entry) {
                smi_info->curr_msg = NULL;
                rv = SI_SM_IDLE;
        } else {
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info)
    memory, we will re-enable the interrupt. */
 static inline void disable_si_irq(struct smi_info *smi_info)
 {
-       if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+       if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
                disable_irq_nosync(smi_info->irq);
                smi_info->interrupt_disabled = 1;
        }
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info)
 
 static void handle_flags(struct smi_info *smi_info)
 {
+ retry:
        if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
                /* Watchdog pre-timeout */
                spin_lock(&smi_info->count_lock);
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info)
        } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
                /* Messages available. */
                smi_info->curr_msg = ipmi_alloc_smi_msg();
-               if (!smi_info->curr_msg) {
+               if (! smi_info->curr_msg) {
                        disable_si_irq(smi_info);
                        smi_info->si_state = SI_NORMAL;
                        return;
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info)
        } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
                /* Events available. */
                smi_info->curr_msg = ipmi_alloc_smi_msg();
-               if (!smi_info->curr_msg) {
+               if (! smi_info->curr_msg) {
                        disable_si_irq(smi_info);
                        smi_info->si_state = SI_NORMAL;
                        return;
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info)
                        smi_info->curr_msg->data,
                        smi_info->curr_msg->data_size);
                smi_info->si_state = SI_GETTING_EVENTS;
+       } else if (smi_info->msg_flags & OEM_DATA_AVAIL) {
+               if (smi_info->oem_data_avail_handler)
+                       if (smi_info->oem_data_avail_handler(smi_info))
+                               goto retry;
        } else {
                smi_info->si_state = SI_NORMAL;
        }
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
 #endif
        switch (smi_info->si_state) {
        case SI_NORMAL:
-               if (!smi_info->curr_msg)
+               if (! smi_info->curr_msg)
                        break;
 
                smi_info->curr_msg->rsp_size
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info)
 #if defined(CONFIG_HIGH_RES_TIMERS)
        unsigned long flags;
        unsigned long jiffies_now;
+       unsigned long seq;
 
        if (del_timer(&(smi_info->si_timer))) {
                /* If we don't delete the timer, then it will go off
                   immediately, anyway.  So we only process if we
                   actually delete the timer. */
 
-               /* We already have irqsave on, so no need for it
-                   here. */
-               read_lock(&xtime_lock);
-               jiffies_now = jiffies;
-               smi_info->si_timer.expires = jiffies_now;
-               smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now);
+               do {
+                       seq = read_seqbegin_irqsave(&xtime_lock, flags);
+                       jiffies_now = jiffies;
+                       smi_info->si_timer.expires = jiffies_now;
+                       smi_info->si_timer.arch_cycle_expires
+                               = get_arch_cycles(jiffies_now);
+               } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
                add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
 
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data)
        /* If the state machine asks for a short delay, then shorten
            the timer timeout. */
        if (smi_result == SI_SM_CALL_WITH_DELAY) {
+#if defined(CONFIG_HIGH_RES_TIMERS)
+               unsigned long seq;
+#endif
                spin_lock_irqsave(&smi_info->count_lock, flags);
                smi_info->short_timeouts++;
                spin_unlock_irqrestore(&smi_info->count_lock, flags);
 #if defined(CONFIG_HIGH_RES_TIMERS)
-               read_lock(&xtime_lock);
-                smi_info->si_timer.expires = jiffies;
-                smi_info->si_timer.sub_expires
-                        = get_arch_cycles(smi_info->si_timer.expires);
-                read_unlock(&xtime_lock);
+               do {
+                       seq = read_seqbegin_irqsave(&xtime_lock, flags);
+                       smi_info->si_timer.expires = jiffies;
+                       smi_info->si_timer.arch_cycle_expires
+                               = get_arch_cycles(smi_info->si_timer.expires);
+               } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
                add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
 #else
                smi_info->si_timer.expires = jiffies + 1;
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data)
                spin_unlock_irqrestore(&smi_info->count_lock, flags);
                smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
 #if defined(CONFIG_HIGH_RES_TIMERS)
-               smi_info->si_timer.sub_expires = 0;
+               smi_info->si_timer.arch_cycle_expires = 0;
 #endif
        }
 
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info)
 {
        int rv;
 
-       if (!info->irq)
+       if (! info->irq)
                return 0;
 
        if (info->si_type == SI_BT) {
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info)
                                 SA_INTERRUPT,
                                 DEVICE_NAME,
                                 info);
-               if (!rv)
+               if (! rv)
                        /* Enable the interrupt in the BT interface. */
                        info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
                                         IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info)
 
 static void std_irq_cleanup(struct smi_info *info)
 {
-       if (!info->irq)
+       if (! info->irq)
                return;
 
        if (info->si_type == SI_BT)
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info)
        unsigned int *addr = info->io.info;
        int           mapsize;
 
-       if (!addr || (!*addr))
+       if (! addr || (! *addr))
                return -ENODEV;
 
        info->io_cleanup = port_cleanup;
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
 {
        struct smi_info *info;
 
-       if (!ports[intf_num])
+       if (! ports[intf_num])
                return -ENODEV;
 
-       if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
+       if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
                              ports[intf_num]))
                return -ENODEV;
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
+       if (! info) {
                printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n");
                return -ENOMEM;
        }
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
        info->io.info = &(ports[intf_num]);
        info->io.addr = NULL;
        info->io.regspacing = regspacings[intf_num];
-       if (!info->io.regspacing)
+       if (! info->io.regspacing)
                info->io.regspacing = DEFAULT_REGSPACING;
        info->io.regsize = regsizes[intf_num];
-       if (!info->io.regsize)
+       if (! info->io.regsize)
                info->io.regsize = DEFAULT_REGSPACING;
        info->io.regshift = regshifts[intf_num];
        info->irq = 0;
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info)
        unsigned long *addr = info->io.info;
        int           mapsize;
 
-       if (!addr || (!*addr))
+       if (! addr || (! *addr))
                return -ENODEV;
 
        info->io_cleanup = mem_cleanup;
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
 {
        struct smi_info *info;
 
-       if (!addrs[intf_num])
+       if (! addrs[intf_num])
                return -ENODEV;
 
-       if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
+       if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
                              addrs[intf_num]))
                return -ENODEV;
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
+       if (! info) {
                printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n");
                return -ENOMEM;
        }
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
        info->io.info = &addrs[intf_num];
        info->io.addr = NULL;
        info->io.regspacing = regspacings[intf_num];
-       if (!info->io.regspacing)
+       if (! info->io.regspacing)
                info->io.regspacing = DEFAULT_REGSPACING;
        info->io.regsize = regsizes[intf_num];
-       if (!info->io.regsize)
+       if (! info->io.regsize)
                info->io.regsize = DEFAULT_REGSPACING;
        info->io.regshift = regshifts[intf_num];
        info->irq = 0;
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
 {
        acpi_status status;
 
-       if (!info->irq)
+       if (! info->irq)
                return 0;
 
        /* FIXME - is level triggered right? */
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
 
 static void acpi_gpe_irq_cleanup(struct smi_info *info)
 {
-       if (!info->irq)
+       if (! info->irq)
                return;
 
        acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe);
@@ -1504,10 +1537,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
                addr_space = IPMI_MEM_ADDR_SPACE;
        else
                addr_space = IPMI_IO_ADDR_SPACE;
-       if (!is_new_interface(-1, addr_space, spmi->addr.address))
+       if (! is_new_interface(-1, addr_space, spmi->addr.address))
                return -ENODEV;
 
-       if (!spmi->addr.register_bit_width) {
+       if (! spmi->addr.register_bit_width) {
                acpi_failure = 1;
                return -ENODEV;
        }
@@ -1534,7 +1567,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
        }
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
+       if (! info) {
                printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
                return -ENOMEM;
        }
@@ -1610,22 +1643,15 @@ typedef struct dmi_ipmi_data
 static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
 static int dmi_data_entries;
 
-typedef struct dmi_header
-{
-       u8      type;
-       u8      length;
-       u16     handle;
-} dmi_header_t;
-
-static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
+static int __init decode_dmi(struct dmi_header *dm, int intf_num)
 {
-       u8              __iomem *data = (u8 __iomem *)dm;
+       u8              *data = (u8 *)dm;
        unsigned long   base_addr;
        u8              reg_spacing;
-       u8              len = readb(&dm->length);
+       u8              len = dm->length;
        dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
-       ipmi_data->type = readb(&data[4]);
+       ipmi_data->type = data[4];
 
        memcpy(&base_addr, data+8, sizeof(unsigned long));
        if (len >= 0x11) {
@@ -1640,12 +1666,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
                }
                /* If bit 4 of byte 0x10 is set, then the lsb for the address
                   is odd. */
-               ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
+               ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
 
-               ipmi_data->irq = readb(&data[0x11]);
+               ipmi_data->irq = data[0x11];
 
                /* The top two bits of byte 0x10 hold the register spacing. */
-               reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
+               reg_spacing = (data[0x10] & 0xC0) >> 6;
                switch(reg_spacing){
                case 0x00: /* Byte boundaries */
                    ipmi_data->offset = 1;
@@ -1673,7 +1699,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
                ipmi_data->offset = 1;
        }
 
-       ipmi_data->slave_addr = readb(&data[6]);
+       ipmi_data->slave_addr = data[6];
 
        if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
                dmi_data_entries++;
@@ -1685,94 +1711,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
        return -1;
 }
 
-static int dmi_table(u32 base, int len, int num)
+static void __init dmi_find_bmc(void)
 {
-       u8                __iomem *buf;
-       struct dmi_header __iomem *dm;
-       u8                __iomem *data;
-       int               i=1;
-       int               status=-1;
+       struct dmi_device *dev = NULL;
        int               intf_num = 0;
 
-       buf = ioremap(base, len);
-       if(buf==NULL)
-               return -1;
-
-       data = buf;
-
-       while(i<num && (data - buf) < len)
-       {
-               dm=(dmi_header_t __iomem *)data;
-
-               if((data-buf+readb(&dm->length)) >= len)
-                       break;
-
-               if (readb(&dm->type) == 38) {
-                       if (decode_dmi(dm, intf_num) == 0) {
-                               intf_num++;
-                               if (intf_num >= SI_MAX_DRIVERS)
-                                       break;
-                       }
-               }
-
-               data+=readb(&dm->length);
-               while((data-buf) < len && (readb(data)||readb(data+1)))
-                       data++;
-               data+=2;
-               i++;
-       }
-       iounmap(buf);
-
-       return status;
-}
-
-static inline int dmi_checksum(u8 *buf)
-{
-       u8   sum=0;
-       int  a;
-
-       for(a=0; a<15; a++)
-               sum+=buf[a];
-       return (sum==0);
-}
-
-static int dmi_decode(void)
-{
-       u8   buf[15];
-       u32  fp=0xF0000;
-
-#ifdef CONFIG_SIMNOW
-       return -1;
-#endif
-
-       while(fp < 0xFFFFF)
-       {
-               isa_memcpy_fromio(buf, fp, 15);
-               if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
-               {
-                       u16 num=buf[13]<<8|buf[12];
-                       u16 len=buf[7]<<8|buf[6];
-                       u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+       while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
+               if (intf_num >= SI_MAX_DRIVERS)
+                       break;
 
-                       if(dmi_table(base, len, num) == 0)
-                               return 0;
-               }
-               fp+=16;
+               decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
        }
-
-       return -1;
 }
 
 static int try_init_smbios(int intf_num, struct smi_info **new_info)
 {
-       struct smi_info   *info;
-       dmi_ipmi_data_t   *ipmi_data = dmi_data+intf_num;
-       char              *io_type;
+       struct smi_info *info;
+       dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
+       char            *io_type;
 
        if (intf_num >= dmi_data_entries)
                return -ENODEV;
 
-       switch(ipmi_data->type) {
+       switch (ipmi_data->type) {
                case 0x01: /* KCS */
                        si_type[intf_num] = "kcs";
                        break;
@@ -1787,7 +1748,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
        }
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
+       if (! info) {
                printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n");
                return -ENOMEM;
        }
@@ -1811,7 +1772,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
 
        regspacings[intf_num] = ipmi_data->offset;
        info->io.regspacing = regspacings[intf_num];
-       if (!info->io.regspacing)
+       if (! info->io.regspacing)
                info->io.regspacing = DEFAULT_REGSPACING;
        info->io.regsize = DEFAULT_REGSPACING;
        info->io.regshift = regshifts[intf_num];
@@ -1853,14 +1814,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
 
        pci_smic_checked = 1;
 
-       if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID,
-                                      NULL)))
-               ;
-       else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) &&
-                pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)
-               fe_rmc = 1;
-       else
-               return -ENODEV;
+       pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL);
+       if (! pci_dev) {
+               pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL);
+               if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID))
+                       fe_rmc = 1;
+               else
+                       return -ENODEV;
+       }
 
        error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr);
        if (error)
@@ -1873,7 +1834,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
        }
 
        /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */
-       if (!(base_addr & 0x0001))
+       if (! (base_addr & 0x0001))
        {
                pci_dev_put(pci_dev);
                printk(KERN_ERR
@@ -1883,17 +1844,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
        }
 
        base_addr &= 0xFFFE;
-       if (!fe_rmc)
+       if (! fe_rmc)
                /* Data register starts at base address + 1 in eRMC */
                ++base_addr;
 
-       if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
+       if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
                pci_dev_put(pci_dev);
                return -ENODEV;
        }
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info) {
+       if (! info) {
                pci_dev_put(pci_dev);
                printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n");
                return -ENOMEM;
@@ -1904,7 +1865,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
        ports[intf_num] = base_addr;
        info->io.info = &(ports[intf_num]);
        info->io.regspacing = regspacings[intf_num];
-       if (!info->io.regspacing)
+       if (! info->io.regspacing)
                info->io.regspacing = DEFAULT_REGSPACING;
        info->io.regsize = DEFAULT_REGSPACING;
        info->io.regshift = regshifts[intf_num];
@@ -1925,7 +1886,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
 static int try_init_plug_and_play(int intf_num, struct smi_info **new_info)
 {
 #ifdef CONFIG_PCI
-       if (find_pci_smic(intf_num, new_info)==0)
+       if (find_pci_smic(intf_num, new_info) == 0)
                return 0;
 #endif
        /* Include other methods here. */
@@ -1943,7 +1904,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
        int               rv = 0;
 
        resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
-       if (!resp)
+       if (! resp)
                return -ENOMEM;
 
        /* Do a Get Device ID command, since it comes back with some
@@ -1992,11 +1953,8 @@ static int try_get_dev_id(struct smi_info *smi_info)
        }
 
        /* Record info from the get device id, in case we need it. */
-       smi_info->ipmi_si_dev_rev = resp[4] & 0xf;
-       smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f;
-       smi_info->ipmi_si_fw_rev_minor = resp[6];
-       smi_info->ipmi_version_major = resp[7] & 0xf;
-       smi_info->ipmi_version_minor = resp[7] >> 4;
+       memcpy(&smi_info->device_id, &resp[3],
+              min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id)));
 
  out:
        kfree(resp);
@@ -2028,7 +1986,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
        struct smi_info *smi = data;
 
        out += sprintf(out, "interrupts_enabled:    %d\n",
-                      smi->irq && !smi->interrupt_disabled);
+                      smi->irq && ! smi->interrupt_disabled);
        out += sprintf(out, "short_timeouts:        %ld\n",
                       smi->short_timeouts);
        out += sprintf(out, "long_timeouts:         %ld\n",
@@ -2057,6 +2015,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
        return (out - ((char *) page));
 }
 
+/*
+ * oem_data_avail_to_receive_msg_avail
+ * @info - smi_info structure with msg_flags set
+ *
+ * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL
+ * Returns 1 indicating need to re-run handle_flags().
+ */
+static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
+{
+       smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) |
+                               RECEIVE_MSG_AVAIL);
+       return 1;
+}
+
+/*
+ * setup_dell_poweredge_oem_data_handler
+ * @info - smi_info.device_id must be populated
+ *
+ * Systems that match, but have firmware version < 1.40 may assert
+ * OEM0_DATA_AVAIL on their own, without being told via Set Flags that
+ * it's safe to do so.  Such systems will de-assert OEM1_DATA_AVAIL
+ * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags
+ * as RECEIVE_MSG_AVAIL instead.
+ *
+ * As Dell has no plans to release IPMI 1.5 firmware that *ever*
+ * assert the OEM[012] bits, and if it did, the driver would have to
+ * change to handle that properly, we don't actually check for the
+ * firmware version.
+ * Device ID = 0x20                BMC on PowerEdge 8G servers
+ * Device Revision = 0x80
+ * Firmware Revision1 = 0x01       BMC version 1.40
+ * Firmware Revision2 = 0x40       BCD encoded
+ * IPMI Version = 0x51             IPMI 1.5
+ * Manufacturer ID = A2 02 00      Dell IANA
+ *
+ */
+#define DELL_POWEREDGE_8G_BMC_DEVICE_ID  0x20
+#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
+#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
+{
+       struct ipmi_device_id *id = &smi_info->device_id;
+       const char mfr[3]=DELL_IANA_MFR_ID;
+       if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))
+           && (id->device_id       == DELL_POWEREDGE_8G_BMC_DEVICE_ID)
+           && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV)
+           && (id->ipmi_version    == DELL_POWEREDGE_8G_BMC_IPMI_VERSION))
+       {
+               smi_info->oem_data_avail_handler =
+                       oem_data_avail_to_receive_msg_avail;
+       }
+}
+
+/*
+ * setup_oem_data_handler
+ * @info - smi_info.device_id must be filled in already
+ *
+ * Fills in smi_info.device_id.oem_data_available_handler
+ * when we know what function to use there.
+ */
+
+static void setup_oem_data_handler(struct smi_info *smi_info)
+{
+       setup_dell_poweredge_oem_data_handler(smi_info);
+}
+
 /* Returns 0 if initialized, or negative on an error. */
 static int init_one_smi(int intf_num, struct smi_info **smi)
 {
@@ -2068,19 +2093,15 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
        if (rv)
                rv = try_init_port(intf_num, &new_smi);
 #ifdef CONFIG_ACPI_INTERPRETER
-       if ((rv) && (si_trydefaults)) {
+       if (rv && si_trydefaults)
                rv = try_init_acpi(intf_num, &new_smi);
-       }
 #endif
 #ifdef CONFIG_X86
-       if ((rv) && (si_trydefaults)) {
+       if (rv && si_trydefaults)
                rv = try_init_smbios(intf_num, &new_smi);
-        }
 #endif
-       if ((rv) && (si_trydefaults)) {
+       if (rv && si_trydefaults)
                rv = try_init_plug_and_play(intf_num, &new_smi);
-       }
-
 
        if (rv)
                return rv;
@@ -2090,7 +2111,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
        new_smi->si_sm = NULL;
        new_smi->handlers = NULL;
 
-       if (!new_smi->irq_setup) {
+       if (! new_smi->irq_setup) {
                new_smi->irq = irqs[intf_num];
                new_smi->irq_setup = std_irq_setup;
                new_smi->irq_cleanup = std_irq_cleanup;
@@ -2124,7 +2145,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 
        /* Allocate the state machine's data and initialize it. */
        new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
-       if (!new_smi->si_sm) {
+       if (! new_smi->si_sm) {
                printk(" Could not allocate state machine memory\n");
                rv = -ENOMEM;
                goto out_err;
@@ -2155,6 +2176,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
        if (rv)
                goto out_err;
 
+       setup_oem_data_handler(new_smi);
+
        /* Try to claim any interrupts. */
        new_smi->irq_setup(new_smi);
 
@@ -2188,8 +2211,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 
        rv = ipmi_register_smi(&handlers,
                               new_smi,
-                              new_smi->ipmi_version_major,
-                              new_smi->ipmi_version_minor,
+                              ipmi_version_major(&new_smi->device_id),
+                              ipmi_version_minor(&new_smi->device_id),
                               new_smi->slave_addr,
                               &(new_smi->intf));
        if (rv) {
@@ -2230,7 +2253,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 
        /* Wait for the timer to stop.  This avoids problems with race
           conditions removing the timer here. */
-       while (!new_smi->timer_stopped) {
+       while (! new_smi->timer_stopped) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
        }
@@ -2270,7 +2293,7 @@ static __init int init_ipmi_si(void)
        /* Parse out the si_type string into its components. */
        str = si_type_str;
        if (*str != '\0') {
-               for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) {
+               for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) {
                        si_type[i] = str;
                        str = strchr(str, ',');
                        if (str) {
@@ -2282,22 +2305,14 @@ static __init int init_ipmi_si(void)
                }
        }
 
-       printk(KERN_INFO "IPMI System Interface driver version "
-              IPMI_SI_VERSION);
-       if (kcs_smi_handlers.version)
-               printk(", KCS version %s", kcs_smi_handlers.version);
-       if (smic_smi_handlers.version)
-               printk(", SMIC version %s", smic_smi_handlers.version);
-       if (bt_smi_handlers.version)
-               printk(", BT version %s", bt_smi_handlers.version);
-       printk("\n");
+       printk(KERN_INFO "IPMI System Interface driver.\n");
 
 #ifdef CONFIG_X86
-       dmi_decode();
+       dmi_find_bmc();
 #endif
 
        rv = init_one_smi(0, &(smi_infos[pos]));
-       if (rv && !ports[0] && si_trydefaults) {
+       if (rv && ! ports[0] && si_trydefaults) {
                /* If we are trying defaults and the initial port is
                    not set, then set it. */
                si_type[0] = "kcs";
@@ -2319,7 +2334,7 @@ static __init int init_ipmi_si(void)
        if (rv == 0)
                pos++;
 
-       for (i=1; i < SI_MAX_PARMS; i++) {
+       for (i = 1; i < SI_MAX_PARMS; i++) {
                rv = init_one_smi(i, &(smi_infos[pos]));
                if (rv == 0)
                        pos++;
@@ -2361,14 +2376,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
 
        /* Wait for the timer to stop.  This avoids problems with race
           conditions removing the timer here. */
-       while (!to_clean->timer_stopped) {
+       while (! to_clean->timer_stopped) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
        }
 
        /* Interrupts and timeouts are stopped, now make sure the
           interface is in a clean state. */
-       while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) {
+       while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                poll(to_clean);
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
@@ -2392,13 +2407,15 @@ static __exit void cleanup_ipmi_si(void)
 {
        int i;
 
-       if (!initialized)
+       if (! initialized)
                return;
 
-       for (i=0; i<SI_MAX_DRIVERS; i++) {
+       for (i = 0; i < SI_MAX_DRIVERS; i++) {
                cleanup_one_si(smi_infos[i]);
        }
 }
 module_exit(cleanup_ipmi_si);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces.");
index ae18747e670b10c0f2255403811f1210c85df982..add2aa2732f0c56c4324088a1a18b08ec08c7b9a 100644 (file)
@@ -46,8 +46,6 @@
 #include <linux/ipmi_msgdefs.h>                /* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_SMIC_VERSION "v33"
-
 /* smic_debug is a bit-field
  *     SMIC_DEBUG_ENABLE -     turned on for now
  *     SMIC_DEBUG_MSG -        commands and their responses
@@ -588,7 +586,6 @@ static int smic_size(void)
 
 struct si_sm_handlers smic_smi_handlers =
 {
-       .version           = IPMI_SMIC_VERSION,
        .init_data         = init_smic_data,
        .start_transaction = start_smic_transaction,
        .get_result        = smic_get_result,
index d35a953961cb9df8d5df54310cea2342f68fd8f9..e71aaae855adda775f9c296e6d91a333192d8110 100644 (file)
@@ -53,8 +53,6 @@
 
 #define        PFX "IPMI Watchdog: "
 
-#define IPMI_WATCHDOG_VERSION "v33"
-
 /*
  * The IPMI command/response information for the watchdog timer.
  */
@@ -259,7 +257,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
 
        data[1] = 0;
        WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
-       if (pretimeout > 0) {
+       if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) {
            WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
            data[2] = pretimeout;
        } else {
@@ -659,19 +657,18 @@ static ssize_t ipmi_read(struct file *file,
 
 static int ipmi_open(struct inode *ino, struct file *filep)
 {
-        switch (iminor(ino))
-        {
-                case WATCHDOG_MINOR:
-                   if(test_and_set_bit(0, &ipmi_wdog_open))
+        switch (iminor(ino)) {
+        case WATCHDOG_MINOR:
+               if (test_and_set_bit(0, &ipmi_wdog_open))
                         return -EBUSY;
 
-                   /* Don't start the timer now, let it start on the
-                      first heartbeat. */
-                   ipmi_start_timer_on_heartbeat = 1;
-                    return nonseekable_open(ino, filep);
+               /* Don't start the timer now, let it start on the
+                  first heartbeat. */
+               ipmi_start_timer_on_heartbeat = 1;
+               return nonseekable_open(ino, filep);
 
-                default:
-                    return (-ENODEV);
+       default:
+               return (-ENODEV);
         }
 }
 
@@ -817,15 +814,19 @@ static void ipmi_register_watchdog(int ipmi_intf)
 static int
 ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
 {
+        /* If we are not expecting a timeout, ignore it. */
+       if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+               return NOTIFY_DONE;
+
        /* If no one else handled the NMI, we assume it was the IPMI
            watchdog. */
-       if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
+       if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
+               /* On some machines, the heartbeat will give
+                  an error and not work unless we re-enable
+                  the timer.   So do so. */
+               pretimeout_since_last_heartbeat = 1;
                panic(PFX "pre-timeout");
-
-       /* On some machines, the heartbeat will give
-          an error and not work unless we re-enable
-          the timer.   So do so. */
-       pretimeout_since_last_heartbeat = 1;
+       }
 
        return NOTIFY_DONE;
 }
@@ -924,9 +925,6 @@ static int __init ipmi_wdog_init(void)
 {
        int rv;
 
-       printk(KERN_INFO PFX "driver version "
-              IPMI_WATCHDOG_VERSION "\n");
-
        if (strcmp(action, "reset") == 0) {
                action_val = WDOG_TIMEOUT_RESET;
        } else if (strcmp(action, "none") == 0) {
@@ -1011,6 +1009,8 @@ static int __init ipmi_wdog_init(void)
        register_reboot_notifier(&wdog_reboot_notifier);
        notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
 
+       printk(KERN_INFO PFX "driver initialized\n");
+
        return 0;
 }
 
@@ -1062,3 +1062,5 @@ static void __exit ipmi_wdog_exit(void)
 module_exit(ipmi_wdog_exit);
 module_init(ipmi_wdog_init);
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface.");
index 115dbb35334b031e71acaedff084402499a449a2..3fa64c63110864597f6fb5d32a3d40ebe0d84384 100644 (file)
@@ -750,7 +750,7 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
 
        dev->soft = NULL;
 
-       soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL);
+       soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL);
        if (soft == NULL)
                return -ENOMEM;
 
index 850a78c9c4bc9c639dd5b2c5816a4c89e7568eb1..f182752fe918b9b08bb601bd0bc827bb3e1f0cf2 100644 (file)
 # include <linux/efi.h>
 #endif
 
-#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
-extern void tapechar_init(void);
-#endif
-
 /*
  * Architectures vary in how they handle caching for addresses
  * outside of main memory.
index 931efd58f87a2d4270a7180f2fd9b7c22bcbfa81..0c8375165e29afca09a0ba82a6387f7a56c7e9a4 100644 (file)
@@ -63,8 +63,6 @@ static DECLARE_MUTEX(misc_sem);
 #define DYNAMIC_MINORS 64 /* like dynamic majors */
 static unsigned char misc_minors[DYNAMIC_MINORS / 8];
 
-extern int rtc_DP8570A_init(void);
-extern int rtc_MK48T08_init(void);
 extern int pmu_device_init(void);
 
 #ifdef CONFIG_PROC_FS
@@ -303,12 +301,7 @@ static int __init misc_init(void)
        misc_class = class_create(THIS_MODULE, "misc");
        if (IS_ERR(misc_class))
                return PTR_ERR(misc_class);
-#ifdef CONFIG_MVME16x
-       rtc_MK48T08_init();
-#endif
-#ifdef CONFIG_BVME6000
-       rtc_DP8570A_init();
-#endif
+
        if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
                printk("unable to get major %d for misc devices\n",
                       MISC_MAJOR);
index cefbe985e55cf57e94f07f52d7bc57e6e11834f3..36ae9ad2598cc755cbad3a40a86111b1a25374b2 100644 (file)
@@ -98,12 +98,13 @@ MODULE_PARM_DESC(useinput,
 
 #define SONYPI_DEVICE_MODEL_TYPE1      1
 #define SONYPI_DEVICE_MODEL_TYPE2      2
+#define SONYPI_DEVICE_MODEL_TYPE3      3
 
 /* type1 models use those */
 #define SONYPI_IRQ_PORT                        0x8034
 #define SONYPI_IRQ_SHIFT               22
-#define SONYPI_BASE                    0x50
-#define SONYPI_G10A                    (SONYPI_BASE+0x14)
+#define SONYPI_TYPE1_BASE              0x50
+#define SONYPI_G10A                    (SONYPI_TYPE1_BASE+0x14)
 #define SONYPI_TYPE1_REGION_SIZE       0x08
 #define SONYPI_TYPE1_EVTYPE_OFFSET     0x04
 
@@ -114,6 +115,13 @@ MODULE_PARM_DESC(useinput,
 #define SONYPI_TYPE2_REGION_SIZE       0x20
 #define SONYPI_TYPE2_EVTYPE_OFFSET     0x12
 
+/* type3 series specifics */
+#define SONYPI_TYPE3_BASE              0x40
+#define SONYPI_TYPE3_GID2              (SONYPI_TYPE3_BASE+0x48) /* 16 bits */
+#define SONYPI_TYPE3_MISC              (SONYPI_TYPE3_BASE+0x6d) /* 8 bits  */
+#define SONYPI_TYPE3_REGION_SIZE       0x20
+#define SONYPI_TYPE3_EVTYPE_OFFSET     0x12
+
 /* battery / brightness addresses */
 #define SONYPI_BAT_FLAGS       0x81
 #define SONYPI_LCD_LIGHT       0x96
@@ -159,6 +167,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = {
        { 0x0, 0x0 }
 };
 
+/* same as in type 2 models */
+static struct sonypi_ioport_list *sonypi_type3_ioport_list =
+       sonypi_type2_ioport_list;
+
 /* The set of possible interrupts */
 struct sonypi_irq_list {
        u16     irq;
@@ -180,6 +192,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
        {  0, 0x00 }    /* no IRQ, 0x00 in SIRQ in AML */
 };
 
+/* same as in type2 models */
+static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list;
+
 #define SONYPI_CAMERA_BRIGHTNESS               0
 #define SONYPI_CAMERA_CONTRAST                 1
 #define SONYPI_CAMERA_HUE                      2
@@ -223,6 +238,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
 #define SONYPI_MEYE_MASK                       0x00000400
 #define SONYPI_MEMORYSTICK_MASK                        0x00000800
 #define SONYPI_BATTERY_MASK                    0x00001000
+#define SONYPI_WIRELESS_MASK                   0x00002000
 
 struct sonypi_event {
        u8      data;
@@ -305,6 +321,13 @@ static struct sonypi_event sonypi_blueev[] = {
        { 0, 0 }
 };
 
+/* The set of possible wireless events */
+static struct sonypi_event sonypi_wlessev[] = {
+       { 0x59, SONYPI_EVENT_WIRELESS_ON },
+       { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+       { 0, 0 }
+};
+
 /* The set of possible back button events */
 static struct sonypi_event sonypi_backev[] = {
        { 0x20, SONYPI_EVENT_BACK_PRESSED },
@@ -383,7 +406,6 @@ static struct sonypi_eventtypes {
        { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
-       { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
@@ -391,6 +413,12 @@ static struct sonypi_eventtypes {
        { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
        { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
 
+       { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev },
+       { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+       { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+       { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+       { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+       { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
        { 0 }
 };
 
@@ -563,6 +591,23 @@ static void sonypi_type2_srs(void)
        udelay(10);
 }
 
+static void sonypi_type3_srs(void)
+{
+       u16 v16;
+       u8  v8;
+
+       /* This model type uses the same initialiazation of
+        * the embedded controller as the type2 models. */
+       sonypi_type2_srs();
+
+       /* Initialization of PCI config space of the LPC interface bridge. */
+       v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01;
+       pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16);
+       pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8);
+       v8 = (v8 & 0xCF) | 0x10;
+       pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8);
+}
+
 /* Disables the device - this comes from the AML code in the ACPI bios */
 static void sonypi_type1_dis(void)
 {
@@ -587,6 +632,13 @@ static void sonypi_type2_dis(void)
                printk(KERN_WARNING "ec_write failed\n");
 }
 
+static void sonypi_type3_dis(void)
+{
+       sonypi_type2_dis();
+       udelay(10);
+       pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0);
+}
+
 static u8 sonypi_call1(u8 dev)
 {
        u8 v1, v2;
@@ -1067,10 +1119,17 @@ static struct miscdevice sonypi_misc_device = {
 
 static void sonypi_enable(unsigned int camera_on)
 {
-       if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-               sonypi_type2_srs();
-       else
+       switch (sonypi_device.model) {
+       case SONYPI_DEVICE_MODEL_TYPE1:
                sonypi_type1_srs();
+               break;
+       case SONYPI_DEVICE_MODEL_TYPE2:
+               sonypi_type2_srs();
+               break;
+       case SONYPI_DEVICE_MODEL_TYPE3:
+               sonypi_type3_srs();
+               break;
+       }
 
        sonypi_call1(0x82);
        sonypi_call2(0x81, 0xff);
@@ -1094,10 +1153,18 @@ static int sonypi_disable(void)
        if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
                outb(0xf1, 0xb2);
 
-       if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-               sonypi_type2_dis();
-       else
+       switch (sonypi_device.model) {
+       case SONYPI_DEVICE_MODEL_TYPE1:
                sonypi_type1_dis();
+               break;
+       case SONYPI_DEVICE_MODEL_TYPE2:
+               sonypi_type2_dis();
+               break;
+       case SONYPI_DEVICE_MODEL_TYPE3:
+               sonypi_type3_dis();
+               break;
+       }
+
        return 0;
 }
 
@@ -1143,12 +1210,16 @@ static int __devinit sonypi_probe(void)
        struct sonypi_irq_list *irq_list;
        struct pci_dev *pcidev;
 
-       pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                               PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+       if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                    PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
+               sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
+       else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                         PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
+               sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+       else
+               sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 
        sonypi_device.dev = pcidev;
-       sonypi_device.model = pcidev ?
-               SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2;
 
        spin_lock_init(&sonypi_device.fifo_lock);
        sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
@@ -1176,16 +1247,22 @@ static int __devinit sonypi_probe(void)
                goto out_miscreg;
        }
 
-       if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
+
+       if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
+               ioport_list = sonypi_type1_ioport_list;
+               sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
+               sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
+               irq_list = sonypi_type1_irq_list;
+       } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
                ioport_list = sonypi_type2_ioport_list;
                sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
                sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET;
                irq_list = sonypi_type2_irq_list;
        } else {
-               ioport_list = sonypi_type1_ioport_list;
-               sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
-               sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
-               irq_list = sonypi_type1_irq_list;
+               ioport_list = sonypi_type3_ioport_list;
+               sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE;
+               sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET;
+               irq_list = sonypi_type3_irq_list;
        }
 
        for (i = 0; ioport_list[i].port1; i++) {
@@ -1274,11 +1351,10 @@ static int __devinit sonypi_probe(void)
 
        printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
               "v%s.\n", SONYPI_DRIVER_VERSION);
-       printk(KERN_INFO "sonypi: detected %s model, "
+       printk(KERN_INFO "sonypi: detected type%d model, "
               "verbose = %d, fnkeyinit = %s, camera = %s, "
               "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
-              (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
-                       "type1" : "type2",
+              sonypi_device.model,
               verbose,
               fnkeyinit ? "on" : "off",
               camera ? "on" : "off",
index cc2cc77fd174c2e825938c5d436aa7e3db2a39ce..c0d64914595fe182fb31bce1d8cc207fb19d66e4 100644 (file)
@@ -206,6 +206,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
        {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
        {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
        {0,}
index 6e4be3bb2d89d56b95792bf98e08bb3d201cc3ae..9d657127f313f21e653b0dd7b49fc539a66a0501 100644 (file)
@@ -153,7 +153,6 @@ static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
              unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
-extern void rs_360_init(void);
 static void release_mem(struct tty_struct *tty, int idx);
 
 
@@ -2910,11 +2909,6 @@ void __init console_init(void)
         */
 #ifdef CONFIG_EARLY_PRINTK
        disable_early_printk();
-#endif
-#ifdef CONFIG_SERIAL_68360
-       /* This is not a console initcall. I know not what it's doing here.
-          So I haven't moved it. dwmw2 */
-        rs_360_init();
 #endif
        call = __con_initcall_start;
        while (call < __con_initcall_end) {
index 665103ccaee83b69b6ca30a7fda0f40eec8983f7..b8d0c290b0dbf137152a03d3a992ad07e308738a 100644 (file)
@@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
 /* used by selection: complement pointer position */
 void complement_pos(struct vc_data *vc, int offset)
 {
-       static unsigned short *p;
+       static int old_offset = -1;
        static unsigned short old;
        static unsigned short oldx, oldy;
 
        WARN_CONSOLE_UNLOCKED();
 
-       if (p) {
-               scr_writew(old, p);
+       if (old_offset != -1 && old_offset >= 0 &&
+           old_offset < vc->vc_screenbuf_size) {
+               scr_writew(old, screenpos(vc, old_offset, 1));
                if (DO_UPDATE(vc))
                        vc->vc_sw->con_putc(vc, old, oldy, oldx);
        }
-       if (offset == -1)
-               p = NULL;
-       else {
+
+       old_offset = offset;
+
+       if (offset != -1 && offset >= 0 &&
+           offset < vc->vc_screenbuf_size) {
                unsigned short new;
+               unsigned short *p;
                p = screenpos(vc, offset, 1);
                old = scr_readw(p);
                new = old ^ vc->vc_complement_mask;
@@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset)
                        vc->vc_sw->con_putc(vc, new, oldy, oldx);
                }
        }
+
 }
 
 static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -2272,7 +2277,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = paste_selection(tty);
                        break;
                case TIOCL_UNBLANKSCREEN:
+                       acquire_console_sem();
                        unblank_screen();
+                       release_console_sem();
                        break;
                case TIOCL_SELLOADLUT:
                        ret = sel_loadlut(p);
@@ -2317,8 +2324,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        }
                        break;
                case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+                       acquire_console_sem();
                        ignore_poke = 1;
                        do_blank_screen(0);
+                       release_console_sem();
                        break;
                case TIOCL_BLANKEDSCREEN:
                        ret = console_blanked;
index 5b29c3b2a331bd28fb34a31d18bea4d2abf6d4ad..327b58e648753013e28026f4fb9f66f4af89edfe 100644 (file)
@@ -58,4 +58,31 @@ config EFI_PCDP
 
          See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf>
 
+config DELL_RBU
+       tristate "BIOS update support for DELL systems via sysfs"
+       select FW_LOADER
+       help
+        Say m if you want to have the option of updating the BIOS for your
+        DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
+        supporting application to comunicate with the BIOS regarding the new
+        image for the image update to take effect.
+        See <file:Documentation/dell_rbu.txt> for more details on the driver.
+
+config DCDBAS
+       tristate "Dell Systems Management Base Driver"
+       depends on X86 || X86_64
+       default m
+       help
+         The Dell Systems Management Base Driver provides a sysfs interface
+         for systems management software to perform System Management
+         Interrupts (SMIs) and Host Control Actions (system power cycle or
+         power off after OS shutdown) on certain Dell systems.
+
+         See <file:Documentation/dcdbas.txt> for more details on the driver
+         and the Dell systems on which Dell systems management software makes
+         use of this driver.
+
+         Say Y or M here to enable the driver for use by Dell systems
+         management software such as Dell OpenManage.
+
 endmenu
index 90fd0b26db8b0d667b7ac1b9c9c347b1eb3fed74..85429979d0db2a27021a34c5d8199b1dd47754c1 100644 (file)
@@ -4,3 +4,5 @@
 obj-$(CONFIG_EDD)              += edd.o
 obj-$(CONFIG_EFI_VARS)         += efivars.o
 obj-$(CONFIG_EFI_PCDP)         += pcdp.o
+obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
+obj-$(CONFIG_DCDBAS)           += dcdbas.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
new file mode 100644 (file)
index 0000000..955537f
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ *  dcdbas.c: Dell Systems Management Base Driver
+ *
+ *  The Dell Systems Management Base Driver provides a sysfs interface for
+ *  systems management software to perform System Management Interrupts (SMIs)
+ *  and Host Control Actions (power cycle or power off after OS shutdown) on
+ *  Dell systems.
+ *
+ *  See Documentation/dcdbas.txt for more information.
+ *
+ *  Copyright (C) 1995-2005 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#include "dcdbas.h"
+
+#define DRIVER_NAME            "dcdbas"
+#define DRIVER_VERSION         "5.6.0-1"
+#define DRIVER_DESCRIPTION     "Dell Systems Management Base Driver"
+
+static struct platform_device *dcdbas_pdev;
+
+static u8 *smi_data_buf;
+static dma_addr_t smi_data_buf_handle;
+static unsigned long smi_data_buf_size;
+static u32 smi_data_buf_phys_addr;
+static DECLARE_MUTEX(smi_data_lock);
+
+static unsigned int host_control_action;
+static unsigned int host_control_smi_type;
+static unsigned int host_control_on_shutdown;
+
+/**
+ * smi_data_buf_free: free SMI data buffer
+ */
+static void smi_data_buf_free(void)
+{
+       if (!smi_data_buf)
+               return;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+                         smi_data_buf_handle);
+       smi_data_buf = NULL;
+       smi_data_buf_handle = 0;
+       smi_data_buf_phys_addr = 0;
+       smi_data_buf_size = 0;
+}
+
+/**
+ * smi_data_buf_realloc: grow SMI data buffer if needed
+ */
+static int smi_data_buf_realloc(unsigned long size)
+{
+       void *buf;
+       dma_addr_t handle;
+
+       if (smi_data_buf_size >= size)
+               return 0;
+
+       if (size > MAX_SMI_DATA_BUF_SIZE)
+               return -EINVAL;
+
+       /* new buffer is needed */
+       buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
+       if (!buf) {
+               dev_dbg(&dcdbas_pdev->dev,
+                       "%s: failed to allocate memory size %lu\n",
+                       __FUNCTION__, size);
+               return -ENOMEM;
+       }
+       /* memory zeroed by dma_alloc_coherent */
+
+       if (smi_data_buf)
+               memcpy(buf, smi_data_buf, smi_data_buf_size);
+
+       /* free any existing buffer */
+       smi_data_buf_free();
+
+       /* set up new buffer for use */
+       smi_data_buf = buf;
+       smi_data_buf_handle = handle;
+       smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
+       smi_data_buf_size = size;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       return 0;
+}
+
+static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
+}
+
+static ssize_t smi_data_buf_size_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       return sprintf(buf, "%lu\n", smi_data_buf_size);
+}
+
+static ssize_t smi_data_buf_size_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       unsigned long buf_size;
+       ssize_t ret;
+
+       buf_size = simple_strtoul(buf, NULL, 10);
+
+       /* make sure SMI data buffer is at least buf_size */
+       down(&smi_data_lock);
+       ret = smi_data_buf_realloc(buf_size);
+       up(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
+                            size_t count)
+{
+       size_t max_read;
+       ssize_t ret;
+
+       down(&smi_data_lock);
+
+       if (pos >= smi_data_buf_size) {
+               ret = 0;
+               goto out;
+       }
+
+       max_read = smi_data_buf_size - pos;
+       ret = min(max_read, count);
+       memcpy(buf, smi_data_buf + pos, ret);
+out:
+       up(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
+                             size_t count)
+{
+       ssize_t ret;
+
+       down(&smi_data_lock);
+
+       ret = smi_data_buf_realloc(pos + count);
+       if (ret)
+               goto out;
+
+       memcpy(smi_data_buf + pos, buf, count);
+       ret = count;
+out:
+       up(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t host_control_action_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_action);
+}
+
+static ssize_t host_control_action_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       ssize_t ret;
+
+       /* make sure buffer is available for host control command */
+       down(&smi_data_lock);
+       ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
+       up(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       host_control_action = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_smi_type_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_smi_type);
+}
+
+static ssize_t host_control_smi_type_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t count)
+{
+       host_control_smi_type = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_on_shutdown_show(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_on_shutdown);
+}
+
+static ssize_t host_control_on_shutdown_store(struct device *dev,
+                                             struct device_attribute *attr,
+                                             const char *buf, size_t count)
+{
+       host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+/**
+ * smi_request: generate SMI request
+ *
+ * Called with smi_data_lock.
+ */
+static int smi_request(struct smi_cmd *smi_cmd)
+{
+       cpumask_t old_mask;
+       int ret = 0;
+
+       if (smi_cmd->magic != SMI_CMD_MAGIC) {
+               dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+                        __FUNCTION__);
+               return -EBADR;
+       }
+
+       /* SMI requires CPU 0 */
+       old_mask = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(0));
+       if (smp_processor_id() != 0) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+                       __FUNCTION__);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* generate SMI */
+       asm volatile (
+               "outb %b0,%w1"
+               : /* no output args */
+               : "a" (smi_cmd->command_code),
+                 "d" (smi_cmd->command_address),
+                 "b" (smi_cmd->ebx),
+                 "c" (smi_cmd->ecx)
+               : "memory"
+       );
+
+out:
+       set_cpus_allowed(current, old_mask);
+       return ret;
+}
+
+/**
+ * smi_request_store:
+ *
+ * The valid values are:
+ * 0: zero SMI data buffer
+ * 1: generate calling interface SMI
+ * 2: generate raw SMI
+ *
+ * User application writes smi_cmd to smi_data before telling driver
+ * to generate SMI.
+ */
+static ssize_t smi_request_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct smi_cmd *smi_cmd;
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       ssize_t ret;
+
+       down(&smi_data_lock);
+
+       if (smi_data_buf_size < sizeof(struct smi_cmd)) {
+               ret = -ENODEV;
+               goto out;
+       }
+       smi_cmd = (struct smi_cmd *)smi_data_buf;
+
+       switch (val) {
+       case 2:
+               /* Raw SMI */
+               ret = smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 1:
+               /* Calling Interface SMI */
+               smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
+               ret = smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 0:
+               memset(smi_data_buf, 0, smi_data_buf_size);
+               ret = count;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       up(&smi_data_lock);
+       return ret;
+}
+
+/**
+ * host_control_smi: generate host control SMI
+ *
+ * Caller must set up the host control command in smi_data_buf.
+ */
+static int host_control_smi(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 *data;
+       unsigned long flags;
+       u32 num_ticks;
+       s8 cmd_status;
+       u8 index;
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+       apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
+
+       switch (host_control_smi_type) {
+       case HC_SMITYPE_TYPE1:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1300_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
+                       outb(*data,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
+               }
+
+               /* first set status to -1 as called by spec */
+               cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
+               outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
+
+               /* generate SMM call */
+               outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
+                      == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       case HC_SMITYPE_TYPE2:
+       case HC_SMITYPE_TYPE3:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1400_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
+                       outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
+               }
+
+               /* generate SMM call */
+               if (host_control_smi_type == HC_SMITYPE_TYPE3)
+                       outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               else
+                       outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
+
+               /* restore RTC index pointer since it was written to above */
+               CMOS_READ(RTC_REG_C);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* read control port back to serialize write */
+               cmd_status = inb(PE1400_APM_CONTROL_PORT);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       default:
+               dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+                       __FUNCTION__, host_control_smi_type);
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
+/**
+ * dcdbas_host_control: initiate host control
+ *
+ * This function is called by the driver after the system has
+ * finished shutting down if the user application specified a
+ * host control action to perform on shutdown.  It is safe to
+ * use smi_data_buf at this point because the system has finished
+ * shutting down and no userspace apps are running.
+ */
+static void dcdbas_host_control(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 action;
+
+       if (host_control_action == HC_ACTION_NONE)
+               return;
+
+       action = host_control_action;
+       host_control_action = HC_ACTION_NONE;
+
+       if (!smi_data_buf) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__);
+               return;
+       }
+
+       if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+                       __FUNCTION__);
+               return;
+       }
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+
+       /* power off takes precedence */
+       if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
+               host_control_smi();
+       } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
+               host_control_smi();
+       }
+}
+
+/**
+ * dcdbas_reboot_notify: handle reboot notification for host control
+ */
+static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+                               void *unused)
+{
+       static unsigned int notify_cnt = 0;
+
+       switch (code) {
+       case SYS_DOWN:
+       case SYS_HALT:
+       case SYS_POWER_OFF:
+               if (host_control_on_shutdown) {
+                       /* firmware is going to perform host control action */
+                       if (++notify_cnt == 2) {
+                               printk(KERN_WARNING
+                                      "Please wait for shutdown "
+                                      "action to complete...\n");
+                               dcdbas_host_control();
+                       }
+                       /*
+                        * register again and initiate the host control
+                        * action on the second notification to allow
+                        * everyone that registered to be notified
+                        */
+                       register_reboot_notifier(nb);
+               }
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block dcdbas_reboot_nb = {
+       .notifier_call = dcdbas_reboot_notify,
+       .next = NULL,
+       .priority = 0
+};
+
+static DCDBAS_BIN_ATTR_RW(smi_data);
+
+static struct bin_attribute *dcdbas_bin_attrs[] = {
+       &bin_attr_smi_data,
+       NULL
+};
+
+static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
+static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
+static DCDBAS_DEV_ATTR_WO(smi_request);
+static DCDBAS_DEV_ATTR_RW(host_control_action);
+static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
+static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
+
+static struct device_attribute *dcdbas_dev_attrs[] = {
+       &dev_attr_smi_data_buf_size,
+       &dev_attr_smi_data_buf_phys_addr,
+       &dev_attr_smi_request,
+       &dev_attr_host_control_action,
+       &dev_attr_host_control_smi_type,
+       &dev_attr_host_control_on_shutdown,
+       NULL
+};
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+       int i;
+
+       host_control_action = HC_ACTION_NONE;
+       host_control_smi_type = HC_SMITYPE_NONE;
+
+       dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+       if (IS_ERR(dcdbas_pdev))
+               return PTR_ERR(dcdbas_pdev);
+
+       /*
+        * BIOS SMI calls require buffer addresses be in 32-bit address space.
+        * This is done by setting the DMA mask below.
+        */
+       dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
+       dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
+
+       register_reboot_notifier(&dcdbas_reboot_nb);
+
+       for (i = 0; dcdbas_bin_attrs[i]; i++)
+               sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
+                                     dcdbas_bin_attrs[i]);
+
+       for (i = 0; dcdbas_dev_attrs[i]; i++)
+               device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
+
+       dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
+                DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+       return 0;
+}
+
+/**
+ * dcdbas_exit: perform driver cleanup
+ */
+static void __exit dcdbas_exit(void)
+{
+       platform_device_unregister(dcdbas_pdev);
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
+       smi_data_buf_free();
+}
+
+module_init(dcdbas_init);
+module_exit(dcdbas_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Dell Inc.");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
new file mode 100644 (file)
index 0000000..58a8518
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  dcdbas.h: Definitions for Dell Systems Management Base driver
+ *
+ *  Copyright (C) 1995-2005 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#ifndef _DCDBAS_H_
+#define _DCDBAS_H_
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define MAX_SMI_DATA_BUF_SIZE                  (256 * 1024)
+
+#define HC_ACTION_NONE                         (0)
+#define HC_ACTION_HOST_CONTROL_POWEROFF                BIT(1)
+#define HC_ACTION_HOST_CONTROL_POWERCYCLE      BIT(2)
+
+#define HC_SMITYPE_NONE                                (0)
+#define HC_SMITYPE_TYPE1                       (1)
+#define HC_SMITYPE_TYPE2                       (2)
+#define HC_SMITYPE_TYPE3                       (3)
+
+#define ESM_APM_CMD                            (0x0A0)
+#define ESM_APM_POWER_CYCLE                    (0x10)
+#define ESM_STATUS_CMD_UNSUCCESSFUL            (-1)
+
+#define CMOS_BASE_PORT                         (0x070)
+#define CMOS_PAGE1_INDEX_PORT                  (0)
+#define CMOS_PAGE1_DATA_PORT                   (1)
+#define CMOS_PAGE2_INDEX_PORT_PIIX4            (2)
+#define CMOS_PAGE2_DATA_PORT_PIIX4             (3)
+#define PE1400_APM_CONTROL_PORT                        (0x0B0)
+#define PCAT_APM_CONTROL_PORT                  (0x0B2)
+#define PCAT_APM_STATUS_PORT                   (0x0B3)
+#define PE1300_CMOS_CMD_STRUCT_PTR             (0x38)
+#define PE1400_CMOS_CMD_STRUCT_PTR             (0x70)
+
+#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN       (14)
+#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM                (16)
+
+#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING       (10000)
+#define EXPIRED_TIMER                          (0)
+
+#define SMI_CMD_MAGIC                          (0x534D4931)
+
+#define DCDBAS_DEV_ATTR_RW(_name) \
+       DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
+
+#define DCDBAS_DEV_ATTR_RO(_name) \
+       DEVICE_ATTR(_name,0400,_name##_show,NULL);
+
+#define DCDBAS_DEV_ATTR_WO(_name) \
+       DEVICE_ATTR(_name,0200,NULL,_name##_store);
+
+#define DCDBAS_BIN_ATTR_RW(_name) \
+struct bin_attribute bin_attr_##_name = { \
+       .attr =  { .name = __stringify(_name), \
+                  .mode = 0600, \
+                  .owner = THIS_MODULE }, \
+       .read =  _name##_read, \
+       .write = _name##_write, \
+}
+
+struct smi_cmd {
+       __u32 magic;
+       __u32 ebx;
+       __u32 ecx;
+       __u16 command_address;
+       __u8 command_code;
+       __u8 reserved;
+       __u8 command_buffer[1];
+} __attribute__ ((packed));
+
+struct apm_cmd {
+       __u8 command;
+       __s8 status;
+       __u16 reserved;
+       union {
+               struct {
+                       __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
+               } __attribute__ ((packed)) shortreq;
+
+               struct {
+                       __u16 num_sg_entries;
+                       struct {
+                               __u32 size;
+                               __u64 addr;
+                       } __attribute__ ((packed))
+                           sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
+               } __attribute__ ((packed)) longreq;
+       } __attribute__ ((packed)) parameters;
+} __attribute__ ((packed));
+
+#endif /* _DCDBAS_H_ */
+
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
new file mode 100644 (file)
index 0000000..3b865f3
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * dell_rbu.c
+ * Bios Update driver for Dell systems
+ * Author: Dell Inc
+ *         Abhay Salunke <abhay_salunke@dell.com>
+ *
+ * Copyright (C) 2005 Dell Inc.
+ *
+ * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
+ * creating entries in the /sys file systems on Linux 2.6 and higher
+ * kernels. The driver supports two mechanism to update the BIOS namely
+ * contiguous and packetized. Both these methods still require having some
+ * application to set the CMOS bit indicating the BIOS to update itself
+ * after a reboot.
+ *
+ * Contiguous method:
+ * This driver writes the incoming data in a monolithic image by allocating
+ * contiguous physical pages large enough to accommodate the incoming BIOS
+ * image size.
+ *
+ * Packetized method:
+ * The driver writes the incoming packet image by allocating a new packet
+ * on every time the packet data is written. This driver requires an
+ * application to break the BIOS image in to fixed sized packet chunks.
+ *
+ * See Documentation/dell_rbu.txt for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+
+MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
+MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+
+#define BIOS_SCAN_LIMIT 0xffffffff
+#define MAX_IMAGE_LENGTH 16
+static struct _rbu_data {
+       void *image_update_buffer;
+       unsigned long image_update_buffer_size;
+       unsigned long bios_image_size;
+       int image_update_ordernum;
+       int dma_alloc;
+       spinlock_t lock;
+       unsigned long packet_read_count;
+       unsigned long packet_write_count;
+       unsigned long num_packets;
+       unsigned long packetsize;
+} rbu_data;
+
+static char image_type[MAX_IMAGE_LENGTH] = "mono";
+module_param_string(image_type, image_type, sizeof(image_type), 0);
+MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
+
+struct packet_data {
+       struct list_head list;
+       size_t length;
+       void *data;
+       int ordernum;
+};
+
+static struct packet_data packet_data_head;
+
+static struct platform_device *rbu_device;
+static int context;
+static dma_addr_t dell_rbu_dmaaddr;
+
+static void init_packet_head(void)
+{
+       INIT_LIST_HEAD(&packet_data_head.list);
+       rbu_data.packet_write_count = 0;
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.packetsize = 0;
+}
+
+static int fill_last_packet(void *data, size_t length)
+{
+       struct list_head *ptemp_list;
+       struct packet_data *packet = NULL;
+       int packet_count = 0;
+
+       pr_debug("fill_last_packet: entry \n");
+
+       if (!rbu_data.num_packets) {
+               pr_debug("fill_last_packet: num_packets=0\n");
+               return -ENOMEM;
+       }
+
+       packet_count = rbu_data.num_packets;
+
+       ptemp_list = (&packet_data_head.list)->prev;
+
+       packet = list_entry(ptemp_list, struct packet_data, list);
+
+       if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
+               pr_debug("dell_rbu:%s: packet size data "
+                        "overrun\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       pr_debug("fill_last_packet : buffer = %p\n", packet->data);
+
+       memcpy((packet->data + rbu_data.packet_write_count), data, length);
+
+       if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) {
+               /*
+                * this was the last data chunk in the packet
+                * so reinitialize the packet data counter to zero
+                */
+               rbu_data.packet_write_count = 0;
+       } else
+               rbu_data.packet_write_count += length;
+
+       pr_debug("fill_last_packet: exit \n");
+       return 0;
+}
+
+static int create_packet(size_t length)
+{
+       struct packet_data *newpacket;
+       int ordernum = 0;
+
+       pr_debug("create_packet: entry \n");
+
+       if (!rbu_data.packetsize) {
+               pr_debug("create_packet: packetsize not specified\n");
+               return -EINVAL;
+       }
+
+       newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+       if (!newpacket) {
+               printk(KERN_WARNING
+                      "dell_rbu:%s: failed to allocate new "
+                      "packet\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       ordernum = get_order(length);
+       /*
+        * there is no upper limit on memory
+        * address for packetized mechanism
+        */
+       newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
+                                                           ordernum);
+
+       pr_debug("create_packet: newpacket %p\n", newpacket->data);
+
+       if (!newpacket->data) {
+               printk(KERN_WARNING
+                      "dell_rbu:%s: failed to allocate new "
+                      "packet\n", __FUNCTION__);
+               kfree(newpacket);
+               return -ENOMEM;
+       }
+
+       newpacket->ordernum = ordernum;
+       ++rbu_data.num_packets;
+       /*
+        * initialize the newly created packet headers
+        */
+       INIT_LIST_HEAD(&newpacket->list);
+       list_add_tail(&newpacket->list, &packet_data_head.list);
+       /*
+        * packets have fixed size
+        */
+       newpacket->length = rbu_data.packetsize;
+
+       pr_debug("create_packet: exit \n");
+
+       return 0;
+}
+
+static int packetize_data(void *data, size_t length)
+{
+       int rc = 0;
+
+       if (!rbu_data.packet_write_count) {
+               if ((rc = create_packet(length)))
+                       return rc;
+       }
+       if ((rc = fill_last_packet(data, length)))
+               return rc;
+
+       return rc;
+}
+
+static int
+do_packet_read(char *data, struct list_head *ptemp_list,
+              int length, int bytes_read, int *list_read_count)
+{
+       void *ptemp_buf;
+       struct packet_data *newpacket = NULL;
+       int bytes_copied = 0;
+       int j = 0;
+
+       newpacket = list_entry(ptemp_list, struct packet_data, list);
+       *list_read_count += newpacket->length;
+
+       if (*list_read_count > bytes_read) {
+               /* point to the start of unread data */
+               j = newpacket->length - (*list_read_count - bytes_read);
+               /* point to the offset in the packet buffer */
+               ptemp_buf = (u8 *) newpacket->data + j;
+               /*
+                * check if there is enough room in
+                * * the incoming buffer
+                */
+               if (length > (*list_read_count - bytes_read))
+                       /*
+                        * copy what ever is there in this
+                        * packet and move on
+                        */
+                       bytes_copied = (*list_read_count - bytes_read);
+               else
+                       /* copy the remaining */
+                       bytes_copied = length;
+               memcpy(data, ptemp_buf, bytes_copied);
+       }
+       return bytes_copied;
+}
+
+static int packet_read_list(char *data, size_t * pread_length)
+{
+       struct list_head *ptemp_list;
+       int temp_count = 0;
+       int bytes_copied = 0;
+       int bytes_read = 0;
+       int remaining_bytes = 0;
+       char *pdest = data;
+
+       /* check if we have any packets */
+       if (0 == rbu_data.num_packets)
+               return -ENOMEM;
+
+       remaining_bytes = *pread_length;
+       bytes_read = rbu_data.packet_read_count;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               bytes_copied = do_packet_read(pdest, ptemp_list,
+                                             remaining_bytes, bytes_read,
+                                             &temp_count);
+               remaining_bytes -= bytes_copied;
+               bytes_read += bytes_copied;
+               pdest += bytes_copied;
+               /*
+                * check if we reached end of buffer before reaching the
+                * last packet
+                */
+               if (remaining_bytes == 0)
+                       break;
+
+               ptemp_list = ptemp_list->next;
+       }
+       /*finally set the bytes read */
+       *pread_length = bytes_read - rbu_data.packet_read_count;
+       rbu_data.packet_read_count = bytes_read;
+       return 0;
+}
+
+static void packet_empty_list(void)
+{
+       struct list_head *ptemp_list;
+       struct list_head *pnext_list;
+       struct packet_data *newpacket;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               newpacket =
+                   list_entry(ptemp_list, struct packet_data, list);
+               pnext_list = ptemp_list->next;
+               list_del(ptemp_list);
+               ptemp_list = pnext_list;
+               /*
+                * zero out the RBU packet memory before freeing
+                * to make sure there are no stale RBU packets left in memory
+                */
+               memset(newpacket->data, 0, rbu_data.packetsize);
+               free_pages((unsigned long)newpacket->data,
+                          newpacket->ordernum);
+               kfree(newpacket);
+       }
+       rbu_data.packet_write_count = 0;
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.packetsize = 0;
+}
+
+/*
+ * img_update_free: Frees the buffer allocated for storing BIOS image
+ * Always called with lock held and returned with lock held
+ */
+static void img_update_free(void)
+{
+       if (!rbu_data.image_update_buffer)
+               return;
+       /*
+        * zero out this buffer before freeing it to get rid of any stale
+        * BIOS image copied in memory.
+        */
+       memset(rbu_data.image_update_buffer, 0,
+              rbu_data.image_update_buffer_size);
+       if (rbu_data.dma_alloc == 1)
+               dma_free_coherent(NULL, rbu_data.bios_image_size,
+                                 rbu_data.image_update_buffer,
+                                 dell_rbu_dmaaddr);
+       else
+               free_pages((unsigned long)rbu_data.image_update_buffer,
+                          rbu_data.image_update_ordernum);
+
+       /*
+        * Re-initialize the rbu_data variables after a free
+        */
+       rbu_data.image_update_ordernum = -1;
+       rbu_data.image_update_buffer = NULL;
+       rbu_data.image_update_buffer_size = 0;
+       rbu_data.bios_image_size = 0;
+       rbu_data.dma_alloc = 0;
+}
+
+/*
+ * img_update_realloc: This function allocates the contiguous pages to
+ * accommodate the requested size of data. The memory address and size
+ * values are stored globally and on every call to this function the new
+ * size is checked to see if more data is required than the existing size.
+ * If true the previous memory is freed and new allocation is done to
+ * accommodate the new size. If the incoming size is less then than the
+ * already allocated size, then that memory is reused. This function is
+ * called with lock held and returns with lock held.
+ */
+static int img_update_realloc(unsigned long size)
+{
+       unsigned char *image_update_buffer = NULL;
+       unsigned long rc;
+       unsigned long img_buf_phys_addr;
+       int ordernum;
+       int dma_alloc = 0;
+
+       /*
+        * check if the buffer of sufficient size has been
+        * already allocated
+        */
+       if (rbu_data.image_update_buffer_size >= size) {
+               /*
+                * check for corruption
+                */
+               if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+                       printk(KERN_ERR "dell_rbu:%s: corruption "
+                              "check failed\n", __FUNCTION__);
+                       return -EINVAL;
+               }
+               /*
+                * we have a valid pre-allocated buffer with
+                * sufficient size
+                */
+               return 0;
+       }
+
+       /*
+        * free any previously allocated buffer
+        */
+       img_update_free();
+
+       spin_unlock(&rbu_data.lock);
+
+       ordernum = get_order(size);
+       image_update_buffer =
+           (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
+
+       img_buf_phys_addr =
+           (unsigned long)virt_to_phys(image_update_buffer);
+
+       if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+               free_pages((unsigned long)image_update_buffer, ordernum);
+               ordernum = -1;
+               image_update_buffer = dma_alloc_coherent(NULL, size,
+                                                        &dell_rbu_dmaaddr,
+                                                        GFP_KERNEL);
+               dma_alloc = 1;
+       }
+
+       spin_lock(&rbu_data.lock);
+
+       if (image_update_buffer != NULL) {
+               rbu_data.image_update_buffer = image_update_buffer;
+               rbu_data.image_update_buffer_size = size;
+               rbu_data.bios_image_size =
+                   rbu_data.image_update_buffer_size;
+               rbu_data.image_update_ordernum = ordernum;
+               rbu_data.dma_alloc = dma_alloc;
+               rc = 0;
+       } else {
+               pr_debug("Not enough memory for image update:"
+                        "size = %ld\n", size);
+               rc = -ENOMEM;
+       }
+
+       return rc;
+}
+
+static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
+{
+       int retval;
+       size_t bytes_left;
+       size_t data_length;
+       char *ptempBuf = buffer;
+       unsigned long imagesize;
+
+       /* check to see if we have something to return */
+       if (rbu_data.num_packets == 0) {
+               pr_debug("read_packet_data: no packets written\n");
+               retval = -ENOMEM;
+               goto read_rbu_data_exit;
+       }
+
+       imagesize = rbu_data.num_packets * rbu_data.packetsize;
+
+       if (pos > imagesize) {
+               retval = 0;
+               printk(KERN_WARNING "dell_rbu:read_packet_data: "
+                      "data underrun\n");
+               goto read_rbu_data_exit;
+       }
+
+       bytes_left = imagesize - pos;
+       data_length = min(bytes_left, count);
+
+       if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
+               goto read_rbu_data_exit;
+
+       if ((pos + count) > imagesize) {
+               rbu_data.packet_read_count = 0;
+               /* this was the last copy */
+               retval = bytes_left;
+       } else
+               retval = count;
+
+      read_rbu_data_exit:
+       return retval;
+}
+
+static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
+{
+       unsigned char *ptemp = NULL;
+       size_t bytes_left = 0;
+       size_t data_length = 0;
+       ssize_t ret_count = 0;
+
+       /* check to see if we have something to return */
+       if ((rbu_data.image_update_buffer == NULL) ||
+           (rbu_data.bios_image_size == 0)) {
+               pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
+                        "bios_image_size %lu\n",
+                        rbu_data.image_update_buffer,
+                        rbu_data.bios_image_size);
+               ret_count = -ENOMEM;
+               goto read_rbu_data_exit;
+       }
+
+       if (pos > rbu_data.bios_image_size) {
+               ret_count = 0;
+               goto read_rbu_data_exit;
+       }
+
+       bytes_left = rbu_data.bios_image_size - pos;
+       data_length = min(bytes_left, count);
+
+       ptemp = rbu_data.image_update_buffer;
+       memcpy(buffer, (ptemp + pos), data_length);
+
+       if ((pos + count) > rbu_data.bios_image_size)
+               /* this was the last copy */
+               ret_count = bytes_left;
+       else
+               ret_count = count;
+      read_rbu_data_exit:
+       return ret_count;
+}
+
+static ssize_t
+read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
+{
+       ssize_t ret_count = 0;
+
+       spin_lock(&rbu_data.lock);
+
+       if (!strcmp(image_type, "mono"))
+               ret_count = read_rbu_mono_data(buffer, pos, count);
+       else if (!strcmp(image_type, "packet"))
+               ret_count = read_packet_data(buffer, pos, count);
+       else
+               pr_debug("read_rbu_data: invalid image type specified\n");
+
+       spin_unlock(&rbu_data.lock);
+       return ret_count;
+}
+
+static ssize_t
+read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
+                   size_t count)
+{
+       int size = 0;
+       if (!pos)
+               size = sprintf(buffer, "%s\n", image_type);
+       return size;
+}
+
+static ssize_t
+write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
+                    size_t count)
+{
+       int rc = count;
+       spin_lock(&rbu_data.lock);
+
+       if (strlen(buffer) < MAX_IMAGE_LENGTH)
+               sscanf(buffer, "%s", image_type);
+       else
+               printk(KERN_WARNING "dell_rbu: image_type is invalid"
+                      "max chars = %d, \n incoming str--%s-- \n",
+                      MAX_IMAGE_LENGTH, buffer);
+
+       /* we must free all previous allocations */
+       packet_empty_list();
+       img_update_free();
+
+       spin_unlock(&rbu_data.lock);
+       return rc;
+
+}
+
+static struct bin_attribute rbu_data_attr = {
+       .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+       .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+       .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+       .read = read_rbu_image_type,
+       .write = write_rbu_image_type,
+};
+
+static void callbackfn_rbu(const struct firmware *fw, void *context)
+{
+       int rc = 0;
+
+       if (!fw || !fw->size)
+               return;
+
+       spin_lock(&rbu_data.lock);
+       if (!strcmp(image_type, "mono")) {
+               if (!img_update_realloc(fw->size))
+                       memcpy(rbu_data.image_update_buffer,
+                              fw->data, fw->size);
+       } else if (!strcmp(image_type, "packet")) {
+               if (!rbu_data.packetsize)
+                       rbu_data.packetsize = fw->size;
+               else if (rbu_data.packetsize != fw->size) {
+                       packet_empty_list();
+                       rbu_data.packetsize = fw->size;
+               }
+               packetize_data(fw->data, fw->size);
+       } else
+               pr_debug("invalid image type specified.\n");
+       spin_unlock(&rbu_data.lock);
+
+       rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+                                    "dell_rbu", &rbu_device->dev,
+                                    &context, callbackfn_rbu);
+       if (rc)
+               printk(KERN_ERR
+                      "dell_rbu:%s request_firmware_nowait failed"
+                      " %d\n", __FUNCTION__, rc);
+}
+
+static int __init dcdrbu_init(void)
+{
+       int rc = 0;
+       spin_lock_init(&rbu_data.lock);
+
+       init_packet_head();
+       rbu_device =
+           platform_device_register_simple("dell_rbu", -1, NULL, 0);
+       if (!rbu_device) {
+               printk(KERN_ERR
+                      "dell_rbu:%s:platform_device_register_simple "
+                      "failed\n", __FUNCTION__);
+               return -EIO;
+       }
+
+       sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+       sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+
+       rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+                                    "dell_rbu", &rbu_device->dev,
+                                    &context, callbackfn_rbu);
+       if (rc)
+               printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
+                      " failed %d\n", __FUNCTION__, rc);
+
+       return rc;
+
+}
+
+static __exit void dcdrbu_exit(void)
+{
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       img_update_free();
+       spin_unlock(&rbu_data.lock);
+       platform_device_unregister(rbu_device);
+}
+
+module_exit(dcdrbu_exit);
+module_init(dcdrbu_init);
index 354a262956725ebe8812908bf3a5341e593bc171..8ee56d4b38910486b42746c953d9f4e6cff5135a 100644 (file)
@@ -1489,7 +1489,7 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
        if (the_transceiver)
                return 0;
 
-       isp = kcalloc(1, sizeof *isp, GFP_KERNEL);
+       isp = kzalloc(sizeof *isp, GFP_KERNEL);
        if (!isp)
                return 0;
 
index bebcc47ab06c2614c0d141d522c7731a212afa08..b23322523ef57b1cf147e4368239487e55ef15bc 100644 (file)
@@ -1068,6 +1068,8 @@ static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
        struct unit_directory *ud;
        int i = 0;
        int length = 0;
+       /* ieee1394:venNmoNspNverN */
+       char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
 
        if (!cdev)
                return -ENODEV;
@@ -1094,6 +1096,12 @@ do {                                                             \
        PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);
        PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);
        PUT_ENVP("VERSION=%06x", ud->version);
+       snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
+                       ud->vendor_id,
+                       ud->model_id,
+                       ud->specifier_id,
+                       ud->version);
+       PUT_ENVP("MODALIAS=%s", buf);
 
 #undef PUT_ENVP
 
index fae1c2dcee51660650921523ae85e1c5748b26fe..211ba3223f65cc7c2d78f77d3cc84ab50d3639cd 100644 (file)
@@ -463,7 +463,7 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
                return NULL;
 
        for (i = 0; i < len; i++) {
-               element = kcalloc(1, sizeof(struct port_table_attribute),
+               element = kzalloc(sizeof(struct port_table_attribute),
                                  GFP_KERNEL);
                if (!element)
                        goto err;
index f8b278d3559bc2b3553d8949192ee1ce6494bc78..19c14c4beb44e2537b2207435e5a625efb9a5f2f 100644 (file)
@@ -393,6 +393,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                                case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
                                                case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
                                                case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
+                                               case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
                                                default: return -EINVAL;
                                        }
                                        len = NBITS(len) * sizeof(long);
@@ -421,6 +422,13 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                        return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
                                }
 
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
+                                       int len;
+                                       len = NBITS(SW_MAX) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
+                               }
+
                                if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
                                        int len;
                                        if (!dev->name) return -ENOENT;
index a0118038330a9702f0fd7a03e8269920575f8d18..462f8d300aae5629719c58a983627fed065879a5 100644 (file)
@@ -75,7 +75,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
        if (!request_region(ioport, iolen, "emu10k1-gp"))
                return -EBUSY;
 
-       emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+       emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!emu || !port) {
                printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
index 57615bc639061384d7243230620cd542952213f1..47e93daa0fa7c498aec5ae237135126d0ef2e040 100644 (file)
@@ -83,7 +83,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
        struct fm801_gp *gp;
        struct gameport *port;
 
-       gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+       gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!gp || !port) {
                printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
index 70f051894a3cfa4d50f5dda7268c6af26e63b96f..d2e55dc956bafd3477ebd4e7ea448263b6375fcd 100644 (file)
@@ -142,7 +142,7 @@ static int ns558_isa_probe(int io)
                        return -EBUSY;
        }
 
-       ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+       ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!ns558 || !port) {
                printk(KERN_ERR "ns558: Memory allocation failed.\n");
@@ -215,7 +215,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
        if (!request_region(ioport, iolen, "ns558-pnp"))
                return -EBUSY;
 
-       ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+       ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!ns558 || !port) {
                printk(KERN_ERR "ns558: Memory allocation failed\n");
index a275211c8e1e3434a2788771b63b68077807892f..88636a204525e84862972ea7034c02ae020ae4bb 100644 (file)
@@ -89,6 +89,15 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
 
                        break;
 
+               case EV_SW:
+
+                       if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
+                               return;
+
+                       change_bit(code, dev->sw);
+
+                       break;
+
                case EV_ABS:
 
                        if (code > ABS_MAX || !test_bit(code, dev->absbit))
@@ -402,6 +411,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
        SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
        SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
        SPRINTF_BIT_A2(ffbit,  "FF=",  FF_MAX, EV_FF);
+       SPRINTF_BIT_A2(swbit,  "SW=",  SW_MAX, EV_SW);
 
        envp[i++] = NULL;
 
@@ -490,6 +500,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
                SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
                SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
                SPRINTF_BIT_B2(ffbit,  "FF=",  FF_MAX, EV_FF);
+               SPRINTF_BIT_B2(swbit,  "SW=",  SW_MAX, EV_SW);
 
                len += sprintf(buf + len, "\n");
 
index bf34f75b9467f6650c5447a020f562787bccacfb..bf65430181faf0f2ee5db443f950bd35c90963f8 100644 (file)
@@ -269,7 +269,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
        int i;
        int err;
 
-       if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+       if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL)))
                return -ENOMEM;
 
        a3d->gameport = gameport;
index 265962956c63cbf9d924f8bd8518981d10cf2ea5..cf35ae638a0d2c129544d16d90c87c22027e2b4e 100644 (file)
@@ -469,7 +469,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
        int i;
        int err;
 
-       if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+       if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL)))
                return -ENOMEM;
 
        port->gameport = gameport;
index c3a5739030c3ba45d8dd1dda01cd79382faf3478..64b1313a3c66d0c6400dcbd8e35c9f60c0041bd9 100644 (file)
@@ -655,7 +655,7 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
        int i;
        int err;
 
-       if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+       if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
                return - ENOMEM;
 
        err = analog_init_port(gameport, drv, port);
index a6002205328f80d16bf882054f5bfc32f9b806ac..0b2e9fa2657969457dfc2db4c12b39c5984f8966 100644 (file)
@@ -163,7 +163,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
        int i, j;
        int err;
 
-       if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+       if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL)))
                return -ENOMEM;
 
        cobra->gameport = gameport;
index fbd3eed07f90403806e1bce3212781a638e35241..2a3e4bb2da507ef78f9cc33cf88b88e19d262fac 100644 (file)
@@ -572,7 +572,7 @@ static struct db9 __init *db9_probe(int *config, int nargs)
                }
        }
 
-       if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) {
+       if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) {
                parport_put_port(pp);
                return NULL;
        }
index 95bbdd302aad8639bacc4817e6f49b472e749211..5427bf9fc862320261a2c45aebbe53beeb761d00 100644 (file)
@@ -554,7 +554,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
                return NULL;
        }
 
-       if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
+       if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
                parport_put_port(pp);
                return NULL;
        }
index 7d969420066c75c0140eed3ba2d88bc9cf7fedf5..8e4f92b115e6aa8188c70745011e40c71e00ab48 100644 (file)
@@ -242,7 +242,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
        unsigned char data[GF2K_LENGTH];
        int i, err;
 
-       if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
+       if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL)))
                return -ENOMEM;
 
        gf2k->gameport = gameport;
index d1500d2562d67ec99fcaa72de01dac377cf14d23..9d3f910dd568b4cb46f7daf8ee0a6027b7ab5f8a 100644 (file)
@@ -301,7 +301,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
        int i, j, t;
        int err;
 
-       if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+       if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
                return -ENOMEM;
 
        grip->gameport = gameport;
index 0da7bd133ccf39f03e948d60e2bfa19e18b742ea..da17eee6f5741f45cea1d86eca0be7c5045307a9 100644 (file)
@@ -607,7 +607,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
        struct grip_mp *grip;
        int err;
 
-       if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+       if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
                return -ENOMEM;
 
        grip->gameport = gameport;
index f93da7bc082d08622b0859222a87b7e981407304..6a70ec429f063eb28d6f6f251037b695cb794841 100644 (file)
@@ -183,7 +183,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
        int i, t;
        int err;
 
-       if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
+       if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL)))
                return -ENOMEM;
 
        guillemot->gameport = gameport;
index 9d3f8c38cb097391403f44846781a75d4c68d845..d7b3472bd686611a5e30276203ea42778b1ea199 100644 (file)
@@ -212,7 +212,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
        int i, t;
        int err;
 
-       if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
+       if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL)))
                return -ENOMEM;
 
        interact->gameport = gameport;
index 47144a7ed9e750f4682eac415c9d6bf7c8ac1b49..9e0353721a35d8892e96d5a5779075bafb1b92e5 100644 (file)
@@ -590,7 +590,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
 
        comment[0] = 0;
 
-       sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
+       sw = kzalloc(sizeof(struct sw), GFP_KERNEL);
        buf = kmalloc(SW_LENGTH, GFP_KERNEL);
        idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
        if (!sw || !buf || !idbuf) {
index 9eb9954cac6e2584e70ef4c9a9d6646c494e348d..7431efc4330edb090696ea66b78e06e5c4d30378 100644 (file)
@@ -262,7 +262,7 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
        int i, j, k, l, m;
        int err;
 
-       if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+       if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
                return -ENOMEM;
 
        tmdc->gameport = gameport;
index 28100d461cb751c1c1d8b34f4fb5001b970e1b2c..0c5b9c8297cd4ff1afb1c1fe979f962d944a6dca 100644 (file)
@@ -178,7 +178,7 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
                return NULL;
        }
 
-       if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
+       if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) {
                parport_put_port(pp);
                return NULL;
        }
index a8551711e8d60031ffaadbb1e7e632a32f162aed..cd4b6e795013a841399cdcfbb25012990e240054 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/jiffies.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/irq.h>
@@ -32,7 +33,6 @@
 /* zero code, 124 scancodes + 3 hinge combinations */
 #define        NR_SCANCODES            ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
 #define SCAN_INTERVAL          (HZ/10)
-#define CORGIKBD_PRESSED       1
 
 #define HINGE_SCAN_INTERVAL            (HZ/4)
 
@@ -73,25 +73,13 @@ struct corgikbd {
        struct input_dev input;
        char phys[32];
 
-       unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
        spinlock_t lock;
-
        struct timer_list timer;
        struct timer_list htimer;
-};
 
-static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
-{
-       if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
-               corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
-               input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
-               if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
-                       input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
-       } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
-               corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
-               input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
-       }
-}
+       unsigned int suspended;
+       unsigned long suspend_jiffies;
+};
 
 #define KB_DISCHARGE_DELAY     10
 #define KB_ACTIVATE_DELAY      10
@@ -105,36 +93,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c
  */
 static inline void corgikbd_discharge_all(void)
 {
-       // STROBE All HiZ
+       /* STROBE All HiZ */
        GPCR2  = CORGI_GPIO_ALL_STROBE_BIT;
        GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
 }
 
 static inline void corgikbd_activate_all(void)
 {
-       // STROBE ALL -> High
+       /* STROBE ALL -> High */
        GPSR2  = CORGI_GPIO_ALL_STROBE_BIT;
        GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
 
        udelay(KB_DISCHARGE_DELAY);
 
-       // Clear any interrupts we may have triggered when altering the GPIO lines
+       /* Clear any interrupts we may have triggered when altering the GPIO lines */
        GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
        GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
 }
 
 static inline void corgikbd_activate_col(int col)
 {
-       // STROBE col -> High, not col -> HiZ
+       /* STROBE col -> High, not col -> HiZ */
        GPSR2 = CORGI_GPIO_STROBE_BIT(col);
        GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
 }
 
 static inline void corgikbd_reset_col(int col)
 {
-       // STROBE col -> Low
+       /* STROBE col -> Low */
        GPCR2 = CORGI_GPIO_STROBE_BIT(col);
-       // STROBE col -> out, not col -> HiZ
+       /* STROBE col -> out, not col -> HiZ */
        GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
 }
 
@@ -149,10 +137,13 @@ static inline void corgikbd_reset_col(int col)
 /* Scan the hardware keyboard and push any changes up through the input layer */
 static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
 {
-       unsigned int row, col, rowd, scancode;
+       unsigned int row, col, rowd;
        unsigned long flags;
        unsigned int num_pressed;
 
+       if (corgikbd_data->suspended)
+               return;
+
        spin_lock_irqsave(&corgikbd_data->lock, flags);
 
        if (regs)
@@ -173,10 +164,21 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
 
                rowd = GET_ROWS_STATUS(col);
                for (row = 0; row < KB_ROWS; row++) {
+                       unsigned int scancode, pressed;
+
                        scancode = SCANCODE(row, col);
-                       handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
-                       if (rowd & KB_ROWMASK(row))
+                       pressed = rowd & KB_ROWMASK(row);
+
+                       input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
+
+                       if (pressed)
                                num_pressed++;
+
+                       if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
+                                       && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
+                               input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+                               corgikbd_data->suspend_jiffies=jiffies;
+                       }
                }
                corgikbd_reset_col(col);
        }
@@ -221,8 +223,11 @@ static void corgikbd_timer_callback(unsigned long data)
  * The hinge switches generate no interrupt so they need to be
  * monitored by a timer.
  *
- * When we detect changes, we debounce it and then pass the three
- * positions the system can take as keypresses to the input system.
+ * We debounce the switches and pass them to the input system.
+ *
+ *  gprr == 0x00 - Keyboard with Landscape Screen
+ *          0x08 - No Keyboard with Portrait Screen
+ *          0x0c - Keyboard and Screen Closed
  */
 
 #define HINGE_STABLE_COUNT 2
@@ -235,7 +240,7 @@ static void corgikbd_hinge_timer(unsigned long data)
        unsigned long gprr;
        unsigned long flags;
 
-       gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+       gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
        if (gprr != sharpsl_hinge_state) {
                hinge_count = 0;
                sharpsl_hinge_state = gprr;
@@ -244,9 +249,8 @@ static void corgikbd_hinge_timer(unsigned long data)
                if (hinge_count >= HINGE_STABLE_COUNT) {
                        spin_lock_irqsave(&corgikbd_data->lock, flags);
 
-                       handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
-                       handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
-                       handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed  */
+                       input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+                       input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
                        input_sync(&corgikbd_data->input);
 
                        spin_unlock_irqrestore(&corgikbd_data->lock, flags);
@@ -255,19 +259,45 @@ static void corgikbd_hinge_timer(unsigned long data)
        mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
 }
 
+#ifdef CONFIG_PM
+static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+       if (level == SUSPEND_POWER_DOWN) {
+               struct corgikbd *corgikbd = dev_get_drvdata(dev);
+               corgikbd->suspended = 1;
+       }
+       return 0;
+}
+
+static int corgikbd_resume(struct device *dev, uint32_t level)
+{
+       if (level == RESUME_POWER_ON) {
+               struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+               /* Upon resume, ignore the suspend key for a short while */
+               corgikbd->suspend_jiffies=jiffies;
+               corgikbd->suspended = 0;
+       }
+       return 0;
+}
+#else
+#define corgikbd_suspend       NULL
+#define corgikbd_resume                NULL
+#endif
+
 static int __init corgikbd_probe(struct device *dev)
 {
        int i;
        struct corgikbd *corgikbd;
 
-       corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
+       corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
        if (!corgikbd)
                return -ENOMEM;
 
        dev_set_drvdata(dev,corgikbd);
        strcpy(corgikbd->phys, "corgikbd/input0");
 
-       spin_lock_init(corgikbd->lock);
+       spin_lock_init(&corgikbd->lock);
 
        /* Init Keyboard rescan timer */
        init_timer(&corgikbd->timer);
@@ -279,6 +309,8 @@ static int __init corgikbd_probe(struct device *dev)
        corgikbd->htimer.function = corgikbd_hinge_timer;
        corgikbd->htimer.data = (unsigned long) corgikbd;
 
+       corgikbd->suspend_jiffies=jiffies;
+
        init_input_dev(&corgikbd->input);
        corgikbd->input.private = corgikbd;
        corgikbd->input.name = "Corgi Keyboard";
@@ -288,7 +320,7 @@ static int __init corgikbd_probe(struct device *dev)
        corgikbd->input.id.vendor = 0x0001;
        corgikbd->input.id.product = 0x0001;
        corgikbd->input.id.version = 0x0100;
-       corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
+       corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
        corgikbd->input.keycode = corgikbd->keycode;
        corgikbd->input.keycodesize = sizeof(unsigned char);
        corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
@@ -297,6 +329,8 @@ static int __init corgikbd_probe(struct device *dev)
        for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
                set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
        clear_bit(0, corgikbd->input.keybit);
+       set_bit(SW_0, corgikbd->input.swbit);
+       set_bit(SW_1, corgikbd->input.swbit);
 
        input_register_device(&corgikbd->input);
        mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
@@ -343,6 +377,8 @@ static struct device_driver corgikbd_driver = {
        .bus            = &platform_bus_type,
        .probe          = corgikbd_probe,
        .remove         = corgikbd_remove,
+       .suspend        = corgikbd_suspend,
+       .resume         = corgikbd_resume,
 };
 
 static int __devinit corgikbd_init(void)
index 2bb2fe78bdca988f34ccae1cdebf0ba0faff79c5..12bdd3eff923ea32042d76f47110d217c43243f7 100644 (file)
@@ -883,7 +883,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
                psmouse_deactivate(parent);
        }
 
-       if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
+       if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) {
                retval = -ENOMEM;
                goto out;
        }
index 79ca38469159b90abd6d1f52bffb162dbb89968c..1bd88fca05425a9d6ddfb9f52c36d296f832fad2 100644 (file)
@@ -87,7 +87,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL);
+       serport = kzalloc(sizeof(struct serport), GFP_KERNEL);
        if (!serport)
                return -ENOMEM;
 
@@ -165,7 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
        if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
                return -EBUSY;
 
-       serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
+       serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!serio)
                return -ENOMEM;
 
index 3f8b61cfbc37977abc2453a2fab177e1149a410a..5d19261b884fe8f09ebe48432589011080942e41 100644 (file)
@@ -53,11 +53,8 @@ struct corgi_ts {
 
 #define SyncHS()       while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
 #define CCNT(a)                asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
-#define CCNT_ON()      {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-#define CCNT_OFF()     {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-
-#define WAIT_HS_400_VGA                7013U   // 17.615us
-#define WAIT_HS_400_QVGA       16622U  // 41.750us
+#define PMNC_GET(x)    asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
+#define PMNC_SET(x)    asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
 
 
 /* ADS7846 Touch Screen Controller bit definitions */
@@ -69,41 +66,29 @@ struct corgi_ts {
 #define ADSCTRL_STS            (1u << 7)       /* Start Bit */
 
 /* External Functions */
-extern int w100fb_get_xres(void);
-extern int w100fb_get_blanking(void);
-extern int w100fb_get_fastsysclk(void);
+extern unsigned long w100fb_get_hsynclen(struct device *dev);
 extern unsigned int get_clk_frequency_khz(int info);
 
 static unsigned long calc_waittime(void)
 {
-       int w100fb_xres = w100fb_get_xres();
-       unsigned int waittime = 0;
-
-       if (w100fb_xres == 480 || w100fb_xres == 640) {
-               waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
-
-               if (w100fb_get_fastsysclk() == 100)
-                       waittime = waittime * 75 / 100;
-
-               if (w100fb_xres == 640)
-                       waittime *= 3;
+       unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev);
 
-               return waittime;
-       }
-
-       return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
+       if (hsync_len)
+               return get_clk_frequency_khz(0)*1000/hsync_len;
+       else
+               return 0;
 }
 
 static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
 {
+       unsigned long timer1 = 0, timer2, pmnc = 0;
        int pos = 0;
-       unsigned long timer1 = 0, timer2;
-       int dosleep;
 
-       dosleep = !w100fb_get_blanking();
+       if (wait_time && doSend) {
+               PMNC_GET(pmnc);
+               if (!(pmnc & 0x01))
+                       PMNC_SET(0x01);
 
-       if (dosleep && doSend) {
-               CCNT_ON();
                /* polling HSync */
                SyncHS();
                /* get CCNT */
@@ -119,11 +104,11 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
                corgi_ssp_ads7846_put(cmd);
                corgi_ssp_ads7846_get();
 
-               if (dosleep) {
+               if (wait_time) {
                        /* Wait after HSync */
                        CCNT(timer2);
                        if (timer2-timer1 > wait_time) {
-                               /* timeout */
+                               /* too slow - timeout, try again */
                                SyncHS();
                                /* get OSCR */
                                CCNT(timer1);
@@ -134,8 +119,8 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
                                CCNT(timer2);
                }
                corgi_ssp_ads7846_put(cmd);
-               if (dosleep)
-                       CCNT_OFF();
+               if (wait_time && !(pmnc & 0x01))
+                       PMNC_SET(pmnc);
        }
        return pos;
 }
@@ -244,7 +229,7 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 #ifdef CONFIG_PM
-static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+static int corgits_suspend(struct device *dev, pm_message_t state, uint32_t level)
 {
        if (level == SUSPEND_POWER_DOWN) {
                struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
index 17cf7663c58233fda3610b9890d2e663254ba643..26c545fa223be8672a5e3cace0e4377b04af48a2 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
@@ -1242,6 +1241,8 @@ struct IsdnCardState {
 
 #ifdef CONFIG_HISAX_ENTERNOW_PCI
 #define CARD_FN_ENTERNOW_PCI 1
+#else
+#define CARD_FN_ENTERNOW_PCI 0
 #endif
 
 #define TEI_PER_CARD 1
index f47f2b9846d8fc45c55ef777a989316c9908c18e..38619e8cd8230b4c9d893fbb85976a6a9055df2e 100644 (file)
@@ -516,11 +516,11 @@ buffer_full:
 }
 
 int
-isdn_v110_stat_callback(int idx, isdn_ctrl * c)
+isdn_v110_stat_callback(int idx, isdn_ctrl *c)
 {
        isdn_v110_stream *v = NULL;
        int i;
-       int ret;
+       int ret = 0;
 
        if (idx < 0)
                return 0;
index 45754bb6a79994678901f967bc29dc3c91d34d62..9de000131a8a2cb729c9e66858d30ed0d5700088 100644 (file)
@@ -239,6 +239,11 @@ static void vm_dp_init(struct dpages *dp, void *data)
        dp->context_ptr = data;
 }
 
+static void dm_bio_destructor(struct bio *bio)
+{
+       bio_free(bio, _bios);
+}
+
 /*-----------------------------------------------------------------
  * IO routines that accept a list of pages.
  *---------------------------------------------------------------*/
@@ -263,6 +268,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
                bio->bi_bdev = where->bdev;
                bio->bi_end_io = endio;
                bio->bi_private = io;
+               bio->bi_destructor = dm_bio_destructor;
                bio_set_region(bio, region);
 
                /*
index d487d9deb98e1c04ddb4bc152e2a47d880c3332d..930b9fc27953766e94b2ce8869f6228feb5f04b3 100644 (file)
@@ -399,6 +399,11 @@ struct clone_info {
        unsigned short idx;
 };
 
+static void dm_bio_destructor(struct bio *bio)
+{
+       bio_free(bio, dm_set);
+}
+
 /*
  * Creates a little bio that is just does part of a bvec.
  */
@@ -410,6 +415,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
        struct bio_vec *bv = bio->bi_io_vec + idx;
 
        clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set);
+       clone->bi_destructor = dm_bio_destructor;
        *clone->bi_io_vec = *bv;
 
        clone->bi_sector = sector;
index b12545f093f8aacd54e4aac476a0b504aaddda38..1e85d16491b02acb426d9f6a48f5439fc38c603c 100644 (file)
@@ -1,5 +1,5 @@
 config DVB_BT8XX
-       tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards"
+       tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && VIDEO_BT848
        select DVB_MT352
        select DVB_SP887X
@@ -8,8 +8,8 @@ config DVB_BT8XX
        select DVB_OR51211
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
-         the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
-         pcHDTV HD2000 cards.
+         the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
+         the pcHDTV HD2000 cards, and certain AVerMedia cards.
 
          Since these cards have no MPEG decoder onboard, they transmit
          only compressed MPEG data over the PCI bus, so you need
index 1f1cd7a8d500846c07e8fd4fa49c0d8335cd7443..7142b9c51dd2460e3b2c65ec91bddf08d877f8b0 100644 (file)
@@ -69,8 +69,8 @@ struct lgdt330x_state
 };
 
 static int i2c_write_demod_bytes (struct lgdt330x_state* state,
-                          u8 *buf, /* data bytes to send */
-                          int len  /* number of bytes to send */ )
+                                 u8 *buf, /* data bytes to send */
+                                 int len  /* number of bytes to send */ )
 {
        struct i2c_msg msg =
                { .addr = state->config->demod_address,
@@ -129,13 +129,13 @@ static int lgdt3302_SwReset(struct lgdt330x_state* state)
        };
 
        ret = i2c_write_demod_bytes(state,
-                            reset, sizeof(reset));
+                                   reset, sizeof(reset));
        if (ret == 0) {
 
                /* force reset high (inactive) and unmask interrupts */
                reset[1] = 0x7f;
                ret = i2c_write_demod_bytes(state,
-                                    reset, sizeof(reset));
+                                           reset, sizeof(reset));
        }
        return ret;
 }
@@ -149,13 +149,13 @@ static int lgdt3303_SwReset(struct lgdt330x_state* state)
        };
 
        ret = i2c_write_demod_bytes(state,
-                            reset, sizeof(reset));
+                                   reset, sizeof(reset));
        if (ret == 0) {
 
                /* force reset high (inactive) */
                reset[1] = 0x01;
                ret = i2c_write_demod_bytes(state,
-                                    reset, sizeof(reset));
+                                           reset, sizeof(reset));
        }
        return ret;
 }
@@ -172,7 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state)
        }
 }
 
-
 static int lgdt330x_init(struct dvb_frontend* fe)
 {
        /* Hardware reset is done using gpio[0] of cx23880x chip.
@@ -229,13 +228,13 @@ static int lgdt330x_init(struct dvb_frontend* fe)
        case LGDT3302:
                chip_name = "LGDT3302";
                err = i2c_write_demod_bytes(state, lgdt3302_init_data,
-                                                                       sizeof(lgdt3302_init_data));
-               break;
+                                           sizeof(lgdt3302_init_data));
+               break;
        case LGDT3303:
                chip_name = "LGDT3303";
                err = i2c_write_demod_bytes(state, lgdt3303_init_data,
-                                                                       sizeof(lgdt3303_init_data));
-               break;
+                                           sizeof(lgdt3303_init_data));
+               break;
        default:
                chip_name = "undefined";
                printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
@@ -262,15 +261,15 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        switch (state->config->demod_chip) {
        case LGDT3302:
                err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
-                                                                 buf, sizeof(buf));
-               break;
+                                          buf, sizeof(buf));
+               break;
        case LGDT3303:
                err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
-                                                                 buf, sizeof(buf));
-               break;
+                                          buf, sizeof(buf));
+               break;
        default:
                printk(KERN_WARNING
-                          "Only LGDT3302 and LGDT3303 are supported chips.\n");
+                      "Only LGDT3302 and LGDT3303 are supported chips.\n");
                err = -ENODEV;
        }
 
@@ -330,7 +329,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
 
                        if (state->config->demod_chip == LGDT3303) {
                                err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
-                                                                                       sizeof(lgdt3303_8vsb_44_data));
+                                                           sizeof(lgdt3303_8vsb_44_data));
                        }
                        break;
 
@@ -378,18 +377,19 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
 
                /* Select the requested mode */
                i2c_write_demod_bytes(state, top_ctrl_cfg,
-                                                         sizeof(top_ctrl_cfg));
-               state->config->set_ts_params(fe, 0);
+                                     sizeof(top_ctrl_cfg));
+               if (state->config->set_ts_params)
+                       state->config->set_ts_params(fe, 0);
                state->current_modulation = param->u.vsb.modulation;
        }
 
-       /* Change only if we are actually changing the channel */
-       if (state->current_frequency != param->frequency) {
-               /* Tune to the new frequency */
+       /* Tune to the specified frequency */
+       if (state->config->pll_set)
                state->config->pll_set(fe, param);
-               /* Keep track of the new frequency */
-               state->current_frequency = param->frequency;
-       }
+
+       /* Keep track of the new frequency */
+       state->current_frequency = param->frequency;
+
        lgdt330x_SwReset(state);
        return 0;
 }
index 810e7aac0a535edeed845e2c435d3d8f5cbb9d8f..3e6f5347da21ef90f97e99a0c651d28fc1edf070 100644 (file)
@@ -29,7 +29,7 @@ obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
 obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_PLANB) += planb.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o saa7191.o indycam.o
 obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
 obj-$(CONFIG_VIDEO_CPIA) += cpia.o
 obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
index 52e32f05d625b2fc9c0bcba9caa2aa60b9ac8878..1ca2b67aedfb653c66fc9b35467356d87604274f 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index b5ed9544bdea14702564a7037f96ed9bc388e3ca..173bca1e02950cdd29d340e56474f1da30389fbb 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index c6cfa7c48b04e5d5547437ab6703f61d25653dc2..3ee0afca76a7f1b206a39688648aacbd68e4ae5e 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index c13d2865886882b36c3a8ee91f4a39a11e8c0362..8eb871d0e85b61cdf1d139d73116bcbd32ff88f8 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
new file mode 100644 (file)
index 0000000..b2b0384
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ *  indycam.c - Silicon Graphics IndyCam digital camera driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+/* IndyCam decodes stream of photons into digital image representation ;-) */
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "indycam.h"
+
+//#define INDYCAM_DEBUG
+
+#define INDYCAM_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("SGI IndyCam driver");
+MODULE_VERSION(INDYCAM_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#ifdef INDYCAM_DEBUG
+#define dprintk(x...) printk("IndyCam: " x);
+#define indycam_regdump(client) indycam_regdump_debug(client)
+#else
+#define dprintk(x...)
+#define indycam_regdump(client)
+#endif
+
+#define VINO_ADAPTER   (I2C_ALGO_SGI | I2C_HW_SGI_VINO)
+
+struct indycam {
+       struct i2c_client *client;
+       int version;
+};
+
+static struct i2c_driver i2c_driver_indycam;
+
+static const unsigned char initseq[] = {
+       INDYCAM_CONTROL_AGCENA,         /* INDYCAM_CONTROL */
+       INDYCAM_SHUTTER_DEFAULT,        /* INDYCAM_SHUTTER */
+       INDYCAM_GAIN_DEFAULT,           /* INDYCAM_GAIN */
+       0x00,                           /* INDYCAM_BRIGHTNESS (read-only) */
+       INDYCAM_RED_BALANCE_DEFAULT,    /* INDYCAM_RED_BALANCE */
+       INDYCAM_BLUE_BALANCE_DEFAULT,   /* INDYCAM_BLUE_BALANCE */
+       INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */
+       INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
+};
+
+/* IndyCam register handling */
+
+static int indycam_read_reg(struct i2c_client *client, unsigned char reg,
+                            unsigned char *value)
+{
+       int ret;
+
+       if (reg == INDYCAM_RESET) {
+               dprintk("indycam_read_reg(): "
+                       "skipping write-only register %d\n", reg);
+               *value = 0;
+               return 0;
+       }
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       if (ret < 0) {
+               printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
+                      "register = 0x%02x\n", reg);
+               return ret;
+       }
+
+       *value = (unsigned char)ret;
+
+       return 0;
+}
+
+static int indycam_write_reg(struct i2c_client *client, unsigned char reg,
+                            unsigned char value)
+{
+       int err;
+
+       if ((reg == INDYCAM_BRIGHTNESS)
+           || (reg == INDYCAM_VERSION)) {
+               dprintk("indycam_write_reg(): "
+                       "skipping read-only register %d\n", reg);
+               return 0;
+       }
+
+       dprintk("Writing Reg %d = 0x%02x\n", reg, value);
+       err = i2c_smbus_write_byte_data(client, reg, value);
+       if (err) {
+               printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
+                      "register = 0x%02x, value = 0x%02x\n", reg, value);
+       }
+       return err;
+}
+
+static int indycam_write_block(struct i2c_client *client, unsigned char reg,
+                               unsigned char length, unsigned char *data)
+{
+       unsigned char i;
+       int err;
+
+       for (i = reg; i < length; i++) {
+               err = indycam_write_reg(client, reg + i, data[i]);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+/* Helper functions */
+
+#ifdef INDYCAM_DEBUG
+static void indycam_regdump_debug(struct i2c_client *client)
+{
+       int i;
+       unsigned char val;
+
+       for (i = 0; i < 9; i++) {
+               indycam_read_reg(client, i, &val);
+               dprintk("Reg %d = 0x%02x\n", i, val);
+       }
+}
+#endif
+
+static int indycam_get_controls(struct i2c_client *client,
+                               struct indycam_control *ctrl)
+{
+       unsigned char ctrl_reg;
+
+       indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+       ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA)
+               ? INDYCAM_VALUE_ENABLED
+               : INDYCAM_VALUE_DISABLED;
+       ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL)
+               ? INDYCAM_VALUE_ENABLED
+               : INDYCAM_VALUE_DISABLED;
+       indycam_read_reg(client, INDYCAM_SHUTTER,
+                        (unsigned char *)&ctrl->shutter);
+       indycam_read_reg(client, INDYCAM_GAIN,
+                        (unsigned char *)&ctrl->gain);
+       indycam_read_reg(client, INDYCAM_RED_BALANCE,
+                        (unsigned char *)&ctrl->red_balance);
+       indycam_read_reg(client, INDYCAM_BLUE_BALANCE,
+                        (unsigned char *)&ctrl->blue_balance);
+       indycam_read_reg(client, INDYCAM_RED_SATURATION,
+                        (unsigned char *)&ctrl->red_saturation);
+       indycam_read_reg(client, INDYCAM_BLUE_SATURATION,
+                        (unsigned char *)&ctrl->blue_saturation);
+       indycam_read_reg(client, INDYCAM_GAMMA,
+                        (unsigned char *)&ctrl->gamma);
+
+       return 0;
+}
+
+static int indycam_set_controls(struct i2c_client *client,
+                               struct indycam_control *ctrl)
+{
+       unsigned char ctrl_reg;
+
+       indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+       if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) {
+               if (ctrl->agc)
+                       ctrl_reg |= INDYCAM_CONTROL_AGCENA;
+               else
+                       ctrl_reg &= ~INDYCAM_CONTROL_AGCENA;
+       }
+       if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) {
+               if (ctrl->awb)
+                       ctrl_reg |= INDYCAM_CONTROL_AWBCTL;
+               else
+                       ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL;
+       }
+       indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg);
+
+       if (ctrl->shutter >= 0)
+               indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter);
+       if (ctrl->gain >= 0)
+               indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain);
+       if (ctrl->red_balance >= 0)
+               indycam_write_reg(client, INDYCAM_RED_BALANCE,
+                                 ctrl->red_balance);
+       if (ctrl->blue_balance >= 0)
+               indycam_write_reg(client, INDYCAM_BLUE_BALANCE,
+                                 ctrl->blue_balance);
+       if (ctrl->red_saturation >= 0)
+               indycam_write_reg(client, INDYCAM_RED_SATURATION,
+                                 ctrl->red_saturation);
+       if (ctrl->blue_saturation >= 0)
+               indycam_write_reg(client, INDYCAM_BLUE_SATURATION,
+                                 ctrl->blue_saturation);
+       if (ctrl->gamma >= 0)
+               indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma);
+
+       return 0;
+}
+
+/* I2C-interface */
+
+static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       int err = 0;
+       struct indycam *camera;
+       struct i2c_client *client;
+
+       printk(KERN_INFO "SGI IndyCam driver version %s\n",
+              INDYCAM_MODULE_VERSION);
+
+       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (!client)
+               return -ENOMEM;
+       camera = kmalloc(sizeof(struct indycam), GFP_KERNEL);
+       if (!camera) {
+               err = -ENOMEM;
+               goto out_free_client;
+       }
+
+       memset(client, 0, sizeof(struct i2c_client));
+       memset(camera, 0, sizeof(struct indycam));
+
+       client->addr = addr;
+       client->adapter = adap;
+       client->driver = &i2c_driver_indycam;
+       client->flags = 0;
+       strcpy(client->name, "IndyCam client");
+       i2c_set_clientdata(client, camera);
+
+       camera->client = client;
+
+       err = i2c_attach_client(client);
+       if (err)
+               goto out_free_camera;
+
+       camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION);
+       if (camera->version != CAMERA_VERSION_INDY &&
+           camera->version != CAMERA_VERSION_MOOSE) {
+               err = -ENODEV;
+               goto out_detach_client;
+       }
+       printk(KERN_INFO "IndyCam v%d.%d detected\n",
+              INDYCAM_VERSION_MAJOR(camera->version),
+              INDYCAM_VERSION_MINOR(camera->version));
+
+       indycam_regdump(client);
+
+       // initialize
+       err = indycam_write_block(client, 0, sizeof(initseq),
+                                 (unsigned char *)&initseq);
+       if (err) {
+               printk(KERN_ERR "IndyCam initalization failed\n");
+               err = -EIO;
+               goto out_detach_client;
+       }
+
+       indycam_regdump(client);
+
+       // white balance
+       err = indycam_write_reg(client, INDYCAM_CONTROL,
+                         INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
+       if (err) {
+               printk(KERN_ERR "IndyCam white balance "
+                      "initialization failed\n");
+               err = -EIO;
+               goto out_detach_client;
+       }
+
+       indycam_regdump(client);
+
+       printk(KERN_INFO "IndyCam initialized\n");
+
+       return 0;
+
+out_detach_client:
+       i2c_detach_client(client);
+out_free_camera:
+       kfree(camera);
+out_free_client:
+       kfree(client);
+       return err;
+}
+
+static int indycam_probe(struct i2c_adapter *adap)
+{
+       /* Indy specific crap */
+       if (adap->id == VINO_ADAPTER)
+               return indycam_attach(adap, INDYCAM_ADDR, 0);
+       /* Feel free to add probe here :-) */
+       return -ENODEV;
+}
+
+static int indycam_detach(struct i2c_client *client)
+{
+       struct indycam *camera = i2c_get_clientdata(client);
+
+       i2c_detach_client(client);
+       kfree(camera);
+       kfree(client);
+       return 0;
+}
+
+static int indycam_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg)
+{
+       // struct indycam *camera = i2c_get_clientdata(client);
+
+       /* The old video_decoder interface just isn't enough,
+        * so we'll use some custom commands. */
+       switch (cmd) {
+       case DECODER_GET_CAPABILITIES: {
+               struct video_decoder_capability *cap = arg;
+
+               cap->flags  = VIDEO_DECODER_NTSC;
+               cap->inputs = 1;
+               cap->outputs = 1;
+               break;
+       }
+       case DECODER_GET_STATUS: {
+               int *iarg = arg;
+
+               *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
+                       DECODER_STATUS_COLOR;
+               break;
+       }
+       case DECODER_SET_NORM: {
+               int *iarg = arg;
+
+               switch (*iarg) {
+               case VIDEO_MODE_NTSC:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       }
+       case DECODER_SET_INPUT: {
+               int *iarg = arg;
+
+               if (*iarg != 0)
+                       return -EINVAL;
+               break;
+       }
+       case DECODER_SET_OUTPUT: {
+               int *iarg = arg;
+
+               if (*iarg != 0)
+                       return -EINVAL;
+               break;
+       }
+       case DECODER_ENABLE_OUTPUT: {
+               /* Always enabled */
+               break;
+       }
+       case DECODER_SET_PICTURE: {
+               // struct video_picture *pic = arg;
+               /* TODO: convert values for indycam_set_controls() */
+               break;
+       }
+       case DECODER_INDYCAM_GET_CONTROLS: {
+               struct indycam_control *ctrl = arg;
+               indycam_get_controls(client, ctrl);
+       }
+       case DECODER_INDYCAM_SET_CONTROLS: {
+               struct indycam_control *ctrl = arg;
+               indycam_set_controls(client, ctrl);
+       }
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct i2c_driver i2c_driver_indycam = {
+       .owner          = THIS_MODULE,
+       .name           = "indycam",
+       .id             = I2C_DRIVERID_INDYCAM,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = indycam_probe,
+       .detach_client  = indycam_detach,
+       .command        = indycam_command,
+};
+
+static int __init indycam_init(void)
+{
+       return i2c_add_driver(&i2c_driver_indycam);
+}
+
+static void __exit indycam_exit(void)
+{
+       i2c_del_driver(&i2c_driver_indycam);
+}
+
+module_init(indycam_init);
+module_exit(indycam_exit);
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h
new file mode 100644 (file)
index 0000000..d9ddb6b
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  indycam.h - Silicon Graphics IndyCam digital camera driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _INDYCAM_H_
+#define _INDYCAM_H_
+
+/* I2C address for the Guinness Camera */
+#define INDYCAM_ADDR                   0x56
+
+/* Camera version */
+#define CAMERA_VERSION_INDY            0x10    /* v1.0 */
+#define CAMERA_VERSION_MOOSE           0x12    /* v1.2 */
+#define INDYCAM_VERSION_MAJOR(x)       (((x) & 0xf0) >> 4)
+#define INDYCAM_VERSION_MINOR(x)       ((x) & 0x0f)
+
+/* Register bus addresses */
+#define INDYCAM_CONTROL                        0x00
+#define INDYCAM_SHUTTER                        0x01
+#define INDYCAM_GAIN                   0x02
+#define INDYCAM_BRIGHTNESS             0x03 /* read-only */
+#define INDYCAM_RED_BALANCE            0x04
+#define INDYCAM_BLUE_BALANCE           0x05
+#define INDYCAM_RED_SATURATION         0x06
+#define INDYCAM_BLUE_SATURATION                0x07
+#define INDYCAM_GAMMA                  0x08
+#define INDYCAM_VERSION                        0x0e /* read-only */
+#define INDYCAM_RESET                  0x0f /* write-only */
+
+#define INDYCAM_LED                    0x46
+#define INDYCAM_ORIENTATION            0x47
+#define INDYCAM_BUTTON                 0x48
+
+/* Field definitions of registers */
+#define INDYCAM_CONTROL_AGCENA         (1<<0) /* automatic gain control */
+#define INDYCAM_CONTROL_AWBCTL         (1<<1) /* automatic white balance */
+                                               /* 2-3 are reserved */
+#define INDYCAM_CONTROL_EVNFLD         (1<<4)  /* read-only */
+
+#define INDYCAM_SHUTTER_10000          0x02    /* 1/10000 second */
+#define INDYCAM_SHUTTER_4000           0x04    /* 1/4000 second */
+#define INDYCAM_SHUTTER_2000           0x08    /* 1/2000 second */
+#define INDYCAM_SHUTTER_1000           0x10    /* 1/1000 second */
+#define INDYCAM_SHUTTER_500            0x20    /* 1/500 second */
+#define INDYCAM_SHUTTER_250            0x3f    /* 1/250 second */
+#define INDYCAM_SHUTTER_125            0x7e    /* 1/125 second */
+#define INDYCAM_SHUTTER_100            0x9e    /* 1/100 second */
+#define INDYCAM_SHUTTER_60             0x00    /* 1/60 second */
+
+#define INDYCAM_LED_ACTIVE                     0x10
+#define INDYCAM_LED_INACTIVE                   0x30
+#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP      0x40
+#define INDYCAM_BUTTON_RELEASED                        0x10
+
+#define INDYCAM_SHUTTER_MIN            0x00
+#define INDYCAM_SHUTTER_MAX            0xff
+#define INDYCAM_GAIN_MIN                0x00
+#define INDYCAM_GAIN_MAX                0xff
+#define INDYCAM_RED_BALANCE_MIN        0x00 /* the effect is the opposite? */
+#define INDYCAM_RED_BALANCE_MAX        0xff
+#define INDYCAM_BLUE_BALANCE_MIN        0x00 /* the effect is the opposite? */
+#define INDYCAM_BLUE_BALANCE_MAX        0xff
+#define INDYCAM_RED_SATURATION_MIN      0x00
+#define INDYCAM_RED_SATURATION_MAX      0xff
+#define INDYCAM_BLUE_SATURATION_MIN    0x00
+#define INDYCAM_BLUE_SATURATION_MAX    0xff
+#define INDYCAM_GAMMA_MIN              0x00
+#define INDYCAM_GAMMA_MAX              0xff
+
+/* Driver interface definitions */
+
+#define INDYCAM_VALUE_ENABLED          1
+#define INDYCAM_VALUE_DISABLED         0
+#define INDYCAM_VALUE_UNCHANGED                -1
+
+/* When setting controls, a value of -1 leaves the control unchanged. */
+struct indycam_control {
+       int agc;        /* boolean */
+       int awb;        /* boolean */
+       int shutter;
+       int gain;
+       int red_balance;
+       int blue_balance;
+       int red_saturation;
+       int blue_saturation;
+       int gamma;
+};
+
+#define        DECODER_INDYCAM_GET_CONTROLS    _IOR('d', 193, struct indycam_control)
+#define        DECODER_INDYCAM_SET_CONTROLS    _IOW('d', 194, struct indycam_control)
+
+/* Default values for controls */
+
+#define INDYCAM_AGC_DEFAULT            INDYCAM_VALUE_ENABLED
+#define INDYCAM_AWB_DEFAULT            INDYCAM_VALUE_ENABLED
+
+#define INDYCAM_SHUTTER_DEFAULT                INDYCAM_SHUTTER_60
+#define INDYCAM_GAIN_DEFAULT           0x80
+#define INDYCAM_RED_BALANCE_DEFAULT    0x18
+#define INDYCAM_BLUE_BALANCE_DEFAULT   0xa4
+#define INDYCAM_RED_SATURATION_DEFAULT 0x80
+#define INDYCAM_BLUE_SATURATION_DEFAULT        0xc0
+#define INDYCAM_GAMMA_DEFAULT          0x80
+
+#endif
index fe194012bccf65aac168a7bfc61b48fa621767c8..3f2a882bc20a6a6b31b00af7bef5278596f253db 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
 
 #include "meye.h"
 #include <linux/meye.h>
@@ -121,7 +122,7 @@ static int ptable_alloc(void)
        memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
 
        /* give only 32 bit DMA addresses */
-       if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff))
+       if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK))
                return -1;
 
        meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
index f18df53d98ff16c7b7b1027b5d0e5057ae7510c3..fe8a5e45396982ca0a1a62ee2ab6571ca4d7ba23 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index e0c70f54f0737f93cc8aa519fb588b93c0794eed..d9f50e2f7b92f1c14997945c465ffdc13fad668c 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index e93412f4407cb9d7fa1008d4c21a9e018555d534..132aa7943c1625a7385a15a9d69bbd37b3864a3e 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
new file mode 100644 (file)
index 0000000..454f5c1
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *  saa7191.c - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#define VINO_ADAPTER   (I2C_ALGO_SGI | I2C_HW_SGI_VINO)
+
+struct saa7191 {
+       struct i2c_client *client;
+
+       /* the register values are stored here as the actual
+        * I2C-registers are write-only */
+       unsigned char reg[25];
+
+       unsigned char norm;
+       unsigned char input;
+};
+
+static struct i2c_driver i2c_driver_saa7191;
+
+static const unsigned char initseq[] = {
+       0,      /* Subaddress */
+       0x50,   /* SAA7191_REG_IDEL */
+       0x30,   /* SAA7191_REG_HSYB */
+       0x00,   /* SAA7191_REG_HSYS */
+       0xe8,   /* SAA7191_REG_HCLB */
+       0xb6,   /* SAA7191_REG_HCLS */
+       0xf4,   /* SAA7191_REG_HPHI */
+       0x01,   /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */
+       0x00,   /* SAA7191_REG_HUEC */
+       0xf8,   /* SAA7191_REG_CKTQ */
+       0xf8,   /* SAA7191_REG_CKTS */
+       0x90,   /* SAA7191_REG_PLSE */
+       0x90,   /* SAA7191_REG_SESE */
+       0x00,   /* SAA7191_REG_GAIN */
+       0x0c,   /* SAA7191_REG_STDC - not SECAM, slow time constant */
+       0x78,   /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */
+       0x99,   /* SAA7191_REG_CTL3 - automatic field detection */
+       0x00,   /* SAA7191_REG_CTL4 */
+       0x2c,   /* SAA7191_REG_CHCV */
+       0x00,   /* unused */
+       0x00,   /* unused */
+       0x34,   /* SAA7191_REG_HS6B */
+       0x0a,   /* SAA7191_REG_HS6S */
+       0xf4,   /* SAA7191_REG_HC6B */
+       0xce,   /* SAA7191_REG_HC6S */
+       0xf4,   /* SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static unsigned char saa7191_read_reg(struct i2c_client *client,
+                                     unsigned char reg)
+{
+       return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
+}
+
+static int saa7191_read_status(struct i2c_client *client,
+                              unsigned char *value)
+{
+       int ret;
+
+       ret = i2c_master_recv(client, value, 1);
+       if (ret < 0) {
+               printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed");
+               return ret;
+       }
+
+       return 0;
+}
+
+
+static int saa7191_write_reg(struct i2c_client *client, unsigned char reg,
+                            unsigned char value)
+{
+
+       ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* the first byte of data must be the first subaddress number (register) */
+static int saa7191_write_block(struct i2c_client *client,
+                              unsigned char length, unsigned char *data)
+{
+       int i;
+       int ret;
+
+       struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
+       for (i = 0; i < (length - 1); i++) {
+               decoder->reg[data[0] + i] = data[i + 1];
+       }
+
+       ret = i2c_master_send(client, data, length);
+       if (ret < 0) {
+               printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+                      "write failed");
+               return ret;
+       }
+
+       return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_set_input(struct i2c_client *client, int input)
+{
+       unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
+       unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
+       int err;
+
+       switch (input) {
+       case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+               iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+                         | SAA7191_IOCK_GPSW2);
+               /* Chrominance trap active */
+               luma &= ~SAA7191_LUMA_BYPS;
+               break;
+       case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+               iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+               /* Chrominance trap bypassed */
+               luma |= SAA7191_LUMA_BYPS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
+       if (err)
+               return -EIO;
+       err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
+       if (err)
+               return -EIO;
+
+       return 0;
+}
+
+static int saa7191_set_norm(struct i2c_client *client, int norm)
+{
+       struct saa7191 *decoder = i2c_get_clientdata(client);
+       unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+       unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
+       unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
+       int err;
+
+       switch(norm) {
+       case SAA7191_NORM_AUTO: {
+               unsigned char status;
+
+               // does status depend on current norm ?
+               if (saa7191_read_status(client, &status))
+                       return -EIO;
+
+               stdc &= ~SAA7191_STDC_SECS;
+               ctl3 &= ~SAA7191_CTL3_FSEL;
+               ctl3 |= SAA7191_CTL3_AUFD;
+               chcv = (status & SAA7191_STATUS_FIDT)
+                              ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL;
+               break;
+       }
+       case SAA7191_NORM_PAL:
+               stdc &= ~SAA7191_STDC_SECS;
+               ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+               chcv = SAA7191_CHCV_PAL;
+               break;
+       case SAA7191_NORM_NTSC:
+               stdc &= ~SAA7191_STDC_SECS;
+               ctl3 &= ~SAA7191_CTL3_AUFD;
+               ctl3 |= SAA7191_CTL3_FSEL;
+               chcv = SAA7191_CHCV_NTSC;
+               break;
+       case SAA7191_NORM_SECAM:
+               stdc |= SAA7191_STDC_SECS;
+               ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+               chcv = SAA7191_CHCV_PAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+       if (err)
+               return -EIO;
+       err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+       if (err)
+               return -EIO;
+       err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
+       if (err)
+               return -EIO;
+
+       decoder->norm = norm;
+
+       return 0;
+}
+
+static int saa7191_get_controls(struct i2c_client *client,
+                               struct saa7191_control *ctrl)
+{
+       unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC);
+       unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+
+       if (hue < 0x80) {
+               hue += 0x80;
+       } else {
+               hue -= 0x80;
+       }
+       ctrl->hue = hue;
+
+       ctrl->vtrc = (stdc & SAA7191_STDC_VTRC)
+               ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+       return 0;
+}
+
+static int saa7191_set_controls(struct i2c_client *client,
+                               struct saa7191_control *ctrl)
+{
+       int err;
+
+       if (ctrl->hue >= 0) {
+               unsigned char hue = ctrl->hue & 0xff;
+               if (hue < 0x80) {
+                       hue += 0x80;
+               } else {
+                       hue -= 0x80;
+               }
+               err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue);
+               if (err)
+                       return -EIO;
+       }
+       if (ctrl->vtrc >= 0) {
+               unsigned char stdc =
+                       saa7191_read_reg(client, SAA7191_REG_STDC);
+
+               if (ctrl->vtrc) {
+                       stdc |= SAA7191_STDC_VTRC;
+               } else {
+                       stdc &= ~SAA7191_STDC_VTRC;
+               }
+
+               err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+               if (err)
+                       return -EIO;
+       }
+
+       return 0;
+}
+
+/* I2C-interface */
+
+static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       int err = 0;
+       struct saa7191 *decoder;
+       struct i2c_client *client;
+
+       printk(KERN_INFO "Philips SAA7191 driver version %s\n",
+              SAA7191_MODULE_VERSION);
+
+       client = kmalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return -ENOMEM;
+       decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+       if (!decoder) {
+               err = -ENOMEM;
+               goto out_free_client;
+       }
+
+       memset(client, 0, sizeof(struct i2c_client));
+       memset(decoder, 0, sizeof(struct saa7191));
+
+       client->addr = addr;
+       client->adapter = adap;
+       client->driver = &i2c_driver_saa7191;
+       client->flags = 0;
+       strcpy(client->name, "saa7191 client");
+       i2c_set_clientdata(client, decoder);
+
+       decoder->client = client;
+
+       err = i2c_attach_client(client);
+       if (err)
+               goto out_free_decoder;
+
+       decoder->input = SAA7191_INPUT_COMPOSITE;
+       decoder->norm = SAA7191_NORM_AUTO;
+
+       err = saa7191_write_block(client, sizeof(initseq),
+                                 (unsigned char *)initseq);
+       if (err) {
+               printk(KERN_ERR "SAA7191 initialization failed\n");
+               goto out_detach_client;
+       }
+
+       printk(KERN_INFO "SAA7191 initialized\n");
+
+       return 0;
+
+out_detach_client:
+       i2c_detach_client(client);
+out_free_decoder:
+       kfree(decoder);
+out_free_client:
+       kfree(client);
+       return err;
+}
+
+static int saa7191_probe(struct i2c_adapter *adap)
+{
+       /* Always connected to VINO */
+       if (adap->id == VINO_ADAPTER)
+               return saa7191_attach(adap, SAA7191_ADDR, 0);
+       /* Feel free to add probe here :-) */
+       return -ENODEV;
+}
+
+static int saa7191_detach(struct i2c_client *client)
+{
+       struct saa7191 *decoder = i2c_get_clientdata(client);
+
+       i2c_detach_client(client);
+       kfree(decoder);
+       kfree(client);
+       return 0;
+}
+
+static int saa7191_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg)
+{
+       struct saa7191 *decoder = i2c_get_clientdata(client);
+
+       switch (cmd) {
+       case DECODER_GET_CAPABILITIES: {
+               struct video_decoder_capability *cap = arg;
+
+               cap->flags  = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
+                             VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
+               cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1;
+               cap->outputs = 1;
+               break;
+       }
+       case DECODER_GET_STATUS: {
+               int *iarg = arg;
+               unsigned char status;
+               int res = 0;
+
+               if (saa7191_read_status(client, &status)) {
+                       return -EIO;
+               }
+               if ((status & SAA7191_STATUS_HLCK) == 0)
+                       res |= DECODER_STATUS_GOOD;
+               if (status & SAA7191_STATUS_CODE)
+                       res |= DECODER_STATUS_COLOR;
+               switch (decoder->norm) {
+               case SAA7191_NORM_NTSC:
+                       res |= DECODER_STATUS_NTSC;
+                       break;
+               case SAA7191_NORM_PAL:
+                       res |= DECODER_STATUS_PAL;
+                       break;
+               case SAA7191_NORM_SECAM:
+                       res |= DECODER_STATUS_SECAM;
+                       break;
+               case SAA7191_NORM_AUTO:
+               default:
+                       if (status & SAA7191_STATUS_FIDT)
+                               res |= DECODER_STATUS_NTSC;
+                       else
+                               res |= DECODER_STATUS_PAL;
+                       break;
+               }
+               *iarg = res;
+               break;
+       }
+       case DECODER_SET_NORM: {
+               int *iarg = arg;
+
+               switch (*iarg) {
+               case VIDEO_MODE_AUTO:
+                       return saa7191_set_norm(client, SAA7191_NORM_AUTO);
+               case VIDEO_MODE_PAL:
+                       return saa7191_set_norm(client, SAA7191_NORM_PAL);
+               case VIDEO_MODE_NTSC:
+                       return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+               case VIDEO_MODE_SECAM:
+                       return saa7191_set_norm(client, SAA7191_NORM_SECAM);
+               default:
+                       return -EINVAL;
+               }
+               break;
+       }
+       case DECODER_SET_INPUT: {
+               int *iarg = arg;
+
+               switch (client->adapter->id) {
+               case VINO_ADAPTER:
+                       return saa7191_set_input(client, *iarg);
+               default:
+                       if (*iarg != 0)
+                               return -EINVAL;
+               }
+               break;
+       }
+       case DECODER_SET_OUTPUT: {
+               int *iarg = arg;
+
+               /* not much choice of outputs */
+               if (*iarg != 0)
+                       return -EINVAL;
+               break;
+       }
+       case DECODER_ENABLE_OUTPUT: {
+               /* Always enabled */
+               break;
+       }
+       case DECODER_SET_PICTURE: {
+               struct video_picture *pic = arg;
+               unsigned val;
+               int err;
+
+               val = (pic->hue >> 8) - 0x80;
+               err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
+               if (err)
+                       return -EIO;
+               break;
+       }
+       case DECODER_SAA7191_GET_STATUS: {
+               struct saa7191_status *status = arg;
+               unsigned char status_reg;
+
+               if (saa7191_read_status(client, &status_reg))
+                       return -EIO;
+               status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
+                       ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+               status->ntsc = (status_reg & SAA7191_STATUS_FIDT)
+                       ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+               status->color = (status_reg & SAA7191_STATUS_CODE)
+                       ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+               status->input = decoder->input;
+               status->norm = decoder->norm;
+       }
+       case DECODER_SAA7191_SET_NORM: {
+               int *norm = arg;
+               return saa7191_set_norm(client, *norm);
+       }
+       case DECODER_SAA7191_GET_CONTROLS: {
+               struct saa7191_control *ctrl = arg;
+               return saa7191_get_controls(client, ctrl);
+       }
+       case DECODER_SAA7191_SET_CONTROLS: {
+               struct saa7191_control *ctrl = arg;
+               return saa7191_set_controls(client, ctrl);
+       }
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct i2c_driver i2c_driver_saa7191 = {
+       .owner          = THIS_MODULE,
+       .name           = "saa7191",
+       .id             = I2C_DRIVERID_SAA7191,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = saa7191_probe,
+       .detach_client  = saa7191_detach,
+       .command        = saa7191_command
+};
+
+static int saa7191_init(void)
+{
+       return i2c_add_driver(&i2c_driver_saa7191);
+}
+
+static void saa7191_exit(void)
+{
+       i2c_del_driver(&i2c_driver_saa7191);
+}
+
+module_init(saa7191_init);
+module_exit(saa7191_exit);
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h
new file mode 100644 (file)
index 0000000..2720450
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  saa7191.h - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR           0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL       0x00
+#define SAA7191_REG_HSYB       0x01
+#define SAA7191_REG_HSYS       0x02
+#define SAA7191_REG_HCLB       0x03
+#define SAA7191_REG_HCLS       0x04
+#define SAA7191_REG_HPHI       0x05
+#define SAA7191_REG_LUMA       0x06
+#define SAA7191_REG_HUEC       0x07
+#define SAA7191_REG_CKTQ       0x08
+#define SAA7191_REG_CKTS       0x09
+#define SAA7191_REG_PLSE       0x0a
+#define SAA7191_REG_SESE       0x0b
+#define SAA7191_REG_GAIN       0x0c
+#define SAA7191_REG_STDC       0x0d
+#define SAA7191_REG_IOCK       0x0e
+#define SAA7191_REG_CTL3       0x0f
+#define SAA7191_REG_CTL4       0x10
+#define SAA7191_REG_CHCV       0x11
+#define SAA7191_REG_HS6B       0x14
+#define SAA7191_REG_HS6S       0x15
+#define SAA7191_REG_HC6B       0x16
+#define SAA7191_REG_HC6S       0x17
+#define SAA7191_REG_HP6I       0x18
+#define SAA7191_REG_STATUS     0xff    /* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE    0x01    /* color detected flag */
+#define SAA7191_STATUS_FIDT    0x20    /* format type NTSC/PAL */
+#define SAA7191_STATUS_HLCK    0x40    /* PLL unlocked/locked */
+#define SAA7191_STATUS_STTC    0x80    /* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+#define SAA7191_LUMA_BYPS      0x80
+
+/* Chroma Gain Control Settings Register definitions */
+/* 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO      0x80
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC      0x80
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS      0x01
+/* the bit fields above must be or'd with this value */
+#define SAA7191_STDC_VALUE     0x0c
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL      0x80
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS      0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2     0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1     0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD      0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL      0x40
+/* the bit fields above must be or'd with this value */
+#define SAA7191_CTL3_VALUE     0x19
+
+/* Chrominance Gain Control Register definitions
+ * (nominal value for UV CCIR level) */
+#define SAA7191_CHCV_NTSC      0x2c
+#define SAA7191_CHCV_PAL       0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE        0
+#define SAA7191_INPUT_SVIDEO   1
+
+#define SAA7191_NORM_AUTO      0
+#define SAA7191_NORM_PAL       1
+#define SAA7191_NORM_NTSC      2
+#define SAA7191_NORM_SECAM     3
+
+#define SAA7191_VALUE_ENABLED          1
+#define SAA7191_VALUE_DISABLED         0
+#define SAA7191_VALUE_UNCHANGED                -1
+
+struct saa7191_status {
+       /* 0=no signal, 1=signal active*/
+       int signal;
+       /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+       int ntsc;
+       /* 0=no color detected, 1=color detected */
+       int color;
+
+       /* current SAA7191_INPUT_ */
+       int input;
+       /* current SAA7191_NORM_ */
+       int norm;
+};
+
+#define SAA7191_HUE_MIN                0x00
+#define SAA7191_HUE_MAX                0xff
+#define SAA7191_HUE_DEFAULT    0x80
+
+#define SAA7191_VTRC_MIN       0x00
+#define SAA7191_VTRC_MAX       0x01
+#define SAA7191_VTRC_DEFAULT   0x00
+
+struct saa7191_control {
+       int hue;
+       int vtrc;
+};
+
+#define        DECODER_SAA7191_GET_STATUS      _IOR('d', 195, struct saa7191_status)
+#define        DECODER_SAA7191_SET_NORM        _IOW('d', 196, int)
+#define        DECODER_SAA7191_GET_CONTROLS    _IOR('d', 197, struct saa7191_control)
+#define        DECODER_SAA7191_SET_CONTROLS    _IOW('d', 198, struct saa7191_control)
+
+#endif
index 76e8681d65c662f863636fb67deaf35f7158391b..d8a0f763ca101314d18f1c501631dca62d125f62 100644 (file)
 /*
- * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys.
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License version 2 as published by the Free Software Foundation.
  *
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * Based on the previous version of the driver for 2.4 kernels by:
  * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
  */
 
-#include <linux/module.h>
+/*
+ * TODO:
+ * - remove "hacks" from memory allocation code and implement nopage()
+ * - check decimation, calculating and reporting image size when
+ *   using decimation
+ * - check vino_acquire_input(), vino_set_input() and channel
+ *   ownership handling
+ * - report VINO error-interrupts via ioctls ?
+ * - implement picture controls (all implemented?)
+ * - use macros for boolean values (?)
+ * - implement user mode buffers and overlay (?)
+ */
+
 #include <linux/init.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/wrapper.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/time.h>
+#include <linux/moduleparam.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
 #include <linux/i2c.h>
 #include <linux/i2c-algo-sgi.h>
 
-#include <asm/addrspace.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/pgtable.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+
 #include <asm/paccess.h>
 #include <asm/io.h>
 #include <asm/sgi/ip22.h>
-#include <asm/sgi/hpc3.h>
 #include <asm/sgi/mc.h>
 
 #include "vino.h"
+#include "saa7191.h"
+#include "indycam.h"
 
-/* debugging? */
-#if 1
-#define DEBUG(x...)     printk(x);
+/* Uncomment the following line to get lots and lots of (mostly useless)
+ * debug info.
+ * Note that the debug output also slows down the driver significantly */
+// #define VINO_DEBUG
+
+#define VINO_MODULE_VERSION "0.0.3"
+#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3)
+
+MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
+MODULE_VERSION(VINO_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags))
+#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags))
+
+#ifdef VINO_DEBUG
+#define dprintk(x...) printk("VINO: " x);
 #else
-#define DEBUG(x...)
+#define dprintk(x...)
 #endif
 
+#define VINO_NO_CHANNEL                        0
+#define VINO_CHANNEL_A                 1
+#define VINO_CHANNEL_B                 2
+
+#define VINO_PAL_WIDTH                 768
+#define VINO_PAL_HEIGHT                        576
+#define VINO_NTSC_WIDTH                        640
+#define VINO_NTSC_HEIGHT               480
+
+#define VINO_MIN_WIDTH                 32
+#define VINO_MIN_HEIGHT                        32
+
+#define VINO_CLIPPING_START_ODD_D1     1
+#define VINO_CLIPPING_START_ODD_PAL    1
+#define VINO_CLIPPING_START_ODD_NTSC   1
+
+#define VINO_CLIPPING_START_EVEN_D1    2
+#define VINO_CLIPPING_START_EVEN_PAL   2
+#define VINO_CLIPPING_START_EVEN_NTSC  2
+
+#define VINO_INPUT_CHANNEL_COUNT       3
+
+#define VINO_INPUT_NONE                        -1
+#define VINO_INPUT_COMPOSITE           0
+#define VINO_INPUT_SVIDEO              1
+#define VINO_INPUT_D1                  2
+
+#define VINO_PAGE_RATIO                        (PAGE_SIZE / VINO_PAGE_SIZE)
+
+#define VINO_FIFO_THRESHOLD_DEFAULT    512
+
+/*#define VINO_FRAMEBUFFER_SIZE                (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \
+  + 2 * PAGE_SIZE)*/
+#define VINO_FRAMEBUFFER_SIZE          ((VINO_PAL_WIDTH \
+                                         * VINO_PAL_HEIGHT * 4 \
+                                         + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
+
+#define VINO_FRAMEBUFFER_MAX_COUNT     8
+
+#define VINO_FRAMEBUFFER_UNUSED                0
+#define VINO_FRAMEBUFFER_IN_USE                1
+#define VINO_FRAMEBUFFER_READY         2
+
+#define VINO_QUEUE_ERROR               -1
+#define VINO_QUEUE_MAGIC               0x20050125
+
+#define VINO_MEMORY_NONE               0
+#define VINO_MEMORY_MMAP               1
+#define VINO_MEMORY_USERPTR            2
+
+#define VINO_DUMMY_DESC_COUNT          4
+#define VINO_DESC_FETCH_DELAY          5       /* microseconds */
+
+/* the number is the index for vino_data_formats */
+#define VINO_DATA_FMT_NONE             -1
+#define VINO_DATA_FMT_GREY             0
+#define VINO_DATA_FMT_RGB332           1
+#define VINO_DATA_FMT_RGB32            2
+#define VINO_DATA_FMT_YUV              3
+//#define VINO_DATA_FMT_RGB24          4
+
+#define VINO_DATA_FMT_COUNT            4
+
+#define VINO_DATA_NORM_NONE            -1
+#define VINO_DATA_NORM_NTSC            0
+#define VINO_DATA_NORM_PAL             1
+#define VINO_DATA_NORM_SECAM           2
+#define VINO_DATA_NORM_D1              3
+/* The following is a special entry that can be used to
+ * autodetect the norm. */
+#define VINO_DATA_NORM_AUTO            0xff
+
+#define VINO_DATA_NORM_COUNT           4
+
+/* Internal data structure definitions */
+
+struct vino_input {
+       char *name;
+       v4l2_std_id std;
+};
+
+struct vino_clipping {
+       unsigned int left, right, top, bottom;
+};
+
+struct vino_data_format {
+       /* the description */
+       char *description;
+       /* bytes per pixel */
+       unsigned int bpp;
+       /* V4L2 fourcc code */
+       __u32 pixelformat;
+       /* V4L2 colorspace (duh!) */
+       enum v4l2_colorspace colorspace;
+};
+
+struct vino_data_norm {
+       char *description;
+       unsigned int width, height;
+       struct vino_clipping odd;
+       struct vino_clipping even;
+
+       v4l2_std_id std;
+       unsigned int fps_min, fps_max;
+       __u32 framelines;
+};
+
+struct vino_descriptor_table {
+       /* the number of PAGE_SIZE sized pages in the buffer */
+       unsigned int page_count;
+       /* virtual (kmalloc'd) pointers to the actual data
+        * (in PAGE_SIZE chunks, used with mmap streaming) */
+       unsigned long *virtual;
+
+       /* cpu address for the VINO descriptor table
+        * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+       unsigned long *dma_cpu;
+       /* dma address for the VINO descriptor table
+        * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+       dma_addr_t dma;
+};
+
+struct vino_framebuffer {
+       /* identifier nubmer */
+       unsigned int id;
+       /* the length of the whole buffer */
+       unsigned int size;
+       /* the length of actual data in buffer */
+       unsigned int data_size;
+       /* the data format */
+       unsigned int data_format;
+       /* the state of buffer data */
+       unsigned int state;
+       /* is the buffer mapped in user space? */
+       unsigned int map_count;
+       /* memory offset for mmap() */
+       unsigned int offset;
+       /* frame counter */
+       unsigned int frame_counter;
+       /* timestamp (written when image capture finishes) */
+       struct timeval timestamp;
+
+       struct vino_descriptor_table desc_table;
+
+       spinlock_t state_lock;
+};
+
+struct vino_framebuffer_fifo {
+       unsigned int length;
+
+       unsigned int used;
+       unsigned int head;
+       unsigned int tail;
+
+       unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT];
+};
+
+struct vino_framebuffer_queue {
+       unsigned int magic;
+
+       /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
+       unsigned int type;
+       unsigned int length;
+
+       /* data field of in and out contain index numbers for buffer */
+       struct vino_framebuffer_fifo in;
+       struct vino_framebuffer_fifo out;
+
+       struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT];
 
-/* VINO ASIC registers */
-struct sgi_vino *vino;
+       spinlock_t queue_lock;
+       struct semaphore queue_sem;
+       wait_queue_head_t frame_wait_queue;
+};
+
+struct vino_channel_settings {
+       unsigned int channel;
+
+       int input;
+       unsigned int data_format;
+       unsigned int data_norm;
+       struct vino_clipping clipping;
+       unsigned int decimation;
+       unsigned int line_size;
+       unsigned int alpha;
+       unsigned int fps;
+       unsigned int framert_reg;
+
+       unsigned int fifo_threshold;
+
+       struct vino_framebuffer_queue fb_queue;
+
+       /* number of the current field */
+       unsigned int field;
+
+       /* read in progress */
+       int reading;
+       /* streaming is active */
+       int streaming;
+       /* the driver is currently processing the queue */
+       int capturing;
+
+       struct semaphore sem;
+       spinlock_t capture_lock;
 
-static const char *vinostr = "VINO IndyCam/TV";
-static int threshold_a = 512;
-static int threshold_b = 512;
+       unsigned int users;
 
-struct vino_device {
-       struct video_device vdev;
-#define VINO_CHAN_A            1
-#define VINO_CHAN_B            2
-       int chan;
+       /* V4L support */
+       struct video_device *v4l_device;
 };
 
 struct vino_client {
+       /* the channel which owns this client:
+        * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+       unsigned int owner;
        struct i2c_client *driver;
-       int owner;
 };
 
-struct vino_video {
-       struct vino_device chA;
-       struct vino_device chB;
+struct vino_settings {
+       struct vino_channel_settings a;
+       struct vino_channel_settings b;
 
        struct vino_client decoder;
        struct vino_client camera;
 
-       struct semaphore input_lock;
+       /* a lock for vino register access */
+       spinlock_t vino_lock;
+       /* a lock for channel input changes */
+       spinlock_t input_lock;
 
-       /* Loaded into VINO descriptors to clear End Of Descriptors table
-        * interupt condition */
        unsigned long dummy_page;
-       unsigned int dummy_buf[4] __attribute__((aligned(8)));
+       struct vino_descriptor_table dummy_desc_table;
+};
+
+/* Module parameters */
+
+/*
+ * Using vino_pixel_conversion the ARGB32-format pixels supplied
+ * by the VINO chip can be converted to more common formats
+ * like RGBA32 (or probably RGB24 in the future). This way we
+ * can give out data that can be specified correctly with
+ * the V4L2-definitions.
+ *
+ * The pixel format is specified as RGBA32 when no conversion
+ * is used.
+ *
+ * Note that this only affects the 32-bit bit depth.
+ *
+ * Use non-zero value to enable conversion.
+ */
+static int vino_pixel_conversion = 0;
+module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+MODULE_PARM_DESC(pixelconv,
+                "enable pixel conversion (non-zero value enables)");
+
+/* Internal data structures */
+
+static struct sgi_vino *vino;
+
+static struct vino_settings *vino_drvdata;
+
+static const char *vino_driver_name = "vino";
+static const char *vino_driver_description = "SGI VINO";
+static const char *vino_bus_name = "GIO64 bus";
+static const char *vino_v4l_device_name_a = "SGI VINO Channel A";
+static const char *vino_v4l_device_name_b = "SGI VINO Channel B";
+
+static const struct vino_input vino_inputs[] = {
+       {
+               .name           = "Composite",
+               .std            = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+       },{
+               .name           = "S-Video",
+               .std            = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+       },{
+               .name           = "D1 (IndyCam)",
+               .std            = V4L2_STD_NTSC,
+       }
+};
+
+static const struct vino_data_format vino_data_formats[] = {
+       {
+               .description    = "8-bit greyscale",
+               .bpp            = 1,
+               .pixelformat    = V4L2_PIX_FMT_GREY,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },{
+               .description    = "8-bit dithered RGB 3-3-2",
+               .bpp            = 1,
+               .pixelformat    = V4L2_PIX_FMT_RGB332,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       },{
+               .description    = "32-bit RGB",
+               .bpp            = 4,
+               .pixelformat    = V4L2_PIX_FMT_RGB32,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       },{
+               .description    = "YUV 4:2:2",
+               .bpp            = 4,
+               .pixelformat    = V4L2_PIX_FMT_YUYV, // XXX: swapped?
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       }/*,{
+               .description    = "24-bit RGB",
+               .bpp            = 3,
+               .pixelformat    = V4L2_PIX_FMT_RGB24,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               }*/
+};
+
+static const struct vino_data_norm vino_data_norms[] = {
+       {
+               .description    = "NTSC",
+               .std            = V4L2_STD_NTSC,
+               .fps_min        = 6,
+               .fps_max        = 30,
+               .framelines     = 525,
+               .width          = VINO_NTSC_WIDTH,
+               .height         = VINO_NTSC_HEIGHT,
+               .odd            = {
+                       .top    = VINO_CLIPPING_START_ODD_NTSC,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_ODD_NTSC
+                       + VINO_NTSC_HEIGHT / 2 - 1,
+                       .right  = VINO_NTSC_WIDTH,
+               },
+               .even           = {
+                       .top    = VINO_CLIPPING_START_EVEN_NTSC,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_EVEN_NTSC
+                       + VINO_NTSC_HEIGHT / 2 - 1,
+                       .right  = VINO_NTSC_WIDTH,
+               },
+       },{
+               .description    = "PAL",
+               .std            = V4L2_STD_PAL,
+               .fps_min        = 5,
+               .fps_max        = 25,
+               .framelines     = 625,
+               .width          = VINO_PAL_WIDTH,
+               .height         = VINO_PAL_HEIGHT,
+               .odd            = {
+                       .top    = VINO_CLIPPING_START_ODD_PAL,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_ODD_PAL
+                       + VINO_PAL_HEIGHT / 2 - 1,
+                       .right  = VINO_PAL_WIDTH,
+               },
+               .even           = {
+                       .top    = VINO_CLIPPING_START_EVEN_PAL,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_EVEN_PAL
+                       + VINO_PAL_HEIGHT / 2 - 1,
+                       .right  = VINO_PAL_WIDTH,
+               },
+       },{
+               .description    = "SECAM",
+               .std            = V4L2_STD_SECAM,
+               .fps_min        = 5,
+               .fps_max        = 25,
+               .framelines     = 625,
+               .width          = VINO_PAL_WIDTH,
+               .height         = VINO_PAL_HEIGHT,
+               .odd            = {
+                       .top    = VINO_CLIPPING_START_ODD_PAL,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_ODD_PAL
+                       + VINO_PAL_HEIGHT / 2 - 1,
+                       .right  = VINO_PAL_WIDTH,
+               },
+               .even           = {
+                       .top    = VINO_CLIPPING_START_EVEN_PAL,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_EVEN_PAL
+                       + VINO_PAL_HEIGHT / 2 - 1,
+                       .right  = VINO_PAL_WIDTH,
+               },
+       },{
+               .description    = "NTSC (D1 input)",
+               .std            = V4L2_STD_NTSC,
+               .fps_min        = 6,
+               .fps_max        = 30,
+               .framelines     = 525,
+               .width          = VINO_NTSC_WIDTH,
+               .height         = VINO_NTSC_HEIGHT,
+               .odd            = {
+                       .top    = VINO_CLIPPING_START_ODD_D1,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_ODD_D1
+                       + VINO_NTSC_HEIGHT / 2 - 1,
+                       .right  = VINO_NTSC_WIDTH,
+               },
+               .even           = {
+                       .top    = VINO_CLIPPING_START_EVEN_D1,
+                       .left   = 0,
+                       .bottom = VINO_CLIPPING_START_EVEN_D1
+                       + VINO_NTSC_HEIGHT / 2 - 1,
+                       .right  = VINO_NTSC_WIDTH,
+               },
+       }
+};
+
+#define VINO_INDYCAM_V4L2_CONTROL_COUNT                9
+
+struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
+       {
+               .id = V4L2_CID_AUTOGAIN,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Automatic Gain Control",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = INDYCAM_AGC_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_AUTO_WHITE_BALANCE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Automatic White Balance",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = INDYCAM_AWB_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_GAIN,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Gain",
+               .minimum = INDYCAM_GAIN_MIN,
+               .maximum = INDYCAM_GAIN_MAX,
+               .step = 1,
+               .default_value = INDYCAM_GAIN_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_PRIVATE_BASE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Red Saturation",
+               .minimum = INDYCAM_RED_SATURATION_MIN,
+               .maximum = INDYCAM_RED_SATURATION_MAX,
+               .step = 1,
+               .default_value = INDYCAM_RED_SATURATION_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_PRIVATE_BASE + 1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Blue Saturation",
+               .minimum = INDYCAM_BLUE_SATURATION_MIN,
+               .maximum = INDYCAM_BLUE_SATURATION_MAX,
+               .step = 1,
+               .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_RED_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Red Balance",
+               .minimum = INDYCAM_RED_BALANCE_MIN,
+               .maximum = INDYCAM_RED_BALANCE_MAX,
+               .step = 1,
+               .default_value = INDYCAM_RED_BALANCE_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_BLUE_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Blue Balance",
+               .minimum = INDYCAM_BLUE_BALANCE_MIN,
+               .maximum = INDYCAM_BLUE_BALANCE_MAX,
+               .step = 1,
+               .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_EXPOSURE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Shutter Control",
+               .minimum = INDYCAM_SHUTTER_MIN,
+               .maximum = INDYCAM_SHUTTER_MAX,
+               .step = 1,
+               .default_value = INDYCAM_SHUTTER_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_GAMMA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Gamma",
+               .minimum = INDYCAM_GAMMA_MIN,
+               .maximum = INDYCAM_GAMMA_MAX,
+               .step = 1,
+               .default_value = INDYCAM_GAMMA_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       }
+};
+
+#define VINO_SAA7191_V4L2_CONTROL_COUNT                2
+
+struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
+       {
+               .id = V4L2_CID_HUE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hue",
+               .minimum = SAA7191_HUE_MIN,
+               .maximum = SAA7191_HUE_MAX,
+               .step = 1,
+               .default_value = SAA7191_HUE_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       },{
+               .id = V4L2_CID_PRIVATE_BASE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VTR Time Constant",
+               .minimum = SAA7191_VTRC_MIN,
+               .maximum = SAA7191_VTRC_MAX,
+               .step = 1,
+               .default_value = SAA7191_VTRC_DEFAULT,
+               .flags = 0,
+               .reserved = { 0, 0 },
+       }
 };
 
-static struct vino_video *Vino;
+/* VINO I2C bus functions */
 
 unsigned i2c_vino_getctrl(void *data)
 {
@@ -112,49 +638,49 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data =
  */
 static int i2c_vino_client_reg(struct i2c_client *client)
 {
-       int res = 0;
+       int ret = 0;
 
-       down(&Vino->input_lock);
+       spin_lock(&vino_drvdata->input_lock);
        switch (client->driver->id) {
        case I2C_DRIVERID_SAA7191:
-               if (Vino->decoder.driver)
-                       res = -EBUSY;
+               if (vino_drvdata->decoder.driver)
+                       ret = -EBUSY;
                else
-                       Vino->decoder.driver = client;
+                       vino_drvdata->decoder.driver = client;
                break;
        case I2C_DRIVERID_INDYCAM:
-               if (Vino->camera.driver)
-                       res = -EBUSY;
+               if (vino_drvdata->camera.driver)
+                       ret = -EBUSY;
                else
-                       Vino->camera.driver = client;
+                       vino_drvdata->camera.driver = client;
                break;
        default:
-               res = -ENODEV;
+               ret = -ENODEV;
        }
-       up(&Vino->input_lock);
+       spin_unlock(&vino_drvdata->input_lock);
 
-       return res;
+       return ret;
 }
 
 static int i2c_vino_client_unreg(struct i2c_client *client)
 {
-       int res = 0;
+       int ret = 0;
 
-       down(&Vino->input_lock);
-       if (client == Vino->decoder.driver) {
-               if (Vino->decoder.owner)
-                       res = -EBUSY;
+       spin_lock(&vino_drvdata->input_lock);
+       if (client == vino_drvdata->decoder.driver) {
+               if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
+                       ret = -EBUSY;
                else
-                       Vino->decoder.driver = NULL;
-       } else if (client == Vino->camera.driver) {
-               if (Vino->camera.owner)
-                       res = -EBUSY;
+                       vino_drvdata->decoder.driver = NULL;
+       } else if (client == vino_drvdata->camera.driver) {
+               if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
+                       ret = -EBUSY;
                else
-                       Vino->camera.driver = NULL;
+                       vino_drvdata->camera.driver = NULL;
        }
-       up(&Vino->input_lock);
+       spin_unlock(&vino_drvdata->input_lock);
 
-       return res;
+       return ret;
 }
 
 static struct i2c_adapter vino_i2c_adapter =
@@ -176,172 +702,3591 @@ static int vino_i2c_del_bus(void)
        return i2c_sgi_del_bus(&vino_i2c_adapter);
 }
 
+static int i2c_camera_command(unsigned int cmd, void *arg)
+{
+       return vino_drvdata->camera.driver->
+               driver->command(vino_drvdata->camera.driver,
+                               cmd, arg);
+}
 
-static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int i2c_decoder_command(unsigned int cmd, void *arg)
 {
+       return vino_drvdata->decoder.driver->
+               driver->command(vino_drvdata->decoder.driver,
+                               cmd, arg);
 }
 
-static int vino_open(struct video_device *dev, int flags)
+/* VINO framebuffer/DMA descriptor management */
+
+static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
+                                              unsigned int count)
 {
-       struct vino_device *videv = (struct vino_device *)dev;
+       unsigned int i;
 
-       return 0;
+       dprintk("vino_free_buffer_with_count(): count = %d\n", count);
+
+       for (i = 0; i < count; i++) {
+               mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i]));
+               dma_unmap_single(NULL,
+                                fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+                                PAGE_SIZE, DMA_FROM_DEVICE);
+               free_page(fb->desc_table.virtual[i]);
+       }
+
+       dma_free_coherent(NULL,
+                         VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
+                         sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
+                         fb->desc_table.dma);
+       kfree(fb->desc_table.virtual);
+
+       memset(fb, 0, sizeof(struct vino_framebuffer));
+}
+
+static void vino_free_buffer(struct vino_framebuffer *fb)
+{
+       vino_free_buffer_with_count(fb, fb->desc_table.page_count);
 }
 
-static void vino_close(struct video_device *dev)
+static int vino_allocate_buffer(struct vino_framebuffer *fb,
+                               unsigned int size)
 {
-       struct vino_device *videv = (struct vino_device *)dev;
+       unsigned int count, i, j;
+       int ret = 0;
+
+       dprintk("vino_allocate_buffer():\n");
+
+       if (size < 1)
+               return -EINVAL;
+
+       memset(fb, 0, sizeof(struct vino_framebuffer));
+
+       count = ((size / PAGE_SIZE) + 4) & ~3;
+
+       dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
+               size, count);
+
+       /* allocate memory for table with virtual (page) addresses */
+       fb->desc_table.virtual = (unsigned long *)
+               kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+       if (!fb->desc_table.virtual)
+               return -ENOMEM;
+
+       /* allocate memory for table with dma addresses
+        * (has space for four extra descriptors) */
+       fb->desc_table.dma_cpu =
+               dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+                                  sizeof(dma_addr_t), &fb->desc_table.dma,
+                                  GFP_KERNEL | GFP_DMA);
+       if (!fb->desc_table.dma_cpu) {
+               ret = -ENOMEM;
+               goto out_free_virtual;
+       }
+
+       /* allocate pages for the buffer and acquire the according
+        * dma addresses */
+       for (i = 0; i < count; i++) {
+               dma_addr_t dma_data_addr;
+
+               fb->desc_table.virtual[i] =
+                       get_zeroed_page(GFP_KERNEL | GFP_DMA);
+               if (!fb->desc_table.virtual[i]) {
+                       ret = -ENOBUFS;
+                       break;
+               }
+
+               dma_data_addr =
+                       dma_map_single(NULL,
+                                      (void *)fb->desc_table.virtual[i],
+                                      PAGE_SIZE, DMA_FROM_DEVICE);
+
+               for (j = 0; j < VINO_PAGE_RATIO; j++) {
+                       fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+                               dma_data_addr + VINO_PAGE_SIZE * j;
+               }
+
+               mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+       }
+
+       /* page_count needs to be set anyway, because the descriptor table has
+        * been allocated according to this number */
+       fb->desc_table.page_count = count;
+
+       if (ret) {
+               /* the descriptor with index i doesn't contain
+                * a valid address yet */
+               vino_free_buffer_with_count(fb, i);
+               return ret;
+       }
+
+       //fb->size = size;
+       fb->size = count * PAGE_SIZE;
+       fb->data_format = VINO_DATA_FMT_NONE;
+
+       /* set the dma stop-bit for the last (count+1)th descriptor */
+       fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+       return 0;
+
+ out_free_virtual:
+       kfree(fb->desc_table.virtual);
+       return ret;
 }
 
-static int vino_mmap(struct video_device *dev, const char *adr,
-                    unsigned long size)
+#if 0
+/* user buffers not fully implemented yet */
+static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
+                                    void *user,
+                                    unsigned int size)
 {
-       struct vino_device *videv = (struct vino_device *)dev;
+       unsigned int count, i, j;
+       int ret = 0;
+
+       dprintk("vino_prepare_user_buffer():\n");
+
+       if (size < 1)
+               return -EINVAL;
+
+       memset(fb, 0, sizeof(struct vino_framebuffer));
+
+       count = ((size / PAGE_SIZE)) & ~3;
+
+       dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
+               size, count);
+
+       /* allocate memory for table with virtual (page) addresses */
+       fb->desc_table.virtual = (unsigned long *)
+               kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+       if (!fb->desc_table.virtual)
+               return -ENOMEM;
+
+       /* allocate memory for table with dma addresses
+        * (has space for four extra descriptors) */
+       fb->desc_table.dma_cpu =
+               dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+                                  sizeof(dma_addr_t), &fb->desc_table.dma,
+                                  GFP_KERNEL | GFP_DMA);
+       if (!fb->desc_table.dma_cpu) {
+               ret = -ENOMEM;
+               goto out_free_virtual;
+       }
+
+       /* allocate pages for the buffer and acquire the according
+        * dma addresses */
+       for (i = 0; i < count; i++) {
+               dma_addr_t dma_data_addr;
+
+               fb->desc_table.virtual[i] =
+                       get_zeroed_page(GFP_KERNEL | GFP_DMA);
+               if (!fb->desc_table.virtual[i]) {
+                       ret = -ENOBUFS;
+                       break;
+               }
+
+               dma_data_addr =
+                       dma_map_single(NULL,
+                                      (void *)fb->desc_table.virtual[i],
+                                      PAGE_SIZE, DMA_FROM_DEVICE);
+
+               for (j = 0; j < VINO_PAGE_RATIO; j++) {
+                       fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+                               dma_data_addr + VINO_PAGE_SIZE * j;
+               }
+
+               mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+       }
 
-       return -EINVAL;
+       /* page_count needs to be set anyway, because the descriptor table has
+        * been allocated according to this number */
+       fb->desc_table.page_count = count;
+
+       if (ret) {
+               /* the descriptor with index i doesn't contain
+                * a valid address yet */
+               vino_free_buffer_with_count(fb, i);
+               return ret;
+       }
+
+       //fb->size = size;
+       fb->size = count * PAGE_SIZE;
+
+       /* set the dma stop-bit for the last (count+1)th descriptor */
+       fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+       return 0;
+
+ out_free_virtual:
+       kfree(fb->desc_table.virtual);
+       return ret;
 }
+#endif
 
-static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static void vino_sync_buffer(struct vino_framebuffer *fb)
 {
-       struct vino_device *videv = (struct vino_device *)dev;
+       int i;
+
+       dprintk("vino_sync_buffer():\n");
 
-       return -EINVAL;
+       for (i = 0; i < fb->desc_table.page_count; i++)
+               dma_sync_single(NULL,
+                               fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+                               PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
-static const struct video_device vino_device = {
-       .owner          = THIS_MODULE,
-       .type           = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE,
-       .hardware       = VID_HARDWARE_VINO,
-       .name           = "VINO",
-       .open           = vino_open,
-       .close          = vino_close,
-       .ioctl          = vino_ioctl,
-       .mmap           = vino_mmap,
-};
+/* Framebuffer fifo functions (need to be locked externally) */
 
-static int __init vino_init(void)
+static void vino_fifo_init(struct vino_framebuffer_fifo *f,
+                          unsigned int length)
 {
-       unsigned long rev;
-       int i, ret = 0;
+       f->length = 0;
+       f->used = 0;
+       f->head = 0;
+       f->tail = 0;
 
-       /* VINO is Indy specific beast */
-       if (ip22_is_fullhouse())
-               return -ENODEV;
+       if (length > VINO_FRAMEBUFFER_MAX_COUNT)
+               length = VINO_FRAMEBUFFER_MAX_COUNT;
 
-       /*
-        * VINO is in the EISA address space, so the sysid register will tell
-        * us if the EISA_PRESENT pin on MC has been pulled low.
-        *
-        * If EISA_PRESENT is not set we definitely don't have a VINO equiped
-        * system.
-        */
-       if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
-               printk(KERN_ERR "VINO not found\n");
-               return -ENODEV;
+       f->length = length;
+}
+
+/* returns true/false */
+static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+       unsigned int i;
+       for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
+               if (f->data[i] == id)
+                       return 1;
        }
 
-       vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
-       if (!vino)
-               return -EIO;
+       return 0;
+}
 
-       /* Okay, once we know that VINO is present we'll read its revision
-        * safe way. One never knows... */
-       if (get_dbe(rev, &(vino->rev_id))) {
-               printk(KERN_ERR "VINO: failed to read revision register\n");
-               ret = -ENODEV;
-               goto out_unmap;
+/* returns true/false */
+static int vino_fifo_full(struct vino_framebuffer_fifo *f)
+{
+       return (f->used == f->length);
+}
+
+static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
+{
+       return f->used;
+}
+
+static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+       if (id >= f->length) {
+               return VINO_QUEUE_ERROR;
        }
-       if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) {
-               printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev);
-               ret = -ENODEV;
-               goto out_unmap;
+
+       if (vino_fifo_has_id(f, id)) {
+               return VINO_QUEUE_ERROR;
        }
-       printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev));
 
-       Vino = (struct vino_video *)
-               kmalloc(sizeof(struct vino_video), GFP_KERNEL);
-       if (!Vino) {
-               ret = -ENOMEM;
-               goto out_unmap;
+       if (f->used < f->length) {
+               f->data[f->tail] = id;
+               f->tail = (f->tail + 1) % f->length;
+               f->used++;
+       } else {
+               return VINO_QUEUE_ERROR;
        }
 
-       Vino->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!Vino->dummy_page) {
-               ret = -ENOMEM;
-               goto out_free_vino;
+       return 0;
+}
+
+static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+       if (f->used > 0) {
+               *id = f->data[f->head];
+       } else {
+               return VINO_QUEUE_ERROR;
        }
-       for (i = 0; i < 4; i++)
-               Vino->dummy_buf[i] = PHYSADDR(Vino->dummy_page);
 
-       vino->control = 0;
-       /* prevent VINO from throwing spurious interrupts */
-       vino->a.next_4_desc = PHYSADDR(Vino->dummy_buf);
-       vino->b.next_4_desc = PHYSADDR(Vino->dummy_buf);
-       udelay(5);
-       vino->intr_status = 0;
-        /* set threshold level */
-        vino->a.fifo_thres = threshold_a;
-       vino->b.fifo_thres = threshold_b;
+       return 0;
+}
+
+static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+       if (f->used > 0) {
+               *id = f->data[f->head];
+               f->head = (f->head + 1) % f->length;
+               f->used--;
+       } else {
+               return VINO_QUEUE_ERROR;
+       }
+
+       return 0;
+}
 
-       init_MUTEX(&Vino->input_lock);
+/* Framebuffer queue functions */
 
-       if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) {
-               printk(KERN_ERR "VINO: irq%02d registration failed\n",
-                      SGI_VINO_IRQ);
-               ret = -EAGAIN;
-               goto out_free_page;
+/* execute with queue_lock locked */
+static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
+                                      unsigned int length)
+{
+       unsigned int i;
+
+       q->length = 0;
+       memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
+       memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
+       for (i = 0; i < length; i++) {
+               dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
+                       i);
+               vino_free_buffer(q->buffer[i]);
+               kfree(q->buffer[i]);
        }
 
-       ret = vino_i2c_add_bus();
-       if (ret) {
-               printk(KERN_ERR "VINO: I2C bus registration failed\n");
-               goto out_free_irq;
+       q->type = VINO_MEMORY_NONE;
+       q->magic = 0;
+}
+
+static void vino_queue_free(struct vino_framebuffer_queue *q)
+{
+       dprintk("vino_queue_free():\n");
+
+       if (q->magic != VINO_QUEUE_MAGIC)
+               return;
+       if (q->type != VINO_MEMORY_MMAP)
+               return;
+
+       down(&q->queue_sem);
+
+       vino_queue_free_with_count(q, q->length);
+
+       up(&q->queue_sem);
+}
+
+static int vino_queue_init(struct vino_framebuffer_queue *q,
+                          unsigned int *length)
+{
+       unsigned int i;
+       int ret = 0;
+
+       dprintk("vino_queue_init(): length = %d\n", *length);
+
+       if (q->magic == VINO_QUEUE_MAGIC) {
+               dprintk("vino_queue_init(): queue already initialized!\n");
+               return -EINVAL;
        }
 
-       if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) {
-               printk("%s, chnl %d: device registration failed.\n",
-                       Vino->chA.vdev.name, Vino->chA.chan);
-               ret = -EINVAL;
-               goto out_i2c_del_bus;
+       if (q->type != VINO_MEMORY_NONE) {
+               dprintk("vino_queue_init(): queue already initialized!\n");
+               return -EINVAL;
        }
-       if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) {
-               printk("%s, chnl %d: device registration failed.\n",
-                       Vino->chB.vdev.name, Vino->chB.chan);
-               ret = -EINVAL;
-               goto out_unregister_vdev;
+
+       if (*length < 1)
+               return -EINVAL;
+
+       down(&q->queue_sem);
+
+       if (*length > VINO_FRAMEBUFFER_MAX_COUNT)
+               *length = VINO_FRAMEBUFFER_MAX_COUNT;
+
+       q->length = 0;
+
+       for (i = 0; i < *length; i++) {
+               dprintk("vino_queue_init(): allocating buffer %d\n", i);
+               q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
+                                      GFP_KERNEL);
+               if (!q->buffer[i]) {
+                       dprintk("vino_queue_init(): kmalloc() failed\n");
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               ret = vino_allocate_buffer(q->buffer[i],
+                                          VINO_FRAMEBUFFER_SIZE);
+               if (ret) {
+                       kfree(q->buffer[i]);
+                       dprintk("vino_queue_init(): "
+                               "vino_allocate_buffer() failed\n");
+                       break;
+               }
+
+               q->buffer[i]->id = i;
+               if (i > 0) {
+                       q->buffer[i]->offset = q->buffer[i - 1]->offset +
+                               q->buffer[i - 1]->size;
+               } else {
+                       q->buffer[i]->offset = 0;
+               }
+
+               spin_lock_init(&q->buffer[i]->state_lock);
+
+               dprintk("vino_queue_init(): buffer = %d, offset = %d, "
+                       "size = %d\n", i, q->buffer[i]->offset,
+                       q->buffer[i]->size);
        }
 
-       return 0;
+       if (ret) {
+               vino_queue_free_with_count(q, i);
+               *length = 0;
+       } else {
+               q->length = *length;
+               vino_fifo_init(&q->in, q->length);
+               vino_fifo_init(&q->out, q->length);
+               q->type = VINO_MEMORY_MMAP;
+               q->magic = VINO_QUEUE_MAGIC;
+       }
 
-out_unregister_vdev:
-       video_unregister_device(&Vino->chA.vdev);
-out_i2c_del_bus:
-       vino_i2c_del_bus();
-out_free_irq:
-       free_irq(SGI_VINO_IRQ, NULL);
-out_free_page:
-       free_page(Vino->dummy_page);
-out_free_vino:
-       kfree(Vino);
-out_unmap:
-       iounmap(vino);
+       up(&q->queue_sem);
 
        return ret;
 }
 
-static void __exit vino_exit(void)
+static struct vino_framebuffer *vino_queue_add(struct
+                                              vino_framebuffer_queue *q,
+                                              unsigned int id)
 {
-       video_unregister_device(&Vino->chA.vdev);
-       video_unregister_device(&Vino->chB.vdev);
-       vino_i2c_del_bus();
-       free_irq(SGI_VINO_IRQ, NULL);
-       free_page(Vino->dummy_page);
-       kfree(Vino);
-       iounmap(vino);
+       struct vino_framebuffer *ret = NULL;
+       unsigned int total;
+       unsigned long flags;
+
+       dprintk("vino_queue_add(): id = %d\n", id);
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       if (id >= q->length)
+               goto out;
+
+       /* not needed?: if (vino_fifo_full(&q->out)) {
+               goto out;
+               }*/
+       /* check that outgoing queue isn't already full
+        * (or that it won't become full) */
+       total = vino_fifo_get_used(&q->in) +
+               vino_fifo_get_used(&q->out);
+       if (total >= q->length)
+               goto out;
+
+       if (vino_fifo_enqueue(&q->in, id))
+               goto out;
+
+       ret = q->buffer[id];
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
 }
 
-module_init(vino_init);
-module_exit(vino_exit);
+static struct vino_framebuffer *vino_queue_transfer(struct
+                                                   vino_framebuffer_queue *q)
+{
+       struct vino_framebuffer *ret = NULL;
+       struct vino_framebuffer *fb;
+       int id;
+       unsigned long flags;
 
-MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)");
-MODULE_LICENSE("GPL");
+       dprintk("vino_queue_transfer():\n");
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       // now this actually removes an entry from the incoming queue
+       if (vino_fifo_dequeue(&q->in, &id)) {
+               goto out;
+       }
+
+       dprintk("vino_queue_transfer(): id = %d\n", id);
+       fb = q->buffer[id];
+
+       // we have already checked that the outgoing queue is not full, but...
+       if (vino_fifo_enqueue(&q->out, id)) {
+               printk(KERN_ERR "vino_queue_transfer(): "
+                      "outgoing queue is full, this shouldn't happen!\n");
+               goto out;
+       }
+
+       ret = fb;
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+/* returns true/false */
+static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
+                                       unsigned int id)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       ret = vino_fifo_has_id(&q->in, id);
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+/* returns true/false */
+static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
+                                       unsigned int id)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       ret = vino_fifo_has_id(&q->out, id);
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
+                                  unsigned int *used)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return VINO_QUEUE_ERROR;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0) {
+               ret = VINO_QUEUE_ERROR;
+               goto out;
+       }
+
+       *used = vino_fifo_get_used(&q->in);
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
+                                  unsigned int *used)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return VINO_QUEUE_ERROR;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0) {
+               ret = VINO_QUEUE_ERROR;
+               goto out;
+       }
+
+       *used = vino_fifo_get_used(&q->out);
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static int vino_queue_get_total(struct vino_framebuffer_queue *q,
+                               unsigned int *total)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return VINO_QUEUE_ERROR;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0) {
+               ret = VINO_QUEUE_ERROR;
+               goto out;
+       }
+
+       *total = vino_fifo_get_used(&q->in) +
+               vino_fifo_get_used(&q->out);
+
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static struct vino_framebuffer *vino_queue_peek(struct
+                                               vino_framebuffer_queue *q,
+                                               unsigned int *id)
+{
+       struct vino_framebuffer *ret = NULL;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       if (vino_fifo_peek(&q->in, id)) {
+               goto out;
+       }
+
+       ret = q->buffer[*id];
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static struct vino_framebuffer *vino_queue_remove(struct
+                                                 vino_framebuffer_queue *q,
+                                                 unsigned int *id)
+{
+       struct vino_framebuffer *ret = NULL;
+       unsigned long flags;
+       dprintk("vino_queue_remove():\n");
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       if (vino_fifo_dequeue(&q->out, id)) {
+               goto out;
+       }
+
+       dprintk("vino_queue_remove(): id = %d\n", *id);
+       ret = q->buffer[*id];
+out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static struct
+vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
+                                       unsigned int id)
+{
+       struct vino_framebuffer *ret = NULL;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+
+       if (q->length == 0)
+               goto out;
+
+       if (id >= q->length)
+               goto out;
+
+       ret = q->buffer[id];
+ out:
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
+{
+       unsigned int length = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return length;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+       length = q->length;
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return length;
+}
+
+static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
+{
+       unsigned int i;
+       int ret = 0;
+       unsigned long flags;
+
+       if (q->magic != VINO_QUEUE_MAGIC) {
+               return ret;
+       }
+
+       spin_lock_irqsave(&q->queue_lock, flags);
+       for (i = 0; i < q->length; i++) {
+               if (q->buffer[i]->map_count > 0) {
+                       ret = 1;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&q->queue_lock, flags);
+
+       return ret;
+}
+
+/* VINO functions */
+
+/* execute with input_lock locked */
+static void vino_update_line_size(struct vino_channel_settings *vcs)
+{
+       unsigned int w = vcs->clipping.right - vcs->clipping.left;
+       unsigned int d = vcs->decimation;
+       unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
+        unsigned int lsize;
+
+       dprintk("update_line_size(): before: w = %d, d = %d, "
+               "line_size = %d\n", w, d, vcs->line_size);
+        /* line size must be multiple of 8 bytes */
+       lsize = (bpp * (w / d)) & ~7;
+       w = (lsize / bpp) * d;
+
+       vcs->clipping.right = vcs->clipping.left + w;
+       vcs->line_size = lsize;
+       dprintk("update_line_size(): after: w = %d, d = %d, "
+               "line_size = %d\n", w, d, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_clipping(struct vino_channel_settings *vcs,
+                             unsigned int x, unsigned int y,
+                             unsigned int w, unsigned int h)
+{
+       unsigned int maxwidth, maxheight;
+       unsigned int d;
+
+       maxwidth = vino_data_norms[vcs->data_norm].width;
+       maxheight = vino_data_norms[vcs->data_norm].height;
+       d = vcs->decimation;
+
+       y &= ~1;        /* odd/even fields */
+
+       if (x > maxwidth) {
+               x = 0;
+       }
+       if (y > maxheight) {
+               y = 0;
+       }
+
+       if (((w / d) < VINO_MIN_WIDTH)
+           || ((h / d) < VINO_MIN_HEIGHT)) {
+               w = VINO_MIN_WIDTH * d;
+               h = VINO_MIN_HEIGHT * d;
+       }
+
+       if ((x + w) > maxwidth) {
+               w = maxwidth - x;
+               if ((w / d) < VINO_MIN_WIDTH)
+                       x = maxwidth - VINO_MIN_WIDTH * d;
+       }
+       if ((y + h) > maxheight) {
+               h = maxheight - y;
+               if ((h / d) < VINO_MIN_HEIGHT)
+                       y = maxheight - VINO_MIN_HEIGHT * d;
+       }
+
+       vcs->clipping.left = x;
+       vcs->clipping.top = y;
+       vcs->clipping.right = x + w;
+       vcs->clipping.bottom = y + h;
+
+       vino_update_line_size(vcs);
+
+       dprintk("clipping %d, %d, %d, %d / %d - %d\n",
+               vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
+               vcs->clipping.bottom, vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_clipping(struct vino_channel_settings *vcs)
+{
+       vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
+                         vino_data_norms[vcs->data_norm].height);
+}
+
+/* execute with input_lock locked */
+static void vino_set_scaling(struct vino_channel_settings *vcs,
+                            unsigned int w, unsigned int h)
+{
+       unsigned int x, y, curw, curh, d;
+
+       x = vcs->clipping.left;
+       y = vcs->clipping.top;
+       curw = vcs->clipping.right - vcs->clipping.left;
+       curh = vcs->clipping.bottom - vcs->clipping.top;
+
+       d = max(curw / w, curh / h);
+
+       dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
+               w, h, curw, curh, d);
+
+       if (d < 1) {
+               d = 1;
+       }
+       if (d > 8) {
+               d = 8;
+       }
+
+       vcs->decimation = d;
+       vino_set_clipping(vcs, x, y, w * d, h * d);
+
+       dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
+               vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
+               vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_reset_scaling(struct vino_channel_settings *vcs)
+{
+       vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
+                        vcs->clipping.bottom - vcs->clipping.top);
+}
+
+/* execute with input_lock locked */
+static void vino_set_framerate(struct vino_channel_settings *vcs,
+                              unsigned int fps)
+{
+       unsigned int mask;
+
+       switch (vcs->data_norm) {
+       case VINO_DATA_NORM_NTSC:
+       case VINO_DATA_NORM_D1:
+               fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
+
+               if (fps < vino_data_norms[vcs->data_norm].fps_min)
+                       fps = vino_data_norms[vcs->data_norm].fps_min;
+               if (fps > vino_data_norms[vcs->data_norm].fps_max)
+                       fps = vino_data_norms[vcs->data_norm].fps_max;
+
+               switch (fps) {
+               case 6:
+                       mask = 0x003;
+                       break;
+               case 12:
+                       mask = 0x0c3;
+                       break;
+               case 18:
+                       mask = 0x333;
+                       break;
+               case 24:
+                       mask = 0x3ff;
+                       break;
+               case 30:
+                       mask = 0xfff;
+                       break;
+               default:
+                       mask = VINO_FRAMERT_FULL;
+               }
+               vcs->framert_reg = VINO_FRAMERT_RT(mask);
+               break;
+       case VINO_DATA_NORM_PAL:
+       case VINO_DATA_NORM_SECAM:
+               fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
+
+               if (fps < vino_data_norms[vcs->data_norm].fps_min)
+                       fps = vino_data_norms[vcs->data_norm].fps_min;
+               if (fps > vino_data_norms[vcs->data_norm].fps_max)
+                       fps = vino_data_norms[vcs->data_norm].fps_max;
+
+               switch (fps) {
+               case 5:
+                       mask = 0x003;
+                       break;
+               case 10:
+                       mask = 0x0c3;
+                       break;
+               case 15:
+                       mask = 0x333;
+                       break;
+               case 20:
+                       mask = 0x0ff;
+                       break;
+               case 25:
+                       mask = 0x3ff;
+                       break;
+               default:
+                       mask = VINO_FRAMERT_FULL;
+               }
+               vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
+               break;
+       }
+
+       vcs->fps = fps;
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_framerate(struct vino_channel_settings *vcs)
+{
+       vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
+}
+
+/*
+ * Prepare VINO for DMA transfer...
+ * (execute only with vino_lock and input_lock locked)
+ */
+static int vino_dma_setup(struct vino_channel_settings *vcs,
+                         struct vino_framebuffer *fb)
+{
+       u32 ctrl, intr;
+       struct sgi_vino_channel *ch;
+       const struct vino_data_norm *norm;
+
+       dprintk("vino_dma_setup():\n");
+
+       vcs->field = 0;
+       fb->frame_counter = 0;
+
+       ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+       norm = &vino_data_norms[vcs->data_norm];
+
+       ch->page_index = 0;
+       ch->line_count = 0;
+
+       /* VINO line size register is set 8 bytes less than actual */
+       ch->line_size = vcs->line_size - 8;
+
+       /* let VINO know where to transfer data */
+       ch->start_desc_tbl = fb->desc_table.dma;
+       ch->next_4_desc = fb->desc_table.dma;
+
+       /* give vino time to fetch the first four descriptors, 5 usec
+        * should be more than enough time */
+       udelay(VINO_DESC_FETCH_DELAY);
+
+       /* set the alpha register */
+       ch->alpha = vcs->alpha;
+
+       /* set clipping registers */
+       ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
+               VINO_CLIP_EVEN(norm->even.top +
+                              vcs->clipping.top / 2) |
+               VINO_CLIP_X(vcs->clipping.left);
+       ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
+                                    vcs->clipping.bottom / 2 - 1) |
+               VINO_CLIP_EVEN(norm->even.top +
+                              vcs->clipping.bottom / 2 - 1) |
+               VINO_CLIP_X(vcs->clipping.right);
+       /* FIXME: end-of-field bug workaround
+                      VINO_CLIP_X(VINO_PAL_WIDTH);
+        */
+
+       /* set the size of actual content in the buffer (DECIMATION !) */
+       fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
+                        vcs->decimation) *
+               ((vcs->clipping.bottom - vcs->clipping.top) /
+                vcs->decimation) *
+               vino_data_formats[vcs->data_format].bpp;
+
+       ch->frame_rate = vcs->framert_reg;
+
+       ctrl = vino->control;
+       intr = vino->intr_status;
+
+       if (vcs->channel == VINO_CHANNEL_A) {
+               /* All interrupt conditions for this channel was cleared
+                * so clear the interrupt status register and enable
+                * interrupts */
+               intr &= ~VINO_INTSTAT_A;
+               ctrl |= VINO_CTRL_A_INT;
+
+               /* enable synchronization */
+               ctrl |= VINO_CTRL_A_SYNC_ENBL;
+
+               /* enable frame assembly */
+               ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
+
+               /* set decimation used */
+               if (vcs->decimation < 2)
+                       ctrl &= ~VINO_CTRL_A_DEC_ENBL;
+               else {
+                       ctrl |= VINO_CTRL_A_DEC_ENBL;
+                       ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
+                       ctrl |= (vcs->decimation - 1) <<
+                               VINO_CTRL_A_DEC_SCALE_SHIFT;
+               }
+
+               /* select input interface */
+               if (vcs->input == VINO_INPUT_D1)
+                       ctrl |= VINO_CTRL_A_SELECT;
+               else
+                       ctrl &= ~VINO_CTRL_A_SELECT;
+
+               /* palette */
+               ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
+                         VINO_CTRL_A_DITHER);
+       } else {
+               intr &= ~VINO_INTSTAT_B;
+               ctrl |= VINO_CTRL_B_INT;
+
+               ctrl |= VINO_CTRL_B_SYNC_ENBL;
+               ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
+
+               if (vcs->decimation < 2)
+                       ctrl &= ~VINO_CTRL_B_DEC_ENBL;
+               else {
+                       ctrl |= VINO_CTRL_B_DEC_ENBL;
+                       ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
+                       ctrl |= (vcs->decimation - 1) <<
+                               VINO_CTRL_B_DEC_SCALE_SHIFT;
+
+               }
+               if (vcs->input == VINO_INPUT_D1)
+                       ctrl |= VINO_CTRL_B_SELECT;
+               else
+                       ctrl &= ~VINO_CTRL_B_SELECT;
+
+               ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
+                         VINO_CTRL_B_DITHER);
+       }
+
+       /* set palette */
+       fb->data_format = vcs->data_format;
+
+       switch (vcs->data_format) {
+               case VINO_DATA_FMT_GREY:
+                       ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+                               VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
+                       break;
+               case VINO_DATA_FMT_RGB32:
+                       ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+                               VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
+                       break;
+               case VINO_DATA_FMT_YUV:
+                       /* nothing needs to be done */
+                       break;
+               case VINO_DATA_FMT_RGB332:
+                       ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+                               VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
+                               VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
+                       break;
+       }
+
+       vino->intr_status = intr;
+       vino->control = ctrl;
+
+       return 0;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_start(struct vino_channel_settings *vcs)
+{
+       u32 ctrl = vino->control;
+
+       dprintk("vino_dma_start():\n");
+       ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+               VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
+       vino->control = ctrl;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_stop(struct vino_channel_settings *vcs)
+{
+       u32 ctrl = vino->control;
+
+       ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+               ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
+       vino->control = ctrl;
+       dprintk("vino_dma_stop():\n");
+}
+
+/*
+ * Load dummy page to descriptor registers. This prevents generating of
+ * spurious interrupts. (execute only with vino_lock locked)
+ */
+static void vino_clear_interrupt(struct vino_channel_settings *vcs)
+{
+       struct sgi_vino_channel *ch;
+
+       ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+
+       ch->page_index = 0;
+       ch->line_count = 0;
+
+       ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
+       ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
+
+       udelay(VINO_DESC_FETCH_DELAY);
+       dprintk("channel %c clear interrupt condition\n",
+              (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
+}
+
+static int vino_capture(struct vino_channel_settings *vcs,
+                       struct vino_framebuffer *fb)
+{
+       int err = 0;
+       unsigned long flags, flags2;
+
+       spin_lock_irqsave(&fb->state_lock, flags);
+
+       if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+               err = -EBUSY;
+       fb->state = VINO_FRAMEBUFFER_IN_USE;
+
+       spin_unlock_irqrestore(&fb->state_lock, flags);
+
+       if (err)
+               return err;
+
+       spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+       spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
+
+       vino_dma_setup(vcs, fb);
+       vino_dma_start(vcs);
+
+       spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
+       spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+       return err;
+}
+
+static
+struct vino_framebuffer *vino_capture_enqueue(struct
+                                             vino_channel_settings *vcs,
+                                             unsigned int index)
+{
+       struct vino_framebuffer *fb;
+       unsigned long flags;
+
+       dprintk("vino_capture_enqueue():\n");
+
+       spin_lock_irqsave(&vcs->capture_lock, flags);
+
+       fb = vino_queue_add(&vcs->fb_queue, index);
+       if (fb == NULL) {
+               dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
+                       "queue full?\n");
+               goto out;
+       }
+out:
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+       return fb;
+}
+
+static int vino_capture_next(struct vino_channel_settings *vcs, int start)
+{
+       struct vino_framebuffer *fb;
+       unsigned int incoming, id;
+       int err = 0;
+       unsigned long flags, flags2;
+
+       dprintk("vino_capture_next():\n");
+
+       spin_lock_irqsave(&vcs->capture_lock, flags);
+
+       if (start) {
+               /* start capture only if capture isn't in progress already */
+               if (vcs->capturing) {
+                       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+                       return 0;
+               }
+
+       } else {
+               /* capture next frame:
+                * stop capture if capturing is not set */
+               if (!vcs->capturing) {
+                       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+                       return 0;
+               }
+       }
+
+       err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+       if (err) {
+               dprintk("vino_capture_next(): vino_queue_get_incoming() "
+                       "failed\n");
+               err = -EINVAL;
+               goto out;
+       }
+       if (incoming == 0) {
+               dprintk("vino_capture_next(): no buffers available\n");
+               goto out;
+       }
+
+       fb = vino_queue_peek(&vcs->fb_queue, &id);
+       if (fb == NULL) {
+               dprintk("vino_capture_next(): vino_queue_peek() failed\n");
+               err = -EINVAL;
+               goto out;
+       }
+
+       spin_lock_irqsave(&fb->state_lock, flags2);
+       fb->state = VINO_FRAMEBUFFER_UNUSED;
+       spin_unlock_irqrestore(&fb->state_lock, flags2);
+
+       if (start) {
+               vcs->capturing = 1;
+       }
+
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+       err = vino_capture(vcs, fb);
+
+       return err;
+
+out:
+       vcs->capturing = 0;
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+       return err;
+}
+
+static int vino_is_capturing(struct vino_channel_settings *vcs)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vcs->capture_lock, flags);
+
+       ret = vcs->capturing;
+
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+       return ret;
+}
+
+/* waits until a frame is captured */
+static int vino_wait_for_frame(struct vino_channel_settings *vcs)
+{
+       wait_queue_t wait;
+       int err = 0;
+
+       dprintk("vino_wait_for_frame():\n");
+
+       init_waitqueue_entry(&wait, current);
+       /* add ourselves into wait queue */
+       add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+       /* and set current state */
+       set_current_state(TASK_INTERRUPTIBLE);
+
+       /* to ensure that schedule_timeout will return immediately
+        * if VINO interrupt was triggred meanwhile */
+       schedule_timeout(HZ / 10);
+
+       if (signal_pending(current))
+               err = -EINTR;
+
+       remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+       dprintk("vino_wait_for_frame(): waiting for frame %s\n",
+               err ? "failed" : "ok");
+
+       return err;
+}
+
+/* the function assumes that PAGE_SIZE % 4 == 0 */
+static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
+       unsigned char *pageptr;
+       unsigned int page, i;
+       unsigned char a;
+
+       for (page = 0; page < fb->desc_table.page_count; page++) {
+               pageptr = (unsigned char *)fb->desc_table.virtual[page];
+
+               for (i = 0; i < PAGE_SIZE; i += 4) {
+                       a = pageptr[0];
+                       pageptr[0] = pageptr[3];
+                       pageptr[1] = pageptr[2];
+                       pageptr[2] = pageptr[1];
+                       pageptr[3] = a;
+                       pageptr += 4;
+               }
+       }
+}
+
+/* checks if the buffer is in correct state and syncs data */
+static int vino_check_buffer(struct vino_channel_settings *vcs,
+                            struct vino_framebuffer *fb)
+{
+       int err = 0;
+       unsigned long flags;
+
+       dprintk("vino_check_buffer():\n");
+
+       spin_lock_irqsave(&fb->state_lock, flags);
+       switch (fb->state) {
+       case VINO_FRAMEBUFFER_IN_USE:
+               err = -EIO;
+               break;
+       case VINO_FRAMEBUFFER_READY:
+               vino_sync_buffer(fb);
+               fb->state = VINO_FRAMEBUFFER_UNUSED;
+               break;
+       default:
+               err = -EINVAL;
+       }
+       spin_unlock_irqrestore(&fb->state_lock, flags);
+
+       if (!err) {
+               if (vino_pixel_conversion
+                   && (fb->data_format == VINO_DATA_FMT_RGB32)) {
+                       vino_convert_to_rgba(fb);
+               }
+       } else if (err && (err != -EINVAL)) {
+               dprintk("vino_check_buffer(): buffer not ready\n");
+
+               spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+               vino_dma_stop(vcs);
+               vino_clear_interrupt(vcs);
+               spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+       }
+
+       return err;
+}
+
+/* forcefully terminates capture */
+static void vino_capture_stop(struct vino_channel_settings *vcs)
+{
+       unsigned int incoming = 0, outgoing = 0, id;
+       unsigned long flags, flags2;
+
+       dprintk("vino_capture_stop():\n");
+
+       spin_lock_irqsave(&vcs->capture_lock, flags);
+       /* unset capturing to stop queue processing */
+       vcs->capturing = 0;
+
+       spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
+
+       vino_dma_stop(vcs);
+       vino_clear_interrupt(vcs);
+
+       spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
+
+       /* remove all items from the queue */
+       if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+               dprintk("vino_capture_stop(): "
+                       "vino_queue_get_incoming() failed\n");
+               goto out;
+       }
+       while (incoming > 0) {
+               vino_queue_transfer(&vcs->fb_queue);
+
+               if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+                       dprintk("vino_capture_stop(): "
+                               "vino_queue_get_incoming() failed\n");
+                       goto out;
+               }
+       }
+
+       if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+               dprintk("vino_capture_stop(): "
+                       "vino_queue_get_outgoing() failed\n");
+               goto out;
+       }
+       while (outgoing > 0) {
+               vino_queue_remove(&vcs->fb_queue, &id);
+
+               if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+                       dprintk("vino_capture_stop(): "
+                               "vino_queue_get_outgoing() failed\n");
+                       goto out;
+               }
+       }
+
+out:
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+}
+
+static int vino_capture_failed(struct vino_channel_settings *vcs)
+{
+       struct vino_framebuffer *fb;
+       unsigned long flags;
+       unsigned int i;
+       int ret;
+
+       dprintk("vino_capture_failed():\n");
+
+       spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+
+       vino_dma_stop(vcs);
+       vino_clear_interrupt(vcs);
+
+       spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+       ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
+       if (ret == VINO_QUEUE_ERROR) {
+               dprintk("vino_queue_get_incoming() failed\n");
+               return -EINVAL;
+       }
+       if (i == 0) {
+               /* no buffers to process */
+               return 0;
+       }
+
+       fb = vino_queue_peek(&vcs->fb_queue, &i);
+       if (fb == NULL) {
+               dprintk("vino_queue_peek() failed\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&fb->state_lock, flags);
+       if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
+               fb->state = VINO_FRAMEBUFFER_UNUSED;
+               vino_queue_transfer(&vcs->fb_queue);
+               vino_queue_remove(&vcs->fb_queue, &i);
+               /* we should actually discard the newest frame,
+                * but who cares ... */
+       }
+       spin_unlock_irqrestore(&fb->state_lock, flags);
+
+       return 0;
+}
+
+static void vino_frame_done(struct vino_channel_settings *vcs,
+                           unsigned int fc)
+{
+       struct vino_framebuffer *fb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vcs->capture_lock, flags);
+       fb = vino_queue_transfer(&vcs->fb_queue);
+       if (!fb) {
+               spin_unlock_irqrestore(&vcs->capture_lock, flags);
+               dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
+               return;
+       }
+       spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+       fb->frame_counter = fc;
+       do_gettimeofday(&fb->timestamp);
+
+       spin_lock_irqsave(&fb->state_lock, flags);
+       if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+               fb->state = VINO_FRAMEBUFFER_READY;
+       spin_unlock_irqrestore(&fb->state_lock, flags);
+
+       wake_up(&vcs->fb_queue.frame_wait_queue);
+
+       vino_capture_next(vcs, 0);
+}
+
+static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       u32 intr;
+       unsigned int fc_a, fc_b;
+       int done_a = 0;
+       int done_b = 0;
+
+       spin_lock(&vino_drvdata->vino_lock);
+
+       intr = vino->intr_status;
+       fc_a = vino->a.field_counter / 2;
+       fc_b = vino->b.field_counter / 2;
+
+       // TODO: handle error-interrupts in some special way ?
+
+       if (intr & VINO_INTSTAT_A) {
+               if (intr & VINO_INTSTAT_A_EOF) {
+                       vino_drvdata->a.field++;
+                       if (vino_drvdata->a.field > 1) {
+                               vino_dma_stop(&vino_drvdata->a);
+                               vino_clear_interrupt(&vino_drvdata->a);
+                               vino_drvdata->a.field = 0;
+                               done_a = 1;
+                       }
+                       dprintk("intr: channel A end-of-field interrupt: "
+                               "%04x\n", intr);
+               } else {
+                       vino_dma_stop(&vino_drvdata->a);
+                       vino_clear_interrupt(&vino_drvdata->a);
+                       done_a = 1;
+                       dprintk("channel A error interrupt: %04x\n", intr);
+               }
+       }
+       if (intr & VINO_INTSTAT_B) {
+               if (intr & VINO_INTSTAT_B_EOF) {
+                       vino_drvdata->b.field++;
+                       if (vino_drvdata->b.field > 1) {
+                               vino_dma_stop(&vino_drvdata->b);
+                               vino_clear_interrupt(&vino_drvdata->b);
+                               vino_drvdata->b.field = 0;
+                               done_b = 1;
+                       }
+                       dprintk("intr: channel B end-of-field interrupt: "
+                               "%04x\n", intr);
+               } else {
+                       vino_dma_stop(&vino_drvdata->b);
+                       vino_clear_interrupt(&vino_drvdata->b);
+                       done_b = 1;
+                       dprintk("channel B error interrupt: %04x\n", intr);
+               }
+       }
+
+       /* always remember to clear interrupt status */
+       vino->intr_status = ~intr;
+
+       spin_unlock(&vino_drvdata->vino_lock);
+
+       if (done_a) {
+               vino_frame_done(&vino_drvdata->a, fc_a);
+               dprintk("channel A frame done, interrupt: %d\n", intr);
+       }
+       if (done_b) {
+               vino_frame_done(&vino_drvdata->b, fc_b);
+               dprintk("channel B frame done, interrupt: %d\n", intr);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/* VINO video input management */
+
+static int vino_get_saa7191_input(int input)
+{
+       switch (input) {
+       case VINO_INPUT_COMPOSITE:
+               return SAA7191_INPUT_COMPOSITE;
+       case VINO_INPUT_SVIDEO:
+               return SAA7191_INPUT_SVIDEO;
+       default:
+               printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
+                      "invalid input!\n");
+               return -1;
+       }
+}
+
+static int vino_get_saa7191_norm(int norm)
+{
+       switch (norm) {
+       case VINO_DATA_NORM_AUTO:
+               return SAA7191_NORM_AUTO;
+       case VINO_DATA_NORM_PAL:
+               return SAA7191_NORM_PAL;
+       case VINO_DATA_NORM_NTSC:
+               return SAA7191_NORM_NTSC;
+       case VINO_DATA_NORM_SECAM:
+               return SAA7191_NORM_SECAM;
+       default:
+               printk(KERN_ERR "VINO: vino_get_saa7191_norm(): "
+                      "invalid norm!\n");
+               return -1;
+       }
+}
+
+/* execute with input_lock locked */
+static int vino_is_input_owner(struct vino_channel_settings *vcs)
+{
+       switch(vcs->input) {
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               return (vino_drvdata->decoder.owner == vcs->channel);
+       case VINO_INPUT_D1:
+               return (vino_drvdata->camera.owner == vcs->channel);
+       default:
+               return 0;
+       }
+}
+
+static int vino_acquire_input(struct vino_channel_settings *vcs)
+{
+       int ret = 0;
+
+       dprintk("vino_acquire_input():\n");
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       /* First try D1 and then SAA7191 */
+       if (vino_drvdata->camera.driver
+           && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
+               if (i2c_use_client(vino_drvdata->camera.driver)) {
+                       ret = -ENODEV;
+                       goto out;
+               }
+
+               vino_drvdata->camera.owner = vcs->channel;
+               vcs->input = VINO_INPUT_D1;
+               vcs->data_norm = VINO_DATA_NORM_D1;
+       } else if (vino_drvdata->decoder.driver
+                  && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
+               int saa7191_input;
+               int saa7191_norm;
+
+               if (i2c_use_client(vino_drvdata->decoder.driver)) {
+                       ret = -ENODEV;
+                       goto out;
+               }
+
+               vino_drvdata->decoder.owner = vcs->channel;
+               vcs->input = VINO_INPUT_COMPOSITE;
+               vcs->data_norm = VINO_DATA_NORM_PAL;
+
+               saa7191_input = vino_get_saa7191_input(vcs->input);
+               i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+
+               saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+               i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+       } else {
+               vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
+                       vino_drvdata->b.input : vino_drvdata->a.input;
+               vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
+                       vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
+       }
+
+       if (vcs->input == VINO_INPUT_NONE) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (vino_is_input_owner(vcs)) {
+               vino_set_default_clipping(vcs);
+               vino_set_default_framerate(vcs);
+       }
+
+       dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return ret;
+}
+
+static int vino_set_input(struct vino_channel_settings *vcs, int input)
+{
+       struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+               &vino_drvdata->b : &vino_drvdata->a;
+       int ret = 0;
+
+       dprintk("vino_set_input():\n");
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       if (vcs->input == input)
+               goto out;
+
+       switch(input) {
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               if (!vino_drvdata->decoder.driver) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
+                       if (i2c_use_client(vino_drvdata->decoder.driver)) {
+                               ret = -ENODEV;
+                               goto out;
+                       }
+                       vino_drvdata->decoder.owner = vcs->channel;
+               }
+
+               if (vino_drvdata->decoder.owner == vcs->channel) {
+                       int saa7191_input;
+                       int saa7191_norm;
+
+                       vcs->input = input;
+                       vcs->data_norm = VINO_DATA_NORM_PAL;
+
+                       saa7191_input = vino_get_saa7191_input(vcs->input);
+                       i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+                       saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+                       i2c_decoder_command(DECODER_SAA7191_SET_NORM,
+                                           &saa7191_norm);
+               } else {
+                       if (vcs2->input != input) {
+                               ret = -EBUSY;
+                               goto out;
+                       }
+
+                       vcs->input = input;
+                       vcs->data_norm = vcs2->data_norm;
+               }
+
+               if (vino_drvdata->camera.owner == vcs->channel) {
+                       /* Transfer the ownership or release the input */
+                       if (vcs2->input == VINO_INPUT_D1) {
+                               vino_drvdata->camera.owner = vcs2->channel;
+                       } else {
+                               i2c_release_client(vino_drvdata->
+                                                  camera.driver);
+                               vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+                       }
+               }
+               break;
+       case VINO_INPUT_D1:
+               if (!vino_drvdata->camera.driver) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
+                       if (i2c_use_client(vino_drvdata->camera.driver)) {
+                               ret = -ENODEV;
+                               goto out;
+                       }
+                       vino_drvdata->camera.owner = vcs->channel;
+               }
+
+               if (vino_drvdata->decoder.owner == vcs->channel) {
+                       /* Transfer the ownership or release the input */
+                       if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+                                (vcs2->input == VINO_INPUT_SVIDEO)) {
+                               vino_drvdata->decoder.owner = vcs2->channel;
+                       } else {
+                               i2c_release_client(vino_drvdata->
+                                                  decoder.driver);
+                               vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+                       }
+               }
+
+               vcs->input = input;
+               vcs->data_norm = VINO_DATA_NORM_D1;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out;
+       }
+
+       vino_set_default_clipping(vcs);
+       vino_set_default_framerate(vcs);
+
+       dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return ret;
+}
+
+static void vino_release_input(struct vino_channel_settings *vcs)
+{
+       struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+               &vino_drvdata->b : &vino_drvdata->a;
+
+       dprintk("vino_release_input():\n");
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       /* Release ownership of the channel
+        * and if the other channel takes input from
+        * the same source, transfer the ownership */
+       if (vino_drvdata->camera.owner == vcs->channel) {
+               if (vcs2->input == VINO_INPUT_D1) {
+                       vino_drvdata->camera.owner = vcs2->channel;
+               } else {
+                       i2c_release_client(vino_drvdata->camera.driver);
+                       vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+               }
+       } else if (vino_drvdata->decoder.owner == vcs->channel) {
+               if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+                        (vcs2->input == VINO_INPUT_SVIDEO)) {
+                       vino_drvdata->decoder.owner = vcs2->channel;
+               } else {
+                       i2c_release_client(vino_drvdata->decoder.driver);
+                       vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+               }
+       }
+       vcs->input = VINO_INPUT_NONE;
+
+       spin_unlock(&vino_drvdata->input_lock);
+}
+
+/* execute with input_lock locked */
+static int vino_set_data_norm(struct vino_channel_settings *vcs,
+                             unsigned int data_norm)
+{
+       int saa7191_norm;
+
+       switch (vcs->input) {
+       case VINO_INPUT_D1:
+               /* only one "norm" supported */
+               if (data_norm != VINO_DATA_NORM_D1)
+                       return -EINVAL;
+               break;
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+
+               saa7191_norm = vino_get_saa7191_norm(data_norm);
+
+               i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+               vcs->data_norm = data_norm;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* V4L2 helper functions */
+
+static int vino_find_data_format(__u32 pixelformat)
+{
+       int i;
+
+       for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
+               if (vino_data_formats[i].pixelformat == pixelformat)
+                       return i;
+       }
+
+       return VINO_DATA_FMT_NONE;
+}
+
+static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index)
+{
+       int data_norm = VINO_DATA_NORM_NONE;
+
+       spin_lock(&vino_drvdata->input_lock);
+       switch(vcs->input) {
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               if (index == 0) {
+                       data_norm = VINO_DATA_NORM_PAL;
+               } else if (index == 1) {
+                       data_norm = VINO_DATA_NORM_NTSC;
+               } else if (index == 2) {
+                       data_norm = VINO_DATA_NORM_SECAM;
+               }
+               break;
+       case VINO_INPUT_D1:
+               if (index == 0) {
+                       data_norm = VINO_DATA_NORM_D1;
+               }
+               break;
+       }
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return data_norm;
+}
+
+static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
+{
+       int input = VINO_INPUT_NONE;
+
+       spin_lock(&vino_drvdata->input_lock);
+       if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+               switch (index) {
+               case 0:
+                       input = VINO_INPUT_COMPOSITE;
+                       break;
+               case 1:
+                       input = VINO_INPUT_SVIDEO;
+                       break;
+               case 2:
+                       input = VINO_INPUT_D1;
+                       break;
+               }
+       } else if (vino_drvdata->decoder.driver) {
+               switch (index) {
+               case 0:
+                       input = VINO_INPUT_COMPOSITE;
+                       break;
+               case 1:
+                       input = VINO_INPUT_SVIDEO;
+                       break;
+               }
+       } else if (vino_drvdata->camera.driver) {
+               switch (index) {
+               case 0:
+                       input = VINO_INPUT_D1;
+                       break;
+               }
+       }
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return input;
+}
+
+/* execute with input_lock locked */
+static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
+{
+       __u32 index = 0;
+       // FIXME: detect when no inputs available
+
+       if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+               switch (vcs->input) {
+               case VINO_INPUT_COMPOSITE:
+                       index = 0;
+                       break;
+               case VINO_INPUT_SVIDEO:
+                       index = 1;
+                       break;
+               case VINO_INPUT_D1:
+                       index = 2;
+                       break;
+               }
+       } else if (vino_drvdata->decoder.driver) {
+               switch (vcs->input) {
+               case VINO_INPUT_COMPOSITE:
+                       index = 0;
+                       break;
+               case VINO_INPUT_SVIDEO:
+                       index = 1;
+                       break;
+               }
+       } else if (vino_drvdata->camera.driver) {
+               switch (vcs->input) {
+               case VINO_INPUT_D1:
+                       index = 0;
+                       break;
+               }
+       }
+
+       return index;
+}
+
+/* V4L2 ioctls */
+
+static void vino_v4l2_querycap(struct v4l2_capability *cap)
+{
+       memset(cap, 0, sizeof(struct v4l2_capability));
+
+       strcpy(cap->driver, vino_driver_name);
+       strcpy(cap->card, vino_driver_description);
+       strcpy(cap->bus_info, vino_bus_name);
+       cap->version = VINO_VERSION_CODE;
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_STREAMING;
+       // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+}
+
+static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
+                              struct v4l2_input *i)
+{
+       __u32 index = i->index;
+       int input;
+       dprintk("requested index = %d\n", index);
+
+       input = vino_enum_input(vcs, index);
+       if (input == VINO_INPUT_NONE)
+               return -EINVAL;
+
+       memset(i, 0, sizeof(struct v4l2_input));
+
+       i->index = index;
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       i->std = vino_inputs[input].std;
+       strcpy(i->name, vino_inputs[input].name);
+
+       if ((input == VINO_INPUT_COMPOSITE)
+           || (input == VINO_INPUT_SVIDEO)) {
+               struct saa7191_status status;
+               i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
+               i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL;
+               i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
+                            struct v4l2_input *i)
+{
+       __u32 index;
+       int input;
+
+       spin_lock(&vino_drvdata->input_lock);
+       input = vcs->input;
+       index = vino_find_input_index(vcs);
+       spin_unlock(&vino_drvdata->input_lock);
+
+       dprintk("input = %d\n", input);
+
+       if (input == VINO_INPUT_NONE) {
+               return -EINVAL;
+       }
+
+       memset(i, 0, sizeof(struct v4l2_input));
+
+       i->index = index;
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       i->std = vino_inputs[input].std;
+       strcpy(i->name, vino_inputs[input].name);
+
+       return 0;
+}
+
+static int vino_v4l2_s_input(struct vino_channel_settings *vcs,
+                            struct v4l2_input *i)
+{
+       int input;
+       dprintk("requested input = %d\n", i->index);
+
+       input = vino_enum_input(vcs, i->index);
+       if (input == VINO_INPUT_NONE)
+               return -EINVAL;
+
+       return vino_set_input(vcs, input);
+}
+
+static int vino_v4l2_enumstd(struct vino_channel_settings *vcs,
+                            struct v4l2_standard *s)
+{
+       int index = s->index;
+       int data_norm = vino_enum_data_norm(vcs, index);
+       dprintk("standard index = %d\n", index);
+
+       if (data_norm == VINO_DATA_NORM_NONE)
+               return -EINVAL;
+
+       dprintk("standard name = %s\n",
+              vino_data_norms[data_norm].description);
+
+       memset(s, 0, sizeof(struct v4l2_standard));
+       s->index = index;
+
+       s->id = vino_data_norms[data_norm].std;
+       s->frameperiod.numerator = 1;
+       s->frameperiod.denominator =
+               vino_data_norms[data_norm].fps_max;
+       s->framelines =
+               vino_data_norms[data_norm].framelines;
+       strcpy(s->name,
+              vino_data_norms[data_norm].description);
+
+       return 0;
+}
+
+static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
+                          v4l2_std_id *std)
+{
+       spin_lock(&vino_drvdata->input_lock);
+       dprintk("current standard = %d\n", vcs->data_norm);
+       *std = vino_data_norms[vcs->data_norm].std;
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return 0;
+}
+
+static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
+                          v4l2_std_id *std)
+{
+       int ret = 0;
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       /* check if the standard is valid for the current input */
+       if (vino_is_input_owner(vcs)
+           && (vino_inputs[vcs->input].std & (*std))) {
+               dprintk("standard accepted\n");
+
+               /* change the video norm for SAA7191
+                * and accept NTSC for D1 (do nothing) */
+
+               if (vcs->input == VINO_INPUT_D1)
+                       goto out;
+
+               if ((*std) & V4L2_STD_PAL) {
+                       vino_set_data_norm(vcs, VINO_DATA_NORM_PAL);
+                       vcs->data_norm = VINO_DATA_NORM_PAL;
+               } else if ((*std) & V4L2_STD_NTSC) {
+                       vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC);
+                       vcs->data_norm = VINO_DATA_NORM_NTSC;
+               } else if ((*std) & V4L2_STD_SECAM) {
+                       vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM);
+                       vcs->data_norm = VINO_DATA_NORM_SECAM;
+               } else {
+                       ret = -EINVAL;
+               }
+       } else {
+               ret = -EINVAL;
+       }
+
+out:
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return ret;
+}
+
+static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs,
+                             struct v4l2_fmtdesc *fd)
+{
+       enum v4l2_buf_type type = fd->type;
+       int index = fd->index;
+       dprintk("format index = %d\n", index);
+
+       switch (fd->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if ((fd->index < 0) ||
+                   (fd->index >= VINO_DATA_FMT_COUNT))
+                       return -EINVAL;
+               dprintk("format name = %s\n",
+                      vino_data_formats[index].description);
+
+               memset(fd, 0, sizeof(struct v4l2_fmtdesc));
+               fd->index = index;
+               fd->type = type;
+               fd->pixelformat = vino_data_formats[index].pixelformat;
+               strcpy(fd->description, vino_data_formats[index].description);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs,
+                            struct v4l2_format *f)
+{
+       struct vino_channel_settings tempvcs;
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct v4l2_pix_format *pf = &f->fmt.pix;
+
+               dprintk("requested: w = %d, h = %d\n",
+                      pf->width, pf->height);
+
+               spin_lock(&vino_drvdata->input_lock);
+               memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+               spin_unlock(&vino_drvdata->input_lock);
+
+               tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+               if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+                       tempvcs.data_format = VINO_DATA_FMT_RGB32;
+                       pf->pixelformat =
+                               vino_data_formats[tempvcs.data_format].
+                               pixelformat;
+               }
+
+               /* data format must be set before clipping/scaling */
+               vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+               dprintk("data format = %s\n",
+                      vino_data_formats[tempvcs.data_format].description);
+
+               pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+                       tempvcs.decimation;
+               pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+                       tempvcs.decimation;
+
+               pf->field = V4L2_FIELD_INTERLACED;
+               pf->bytesperline = tempvcs.line_size;
+               pf->sizeimage = tempvcs.line_size *
+                       (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+                       tempvcs.decimation;
+               pf->colorspace =
+                       vino_data_formats[tempvcs.data_format].colorspace;
+
+               pf->priv = 0;
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs,
+                          struct v4l2_format *f)
+{
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct v4l2_pix_format *pf = &f->fmt.pix;
+               spin_lock(&vino_drvdata->input_lock);
+
+               pf->width = (vcs->clipping.right - vcs->clipping.left) /
+                       vcs->decimation;
+               pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+                       vcs->decimation;
+               pf->pixelformat =
+                       vino_data_formats[vcs->data_format].pixelformat;
+
+               pf->field = V4L2_FIELD_INTERLACED;
+               pf->bytesperline = vcs->line_size;
+               pf->sizeimage = vcs->line_size *
+                       (vcs->clipping.bottom - vcs->clipping.top) /
+                       vcs->decimation;
+               pf->colorspace =
+                       vino_data_formats[vcs->data_format].colorspace;
+
+               pf->priv = 0;
+
+               spin_unlock(&vino_drvdata->input_lock);
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs,
+                          struct v4l2_format *f)
+{
+       int data_format;
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct v4l2_pix_format *pf = &f->fmt.pix;
+               spin_lock(&vino_drvdata->input_lock);
+
+               if (!vino_is_input_owner(vcs)) {
+                       spin_unlock(&vino_drvdata->input_lock);
+                       return -EINVAL;
+               }
+
+               data_format = vino_find_data_format(pf->pixelformat);
+               if (data_format == VINO_DATA_FMT_NONE) {
+                       vcs->data_format = VINO_DATA_FMT_RGB32;
+                       pf->pixelformat =
+                               vino_data_formats[vcs->data_format].
+                               pixelformat;
+               } else {
+                       vcs->data_format = data_format;
+               }
+
+               /* data format must be set before clipping/scaling */
+               vino_set_scaling(vcs, pf->width, pf->height);
+
+               dprintk("data format = %s\n",
+                      vino_data_formats[vcs->data_format].description);
+
+               pf->width = vcs->clipping.right - vcs->clipping.left;
+               pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+               pf->field = V4L2_FIELD_INTERLACED;
+               pf->bytesperline = vcs->line_size;
+               pf->sizeimage = vcs->line_size *
+                       (vcs->clipping.bottom - vcs->clipping.top) /
+                       vcs->decimation;
+               pf->colorspace =
+                       vino_data_formats[vcs->data_format].colorspace;
+
+               pf->priv = 0;
+
+               spin_unlock(&vino_drvdata->input_lock);
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
+                            struct v4l2_cropcap *ccap)
+{
+       const struct vino_data_norm *norm;
+
+       switch (ccap->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               spin_lock(&vino_drvdata->input_lock);
+               norm = &vino_data_norms[vcs->data_norm];
+               spin_unlock(&vino_drvdata->input_lock);
+
+               ccap->bounds.left = 0;
+               ccap->bounds.top = 0;
+               ccap->bounds.width = norm->width;
+               ccap->bounds.height = norm->height;
+               memcpy(&ccap->defrect, &ccap->bounds,
+                      sizeof(struct v4l2_rect));
+
+               ccap->pixelaspect.numerator = 1;
+               ccap->pixelaspect.denominator = 1;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
+                           struct v4l2_crop *c)
+{
+       switch (c->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               spin_lock(&vino_drvdata->input_lock);
+
+               c->c.left = vcs->clipping.left;
+               c->c.top = vcs->clipping.top;
+               c->c.width = vcs->clipping.right - vcs->clipping.left;
+               c->c.height = vcs->clipping.bottom - vcs->clipping.top;
+
+               spin_unlock(&vino_drvdata->input_lock);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
+                           struct v4l2_crop *c)
+{
+       switch (c->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               spin_lock(&vino_drvdata->input_lock);
+
+               if (!vino_is_input_owner(vcs)) {
+                       spin_unlock(&vino_drvdata->input_lock);
+                       return -EINVAL;
+               }
+               vino_set_clipping(vcs, c->c.left, c->c.top,
+                                 c->c.width, c->c.height);
+
+               spin_unlock(&vino_drvdata->input_lock);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
+                           struct v4l2_streamparm *sp)
+{
+       switch (sp->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct v4l2_captureparm *cp = &sp->parm.capture;
+               memset(cp, 0, sizeof(struct v4l2_captureparm));
+
+               cp->capability = V4L2_CAP_TIMEPERFRAME;
+               cp->timeperframe.numerator = 1;
+
+               spin_lock(&vino_drvdata->input_lock);
+               cp->timeperframe.denominator = vcs->fps;
+               spin_unlock(&vino_drvdata->input_lock);
+
+               // TODO: cp->readbuffers = xxx;
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
+                           struct v4l2_streamparm *sp)
+{
+       switch (sp->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct v4l2_captureparm *cp = &sp->parm.capture;
+
+               spin_lock(&vino_drvdata->input_lock);
+               if (!vino_is_input_owner(vcs)) {
+                       spin_unlock(&vino_drvdata->input_lock);
+                       return -EINVAL;
+               }
+
+               if ((cp->timeperframe.numerator == 0) ||
+                   (cp->timeperframe.denominator == 0)) {
+                       /* reset framerate */
+                       vino_set_default_framerate(vcs);
+               } else {
+                       vino_set_framerate(vcs, cp->timeperframe.denominator /
+                                          cp->timeperframe.numerator);
+               }
+               spin_unlock(&vino_drvdata->input_lock);
+
+               // TODO: set buffers according to cp->readbuffers
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs,
+                            struct v4l2_requestbuffers *rb)
+{
+       if (vcs->reading)
+               return -EBUSY;
+
+       switch (rb->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               // TODO: check queue type
+               if (rb->memory != V4L2_MEMORY_MMAP) {
+                       dprintk("type not mmap\n");
+                       return -EINVAL;
+               }
+
+               if (vino_is_capturing(vcs)) {
+                       dprintk("busy, capturing\n");
+                       return -EBUSY;
+               }
+
+               dprintk("count = %d\n", rb->count);
+               if (rb->count > 0) {
+                       if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+                               dprintk("busy, buffers still mapped\n");
+                               return -EBUSY;
+                       } else {
+                               vino_queue_free(&vcs->fb_queue);
+                               vino_queue_init(&vcs->fb_queue, &rb->count);
+                       }
+               } else {
+                       vino_capture_stop(vcs);
+                       vino_queue_free(&vcs->fb_queue);
+               }
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
+                                       struct vino_framebuffer *fb,
+                                       struct v4l2_buffer *b)
+{
+       if (vino_queue_outgoing_contains(&vcs->fb_queue,
+                                        fb->id)) {
+               b->flags &= ~V4L2_BUF_FLAG_QUEUED;
+               b->flags |= V4L2_BUF_FLAG_DONE;
+       } else if (vino_queue_incoming_contains(&vcs->fb_queue,
+                                      fb->id)) {
+               b->flags &= ~V4L2_BUF_FLAG_DONE;
+               b->flags |= V4L2_BUF_FLAG_QUEUED;
+       } else {
+               b->flags &= ~(V4L2_BUF_FLAG_DONE |
+                             V4L2_BUF_FLAG_QUEUED);
+       }
+
+       b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
+
+       if (fb->map_count > 0)
+               b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+       b->index = fb->id;
+       b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
+               V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
+       b->m.offset = fb->offset;
+       b->bytesused = fb->data_size;
+       b->length = fb->size;
+       b->field = V4L2_FIELD_INTERLACED;
+       b->sequence = fb->frame_counter;
+       memcpy(&b->timestamp, &fb->timestamp,
+              sizeof(struct timeval));
+       // b->input ?
+
+       dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
+               fb->id, fb->size, fb->data_size, fb->offset);
+}
+
+static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
+                             struct v4l2_buffer *b)
+{
+       if (vcs->reading)
+               return -EBUSY;
+
+       switch (b->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct vino_framebuffer *fb;
+
+               // TODO: check queue type
+               if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+                       dprintk("invalid index = %d\n",
+                              b->index);
+                       return -EINVAL;
+               }
+
+               fb = vino_queue_get_buffer(&vcs->fb_queue,
+                                          b->index);
+               if (fb == NULL) {
+                       dprintk("vino_queue_get_buffer() failed");
+                       return -EINVAL;
+               }
+
+               vino_v4l2_get_buffer_status(vcs, fb, b);
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
+                         struct v4l2_buffer *b)
+{
+       if (vcs->reading)
+               return -EBUSY;
+
+       switch (b->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct vino_framebuffer *fb;
+               int ret;
+
+               // TODO: check queue type
+               if (b->memory != V4L2_MEMORY_MMAP) {
+                       dprintk("type not mmap\n");
+                       return -EINVAL;
+               }
+
+               fb = vino_capture_enqueue(vcs, b->index);
+               if (fb == NULL)
+                       return -EINVAL;
+
+               vino_v4l2_get_buffer_status(vcs, fb, b);
+
+               if (vcs->streaming) {
+                       ret = vino_capture_next(vcs, 1);
+                       if (ret)
+                               return ret;
+               }
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
+                          struct v4l2_buffer *b,
+                          unsigned int nonblocking)
+{
+       if (vcs->reading)
+               return -EBUSY;
+
+       switch (b->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+               struct vino_framebuffer *fb;
+               unsigned int incoming, outgoing;
+               int err;
+
+               // TODO: check queue type
+
+               err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+               if (err) {
+                       dprintk("vino_queue_get_incoming() failed\n");
+                       return -EIO;
+               }
+               err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+               if (err) {
+                       dprintk("vino_queue_get_outgoing() failed\n");
+                       return -EIO;
+               }
+
+               dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+               if (outgoing == 0) {
+                       if (incoming == 0) {
+                               dprintk("no incoming or outgoing buffers\n");
+                               return -EINVAL;
+                       }
+                       if (nonblocking) {
+                               dprintk("non-blocking I/O was selected and "
+                                       "there are no buffers to dequeue\n");
+                               return -EAGAIN;
+                       }
+
+                       err = vino_wait_for_frame(vcs);
+                       if (err) {
+                               err = vino_wait_for_frame(vcs);
+                               if (err) {
+                                       /* interrupted */
+                                       vino_capture_failed(vcs);
+                                       return -EIO;
+                               }
+                       }
+               }
+
+               fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+               if (fb == NULL) {
+                       dprintk("vino_queue_remove() failed\n");
+                       return -EINVAL;
+               }
+
+               err = vino_check_buffer(vcs, fb);
+               if (err)
+                       return -EIO;
+
+               vino_v4l2_get_buffer_status(vcs, fb, b);
+               break;
+       }
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
+{
+       unsigned int incoming;
+       int ret;
+       if (vcs->reading)
+               return -EBUSY;
+
+       if (vcs->streaming)
+               return 0;
+
+       // TODO: check queue type
+
+       if (vino_queue_get_length(&vcs->fb_queue) < 1) {
+               dprintk("no buffers allocated\n");
+               return -EINVAL;
+       }
+
+       ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+       if (ret) {
+               dprintk("vino_queue_get_incoming() failed\n");
+               return -EINVAL;
+       }
+
+       vcs->streaming = 1;
+
+       if (incoming > 0) {
+               ret = vino_capture_next(vcs, 1);
+               if (ret) {
+                       vcs->streaming = 0;
+
+                       dprintk("couldn't start capture\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
+{
+       if (vcs->reading)
+               return -EBUSY;
+
+       if (!vcs->streaming)
+               return 0;
+
+       vino_capture_stop(vcs);
+       vcs->streaming = 0;
+
+       return 0;
+}
+
+static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
+                              struct v4l2_queryctrl *queryctrl)
+{
+       int i;
+       int err = 0;
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       switch (vcs->input) {
+       case VINO_INPUT_D1:
+               for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+                       if (vino_indycam_v4l2_controls[i].id ==
+                           queryctrl->id) {
+                               memcpy(queryctrl,
+                                      &vino_indycam_v4l2_controls[i],
+                                      sizeof(struct v4l2_queryctrl));
+                               goto found;
+                       }
+               }
+
+               err =  -EINVAL;
+               break;
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+                       if (vino_saa7191_v4l2_controls[i].id ==
+                           queryctrl->id) {
+                               memcpy(queryctrl,
+                                      &vino_saa7191_v4l2_controls[i],
+                                      sizeof(struct v4l2_queryctrl));
+                               goto found;
+                       }
+               }
+
+               err =  -EINVAL;
+               break;
+       default:
+               err =  -EINVAL;
+       }
+
+ found:
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return err;
+}
+
+static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
+                           struct v4l2_control *control)
+{
+       struct indycam_control indycam_ctrl;
+       struct saa7191_control saa7191_ctrl;
+       int err = 0;
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       switch (vcs->input) {
+       case VINO_INPUT_D1:
+               i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS,
+                                  &indycam_ctrl);
+
+               switch(control->id) {
+               case V4L2_CID_AUTOGAIN:
+                       control->value = indycam_ctrl.agc;
+                       break;
+               case V4L2_CID_AUTO_WHITE_BALANCE:
+                       control->value = indycam_ctrl.awb;
+                       break;
+               case V4L2_CID_GAIN:
+                       control->value = indycam_ctrl.gain;
+                       break;
+               case V4L2_CID_PRIVATE_BASE:
+                       control->value = indycam_ctrl.red_saturation;
+                       break;
+               case V4L2_CID_PRIVATE_BASE + 1:
+                       control->value = indycam_ctrl.blue_saturation;
+                       break;
+               case V4L2_CID_RED_BALANCE:
+                       control->value = indycam_ctrl.red_balance;
+                       break;
+               case V4L2_CID_BLUE_BALANCE:
+                       control->value = indycam_ctrl.blue_balance;
+                       break;
+               case V4L2_CID_EXPOSURE:
+                       control->value = indycam_ctrl.shutter;
+                       break;
+               case V4L2_CID_GAMMA:
+                       control->value = indycam_ctrl.gamma;
+                       break;
+               default:
+                       err = -EINVAL;
+               }
+               break;
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS,
+                                  &saa7191_ctrl);
+
+               switch(control->id) {
+               case V4L2_CID_HUE:
+                       control->value = saa7191_ctrl.hue;
+                       break;
+               case V4L2_CID_PRIVATE_BASE:
+                       control->value = saa7191_ctrl.vtrc;
+                       break;
+               default:
+                       err = -EINVAL;
+               }
+               break;
+       default:
+               err =  -EINVAL;
+       }
+
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return err;
+}
+
+static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
+                           struct v4l2_control *control)
+{
+       struct indycam_control indycam_ctrl;
+       struct saa7191_control saa7191_ctrl;
+       int i;
+       int err = 0;
+
+       spin_lock(&vino_drvdata->input_lock);
+
+       switch (vcs->input) {
+       case VINO_INPUT_D1:
+               for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+                       if (vino_indycam_v4l2_controls[i].id ==
+                           control->id) {
+                               if ((control->value >=
+                                    vino_indycam_v4l2_controls[i].minimum)
+                                   && (control->value <=
+                                       vino_indycam_v4l2_controls[i].
+                                       maximum)) {
+                                       goto ok1;
+                               } else {
+                                       err = -ERANGE;
+                                       goto error;
+                               }
+                       }
+               }
+               err = -EINVAL;
+               goto error;
+
+ok1:
+               indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED;
+               indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED;
+
+               switch(control->id) {
+               case V4L2_CID_AUTOGAIN:
+                       indycam_ctrl.agc = control->value;
+                       break;
+               case V4L2_CID_AUTO_WHITE_BALANCE:
+                       indycam_ctrl.awb = control->value;
+                       break;
+               case V4L2_CID_GAIN:
+                       indycam_ctrl.gain = control->value;
+                       break;
+               case V4L2_CID_PRIVATE_BASE:
+                       indycam_ctrl.red_saturation = control->value;
+                       break;
+               case V4L2_CID_PRIVATE_BASE + 1:
+                       indycam_ctrl.blue_saturation = control->value;
+                       break;
+               case V4L2_CID_RED_BALANCE:
+                       indycam_ctrl.red_balance = control->value;
+                       break;
+               case V4L2_CID_BLUE_BALANCE:
+                       indycam_ctrl.blue_balance = control->value;
+                       break;
+               case V4L2_CID_EXPOSURE:
+                       indycam_ctrl.shutter = control->value;
+                       break;
+               case V4L2_CID_GAMMA:
+                       indycam_ctrl.gamma = control->value;
+                       break;
+               default:
+                       err =  -EINVAL;
+               }
+
+               if (!err)
+                       i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS,
+                                          &indycam_ctrl);
+               break;
+       case VINO_INPUT_COMPOSITE:
+       case VINO_INPUT_SVIDEO:
+               for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+                       if (vino_saa7191_v4l2_controls[i].id ==
+                           control->id) {
+                               if ((control->value >=
+                                    vino_saa7191_v4l2_controls[i].minimum)
+                                   && (control->value <=
+                                       vino_saa7191_v4l2_controls[i].
+                                       maximum)) {
+                                       goto ok2;
+                               } else {
+                                       err = -ERANGE;
+                                       goto error;
+                               }
+                       }
+               }
+               err = -EINVAL;
+               goto error;
+
+ok2:
+               saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED;
+               saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED;
+
+               switch(control->id) {
+               case V4L2_CID_HUE:
+                       saa7191_ctrl.hue = control->value;
+                       break;
+               case V4L2_CID_PRIVATE_BASE:
+                       saa7191_ctrl.vtrc = control->value;
+                       break;
+               default:
+                       err =  -EINVAL;
+               }
+
+               if (!err)
+                       i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS,
+                                           &saa7191_ctrl);
+               break;
+       default:
+               err =  -EINVAL;
+       }
+
+error:
+       spin_unlock(&vino_drvdata->input_lock);
+
+       return err;
+}
+
+/* File operations */
+
+static int vino_open(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       int ret = 0;
+       dprintk("open(): channel = %c\n",
+              (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
+
+       down(&vcs->sem);
+
+       if (vcs->users) {
+               dprintk("open(): driver busy\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = vino_acquire_input(vcs);
+       if (ret) {
+               dprintk("open(): vino_acquire_input() failed\n");
+               goto out;
+       }
+
+       vcs->users++;
+
+ out:
+       up(&vcs->sem);
+
+       dprintk("open(): %s!\n", ret ? "failed" : "complete");
+
+       return ret;
+}
+
+static int vino_close(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       dprintk("close():\n");
+
+       down(&vcs->sem);
+
+       vcs->users--;
+
+       if (!vcs->users) {
+               vino_release_input(vcs);
+
+               /* stop DMA and free buffers */
+               vino_capture_stop(vcs);
+               vino_queue_free(&vcs->fb_queue);
+       }
+
+       up(&vcs->sem);
+
+       return 0;
+}
+
+static void vino_vm_open(struct vm_area_struct *vma)
+{
+       struct vino_framebuffer *fb = vma->vm_private_data;
+
+       fb->map_count++;
+       dprintk("vino_vm_open(): count = %d\n", fb->map_count);
+}
+
+static void vino_vm_close(struct vm_area_struct *vma)
+{
+       struct vino_framebuffer *fb = vma->vm_private_data;
+
+       fb->map_count--;
+       dprintk("vino_vm_close(): count = %d\n", fb->map_count);
+}
+
+static struct vm_operations_struct vino_vm_ops = {
+       .open   = vino_vm_open,
+       .close  = vino_vm_close,
+};
+
+static int vino_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+
+       unsigned long start = vma->vm_start;
+       unsigned long size = vma->vm_end - vma->vm_start;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+       struct vino_framebuffer *fb = NULL;
+       unsigned int i, length;
+       int ret = 0;
+
+       dprintk("mmap():\n");
+
+       // TODO: reject mmap if already mapped
+
+       if (down_interruptible(&vcs->sem))
+               return -EINTR;
+
+       if (vcs->reading) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       // TODO: check queue type
+
+       if (!(vma->vm_flags & VM_WRITE)) {
+               dprintk("mmap(): app bug: PROT_WRITE please\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       if (!(vma->vm_flags & VM_SHARED)) {
+               dprintk("mmap(): app bug: MAP_SHARED please\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* find the correct buffer using offset */
+       length = vino_queue_get_length(&vcs->fb_queue);
+       if (length == 0) {
+               dprintk("mmap(): queue not initialized\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       for (i = 0; i < length; i++) {
+               fb = vino_queue_get_buffer(&vcs->fb_queue, i);
+               if (fb == NULL) {
+                       dprintk("mmap(): vino_queue_get_buffer() failed\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (fb->offset == offset)
+                       goto found;
+       }
+
+       dprintk("mmap(): invalid offset = %lu\n", offset);
+       ret = -EINVAL;
+       goto out;
+
+found:
+       dprintk("mmap(): buffer = %d\n", i);
+
+       if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
+               dprintk("mmap(): failed: size = %lu > %lu\n",
+                       size, fb->desc_table.page_count * PAGE_SIZE);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       for (i = 0; i < fb->desc_table.page_count; i++) {
+               unsigned long pfn =
+                       virt_to_phys((void *)fb->desc_table.virtual[i]) >>
+                       PAGE_SHIFT;
+
+               if (size < PAGE_SIZE)
+                       break;
+
+               // protection was: PAGE_READONLY
+               if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+                                   vma->vm_page_prot)) {
+                       dprintk("mmap(): remap_pfn_range() failed\n");
+                       ret = -EAGAIN;
+                       goto out;
+               }
+
+               start += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       fb->map_count = 1;
+
+       vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+       vma->vm_flags &= ~VM_IO;
+       vma->vm_private_data = fb;
+       vma->vm_file = file;
+       vma->vm_ops = &vino_vm_ops;
+
+out:
+       up(&vcs->sem);
+
+       return ret;
+}
+
+static unsigned int vino_poll(struct file *file, poll_table *pt)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       unsigned int outgoing;
+       unsigned int ret = 0;
+
+       // lock mutex (?)
+       // TODO: this has to be corrected for different read modes
+
+       dprintk("poll():\n");
+
+       if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+               dprintk("poll(): vino_queue_get_outgoing() failed\n");
+               ret = POLLERR;
+               goto error;
+       }
+       if (outgoing > 0)
+               goto over;
+
+       poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
+
+       if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+               dprintk("poll(): vino_queue_get_outgoing() failed\n");
+               ret = POLLERR;
+               goto error;
+       }
+
+over:
+       dprintk("poll(): data %savailable\n",
+               (outgoing > 0) ? "" : "not ");
+       if (outgoing > 0) {
+               ret = POLLIN | POLLRDNORM;
+       }
+
+error:
+
+       return ret;
+}
+
+static int vino_do_ioctl(struct inode *inode, struct file *file,
+                     unsigned int cmd, void *arg)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+
+       switch (_IOC_TYPE(cmd)) {
+       case 'v':
+               dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd);
+               break;
+       case 'V':
+               dprintk("ioctl(): V4L2 %s (0x%08x)\n",
+                       v4l2_ioctl_names[_IOC_NR(cmd)], cmd);
+               break;
+       default:
+               dprintk("ioctl(): unsupported command 0x%08x\n", cmd);
+       }
+
+       switch (cmd) {
+       /* TODO: V4L1 interface (use compatibility layer?) */
+       /* V4L2 interface */
+       case VIDIOC_QUERYCAP: {
+               vino_v4l2_querycap(arg);
+               break;
+       }
+       case VIDIOC_ENUMINPUT: {
+               return vino_v4l2_enuminput(vcs, arg);
+       }
+       case VIDIOC_G_INPUT: {
+               return vino_v4l2_g_input(vcs, arg);
+       }
+       case VIDIOC_S_INPUT: {
+               return vino_v4l2_s_input(vcs, arg);
+       }
+       case VIDIOC_ENUMSTD: {
+               return vino_v4l2_enumstd(vcs, arg);
+       }
+       case VIDIOC_G_STD: {
+               return vino_v4l2_g_std(vcs, arg);
+       }
+       case VIDIOC_S_STD: {
+               return vino_v4l2_s_std(vcs, arg);
+       }
+       case VIDIOC_ENUM_FMT: {
+               return vino_v4l2_enum_fmt(vcs, arg);
+       }
+       case VIDIOC_TRY_FMT: {
+               return vino_v4l2_try_fmt(vcs, arg);
+       }
+       case VIDIOC_G_FMT: {
+               return vino_v4l2_g_fmt(vcs, arg);
+       }
+       case VIDIOC_S_FMT: {
+               return vino_v4l2_s_fmt(vcs, arg);
+       }
+       case VIDIOC_CROPCAP: {
+               return vino_v4l2_cropcap(vcs, arg);
+       }
+       case VIDIOC_G_CROP: {
+               return vino_v4l2_g_crop(vcs, arg);
+       }
+       case VIDIOC_S_CROP: {
+               return vino_v4l2_s_crop(vcs, arg);
+       }
+       case VIDIOC_G_PARM: {
+               return vino_v4l2_g_parm(vcs, arg);
+       }
+       case VIDIOC_S_PARM: {
+               return vino_v4l2_s_parm(vcs, arg);
+       }
+       case VIDIOC_REQBUFS: {
+               return vino_v4l2_reqbufs(vcs, arg);
+       }
+       case VIDIOC_QUERYBUF: {
+               return vino_v4l2_querybuf(vcs, arg);
+       }
+       case VIDIOC_QBUF: {
+               return vino_v4l2_qbuf(vcs, arg);
+       }
+       case VIDIOC_DQBUF: {
+               return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK);
+       }
+       case VIDIOC_STREAMON: {
+               return vino_v4l2_streamon(vcs);
+       }
+       case VIDIOC_STREAMOFF: {
+               return vino_v4l2_streamoff(vcs);
+       }
+       case VIDIOC_QUERYCTRL: {
+               return vino_v4l2_queryctrl(vcs, arg);
+       }
+       case VIDIOC_G_CTRL: {
+               return vino_v4l2_g_ctrl(vcs, arg);
+       }
+       case VIDIOC_S_CTRL: {
+               return vino_v4l2_s_ctrl(vcs, arg);
+       }
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return 0;
+}
+
+static int vino_ioctl(struct inode *inode, struct file *file,
+                     unsigned int cmd, unsigned long arg)
+{
+       struct video_device *dev = video_devdata(file);
+       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       int ret;
+
+       if (down_interruptible(&vcs->sem))
+               return -EINTR;
+
+       ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl);
+
+       up(&vcs->sem);
+
+       return ret;
+}
+
+/* Initialization and cleanup */
+
+// __initdata
+static int vino_init_stage = 0;
+
+static struct file_operations vino_fops = {
+       .owner          = THIS_MODULE,
+       .open           = vino_open,
+       .release        = vino_close,
+       .ioctl          = vino_ioctl,
+       .mmap           = vino_mmap,
+       .poll           = vino_poll,
+       .llseek         = no_llseek,
+};
+
+static struct video_device v4l_device_template = {
+       .name           = "NOT SET",
+       //.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
+       //      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
+       .hardware       = VID_HARDWARE_VINO,
+       .fops           = &vino_fops,
+       .minor          = -1,
+};
+
+static void vino_module_cleanup(int stage)
+{
+       switch(stage) {
+       case 10:
+               video_unregister_device(vino_drvdata->b.v4l_device);
+               vino_drvdata->b.v4l_device = NULL;
+       case 9:
+               video_unregister_device(vino_drvdata->a.v4l_device);
+               vino_drvdata->a.v4l_device = NULL;
+       case 8:
+               vino_i2c_del_bus();
+       case 7:
+               free_irq(SGI_VINO_IRQ, NULL);
+       case 6:
+               if (vino_drvdata->b.v4l_device) {
+                       video_device_release(vino_drvdata->b.v4l_device);
+                       vino_drvdata->b.v4l_device = NULL;
+               }
+       case 5:
+               if (vino_drvdata->a.v4l_device) {
+                       video_device_release(vino_drvdata->a.v4l_device);
+                       vino_drvdata->a.v4l_device = NULL;
+               }
+       case 4:
+               /* all entries in dma_cpu dummy table have the same address */
+               dma_unmap_single(NULL,
+                                vino_drvdata->dummy_desc_table.dma_cpu[0],
+                                PAGE_SIZE, DMA_FROM_DEVICE);
+               dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
+                                 * sizeof(dma_addr_t),
+                                 (void *)vino_drvdata->
+                                 dummy_desc_table.dma_cpu,
+                                 vino_drvdata->dummy_desc_table.dma);
+       case 3:
+               free_page(vino_drvdata->dummy_page);
+       case 2:
+               kfree(vino_drvdata);
+       case 1:
+               iounmap(vino);
+       case 0:
+               break;
+       default:
+               dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
+                       stage);
+       }
+}
+
+static int vino_probe(void)
+{
+       unsigned long rev_id;
+
+       if (ip22_is_fullhouse()) {
+               printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
+               return -ENODEV;
+       }
+
+       if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
+               printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
+               return -ENODEV;
+       }
+
+       vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
+       if (!vino) {
+               printk(KERN_ERR "VINO: ioremap() failed\n");
+               return -EIO;
+       }
+       vino_init_stage++;
+
+       if (get_dbe(rev_id, &(vino->rev_id))) {
+               printk(KERN_ERR "Failed to read VINO revision register\n");
+               vino_module_cleanup(vino_init_stage);
+               return -ENODEV;
+       }
+
+       if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
+               printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
+                      rev_id);
+               vino_module_cleanup(vino_init_stage);
+               return -ENODEV;
+       }
+
+       printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n",
+              VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id));
+
+       return 0;
+}
+
+static int vino_init(void)
+{
+       dma_addr_t dma_dummy_address;
+       int i;
+
+       vino_drvdata = (struct vino_settings *)
+               kmalloc(sizeof(struct vino_settings), GFP_KERNEL);
+       if (!vino_drvdata) {
+               vino_module_cleanup(vino_init_stage);
+               return -ENOMEM;
+       }
+       memset(vino_drvdata, 0, sizeof(struct vino_settings));
+       vino_init_stage++;
+
+       /* create a dummy dma descriptor */
+       vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!vino_drvdata->dummy_page) {
+               vino_module_cleanup(vino_init_stage);
+               return -ENOMEM;
+       }
+       vino_init_stage++;
+
+       // TODO: use page_count in dummy_desc_table
+
+       vino_drvdata->dummy_desc_table.dma_cpu =
+               dma_alloc_coherent(NULL,
+               VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
+               &vino_drvdata->dummy_desc_table.dma,
+               GFP_KERNEL | GFP_DMA);
+       if (!vino_drvdata->dummy_desc_table.dma_cpu) {
+               vino_module_cleanup(vino_init_stage);
+               return -ENOMEM;
+       }
+       vino_init_stage++;
+
+       dma_dummy_address = dma_map_single(NULL,
+                                          (void *)vino_drvdata->dummy_page,
+                                       PAGE_SIZE, DMA_FROM_DEVICE);
+       for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
+               vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
+       }
+
+       /* initialize VINO */
+
+       vino->control = 0;
+       vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+       vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+       udelay(VINO_DESC_FETCH_DELAY);
+
+       vino->intr_status = 0;
+
+       vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+       vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+
+       return 0;
+}
+
+static int vino_init_channel_settings(struct vino_channel_settings *vcs,
+                                unsigned int channel, const char *name)
+{
+       vcs->channel = channel;
+       vcs->input = VINO_INPUT_NONE;
+       vcs->alpha = 0;
+       vcs->users = 0;
+       vcs->data_format = VINO_DATA_FMT_GREY;
+       vcs->data_norm = VINO_DATA_NORM_NTSC;
+       vcs->decimation = 1;
+       vino_set_default_clipping(vcs);
+       vino_set_default_framerate(vcs);
+
+       vcs->capturing = 0;
+
+       init_MUTEX(&vcs->sem);
+       spin_lock_init(&vcs->capture_lock);
+
+       init_MUTEX(&vcs->fb_queue.queue_sem);
+       spin_lock_init(&vcs->fb_queue.queue_lock);
+       init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
+
+       vcs->v4l_device = video_device_alloc();
+       if (!vcs->v4l_device) {
+               vino_module_cleanup(vino_init_stage);
+               return -ENOMEM;
+       }
+       vino_init_stage++;
+
+       memcpy(vcs->v4l_device, &v4l_device_template,
+              sizeof(struct video_device));
+       strcpy(vcs->v4l_device->name, name);
+       vcs->v4l_device->release = video_device_release;
+
+       video_set_drvdata(vcs->v4l_device, vcs);
+
+       return 0;
+}
+
+static int __init vino_module_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "SGI VINO driver version %s\n",
+              VINO_MODULE_VERSION);
+
+       ret = vino_probe();
+       if (ret)
+               return ret;
+
+       ret = vino_init();
+       if (ret)
+               return ret;
+
+       /* initialize data structures */
+
+       spin_lock_init(&vino_drvdata->vino_lock);
+       spin_lock_init(&vino_drvdata->input_lock);
+
+       ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
+                                   vino_v4l_device_name_a);
+       if (ret)
+               return ret;
+
+       ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
+                                   vino_v4l_device_name_b);
+       if (ret)
+               return ret;
+
+       /* initialize hardware and register V4L devices */
+
+       ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
+               vino_driver_description, NULL);
+       if (ret) {
+               printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
+                      SGI_VINO_IRQ);
+               vino_module_cleanup(vino_init_stage);
+               return -EAGAIN;
+       }
+       vino_init_stage++;
+
+       ret = vino_i2c_add_bus();
+       if (ret) {
+               printk(KERN_ERR "VINO I2C bus registration failed\n");
+               vino_module_cleanup(vino_init_stage);
+               return ret;
+       }
+       vino_init_stage++;
+
+       ret = video_register_device(vino_drvdata->a.v4l_device,
+                                   VFL_TYPE_GRABBER, -1);
+       if (ret < 0) {
+               printk(KERN_ERR "VINO channel A Video4Linux-device "
+                      "registration failed\n");
+               vino_module_cleanup(vino_init_stage);
+               return -EINVAL;
+       }
+       vino_init_stage++;
+
+       ret = video_register_device(vino_drvdata->b.v4l_device,
+                                   VFL_TYPE_GRABBER, -1);
+       if (ret < 0) {
+               printk(KERN_ERR "VINO channel B Video4Linux-device "
+                      "registration failed\n");
+               vino_module_cleanup(vino_init_stage);
+               return -EINVAL;
+       }
+       vino_init_stage++;
+
+#if defined(CONFIG_KMOD) && defined(MODULE)
+       request_module("saa7191");
+       request_module("indycam");
+#endif
+
+       dprintk("init complete!\n");
+
+       return 0;
+}
+
+static void __exit vino_module_exit(void)
+{
+       dprintk("exiting, stage = %d ...\n", vino_init_stage);
+       vino_module_cleanup(vino_init_stage);
+       dprintk("cleanup complete, exit!\n");
+}
+
+module_init(vino_module_init);
+module_exit(vino_module_exit);
index d2fce472f35ab7543c58805b525e438eaae2389d..de2d615ae7c9492bc14b72eea236cb67a87331a7 100644 (file)
@@ -1,13 +1,19 @@
 /*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
  * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
  * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
  */
 
-#ifndef VINO_H
-#define VINO_H
+#ifndef _VINO_H_
+#define _VINO_H_
 
 #define VINO_BASE      0x00080000      /* Vino is in the EISA address space,
                                         * but it is not an EISA bus card */
+#define VINO_PAGE_SIZE 4096
 
 struct sgi_vino_channel {
        u32 _pad_alpha;
@@ -21,8 +27,9 @@ struct sgi_vino_channel {
        u32 _pad_clip_end;
        volatile u32 clip_end;
 
+#define VINO_FRAMERT_FULL      0xfff
 #define VINO_FRAMERT_PAL       (1<<0)                  /* 0=NTSC 1=PAL */
-#define VINO_FRAMERT_RT(x)     (((x) & 0x1fff) << 1)   /* bits 1:12 */
+#define VINO_FRAMERT_RT(x)     (((x) & 0xfff) << 1)    /* bits 1:12 */
        u32 _pad_frame_rate;
        volatile u32 frame_rate;
 
@@ -67,18 +74,18 @@ struct sgi_vino {
        volatile u32 rev_id;
 
 #define VINO_CTRL_LITTLE_ENDIAN                (1<<0)
-#define VINO_CTRL_A_FIELD_TRANS_INT    (1<<1)  /* Field transferred int */
-#define VINO_CTRL_A_FIFO_OF_INT                (1<<2)  /* FIFO overflow int */
-#define VINO_CTRL_A_END_DESC_TBL_INT   (1<<3)  /* End of desc table int */
-#define VINO_CTRL_A_INT                        (VINO_CTRL_A_FIELD_TRANS_INT | \
-                                        VINO_CTRL_A_FIFO_OF_INT | \
-                                        VINO_CTRL_A_END_DESC_TBL_INT)
-#define VINO_CTRL_B_FIELD_TRANS_INT    (1<<4)  /* Field transferred int */
-#define VINO_CTRL_B_FIFO_OF_INT                (1<<5)  /* FIFO overflow int */
-#define VINO_CTRL_B_END_DESC_TBL_INT   (1<<6)  /* End of desc table int */
-#define VINO_CTRL_B_INT                        (VINO_CTRL_B_FIELD_TRANS_INT | \
-                                        VINO_CTRL_B_FIFO_OF_INT | \
-                                        VINO_CTRL_B_END_DESC_TBL_INT)
+#define VINO_CTRL_A_EOF_INT            (1<<1)  /* Field transferred int */
+#define VINO_CTRL_A_FIFO_INT           (1<<2)  /* FIFO overflow int */
+#define VINO_CTRL_A_EOD_INT            (1<<3)  /* End of desc table int */
+#define VINO_CTRL_A_INT                        (VINO_CTRL_A_EOF_INT | \
+                                        VINO_CTRL_A_FIFO_INT | \
+                                        VINO_CTRL_A_EOD_INT)
+#define VINO_CTRL_B_EOF_INT            (1<<4)  /* Field transferred int */
+#define VINO_CTRL_B_FIFO_INT           (1<<5)  /* FIFO overflow int */
+#define VINO_CTRL_B_EOD_INT            (1<<6)  /* End of desc table int */
+#define VINO_CTRL_B_INT                        (VINO_CTRL_B_EOF_INT | \
+                                        VINO_CTRL_B_FIFO_INT | \
+                                        VINO_CTRL_B_EOD_INT)
 #define VINO_CTRL_A_DMA_ENBL           (1<<7)
 #define VINO_CTRL_A_INTERLEAVE_ENBL    (1<<8)
 #define VINO_CTRL_A_SYNC_ENBL          (1<<9)
@@ -104,18 +111,18 @@ struct sgi_vino {
        u32 _pad_control;
        volatile u32 control;
 
-#define VINO_INTSTAT_A_FIELD_TRANS     (1<<0)  /* Field transferred int */
-#define VINO_INTSTAT_A_FIFO_OF         (1<<1)  /* FIFO overflow int */
-#define VINO_INTSTAT_A_END_DESC_TBL    (1<<2)  /* End of desc table int */
-#define VINO_INTSTAT_A                 (VINO_INTSTAT_A_FIELD_TRANS | \
-                                        VINO_INTSTAT_A_FIFO_OF | \
-                                        VINO_INTSTAT_A_END_DESC_TBL)
-#define VINO_INTSTAT_B_FIELD_TRANS     (1<<3)  /* Field transferred int */
-#define VINO_INTSTAT_B_FIFO_OF         (1<<4)  /* FIFO overflow int */
-#define VINO_INTSTAT_B_END_DESC_TBL    (1<<5)  /* End of desc table int */
-#define VINO_INTSTAT_B                 (VINO_INTSTAT_B_FIELD_TRANS | \
-                                        VINO_INTSTAT_B_FIFO_OF | \
-                                        VINO_INTSTAT_B_END_DESC_TBL)
+#define VINO_INTSTAT_A_EOF             (1<<0)  /* Field transferred int */
+#define VINO_INTSTAT_A_FIFO            (1<<1)  /* FIFO overflow int */
+#define VINO_INTSTAT_A_EOD             (1<<2)  /* End of desc table int */
+#define VINO_INTSTAT_A                 (VINO_INTSTAT_A_EOF | \
+                                        VINO_INTSTAT_A_FIFO | \
+                                        VINO_INTSTAT_A_EOD)
+#define VINO_INTSTAT_B_EOF             (1<<3)  /* Field transferred int */
+#define VINO_INTSTAT_B_FIFO            (1<<4)  /* FIFO overflow int */
+#define VINO_INTSTAT_B_EOD             (1<<5)  /* End of desc table int */
+#define VINO_INTSTAT_B                 (VINO_INTSTAT_B_EOF | \
+                                        VINO_INTSTAT_B_FIFO | \
+                                        VINO_INTSTAT_B_EOD)
        u32 _pad_intr_status;
        volatile u32 intr_status;
 
index dea6589d153364c0b2f6799f1380e3f99ca180a4..7fc692a8f5b080e8db0a7c133db23f5eced53297 100644 (file)
@@ -6,7 +6,7 @@ menu "Misc devices"
 
 config IBM_ASM
        tristate "Device driver for IBM RSA service processor"
-       depends on X86 && PCI && EXPERIMENTAL && BROKEN
+       depends on X86 && PCI && EXPERIMENTAL
        ---help---
          This option enables device driver support for in-band access to the
          IBM RSA (Condor) service processor in eServer xSeries systems.
index 914804512dba00e7bb3971927a6b7b77e0382824..7e98434cfa37783b1cfa45c1bd162e9a56f14bad 100644 (file)
 #include <linux/termios.h>
 #include <linux/tty.h>
 #include <linux/serial_core.h>
-#include <linux/serial.h>
 #include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
 #include "ibmasm.h"
 #include "lowlevel.h"
 
 
 void ibmasm_register_uart(struct service_processor *sp)
 {
-       struct serial_struct serial;
+       struct uart_port uport;
        void __iomem *iomem_base;
 
        iomem_base = sp->base_address + SCOUT_COM_B_BASE;
@@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp)
                return;
        }
 
-       memset(&serial, 0, sizeof(serial));
-       serial.irq              = sp->irq;
-       serial.baud_base        = 3686400 / 16;
-       serial.flags            = UPF_AUTOPROBE | UPF_SHARE_IRQ;
-       serial.io_type          = UPIO_MEM;
-       serial.iomem_base       = iomem_base;
+       memset(&uport, 0, sizeof(struct uart_port));
+       uport.irq       = sp->irq;
+       uport.uartclk   = 3686400;
+       uport.flags     = UPF_AUTOPROBE | UPF_SHARE_IRQ;
+       uport.iotype    = UPIO_MEM;
+       uport.membase   = iomem_base;
 
-       sp->serial_line = register_serial(&serial);
+       sp->serial_line = serial8250_register_port(&uport);
        if (sp->serial_line < 0) {
                dev_err(sp->dev, "Failed to register serial port\n");
                return;
@@ -68,5 +68,5 @@ void ibmasm_unregister_uart(struct service_processor *sp)
                return;
 
        disable_uart_interrupts(sp->base_address);
-       unregister_serial(sp->serial_line);
+       serial8250_unregister_port(sp->serial_line);
 }
index 0a8165974ba763abebeb0519434f849ea8876413..0a117c61cd1809e4f2ee6d924ac716810c8c848e 100644 (file)
@@ -2,6 +2,8 @@
  *  linux/drivers/mmc/mmc.c
  *
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,6 +18,8 @@
 #include <linux/delay.h>
 #include <linux/pagemap.h>
 #include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -172,7 +176,81 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
+/**
+ *     mmc_wait_for_app_cmd - start an application command and wait for
+                              completion
+ *     @host: MMC host to start command
+ *     @rca: RCA to send MMC_APP_CMD to
+ *     @cmd: MMC command to start
+ *     @retries: maximum number of retries
+ *
+ *     Sends a MMC_APP_CMD, checks the card response, sends the command
+ *     in the parameter and waits for it to complete. Return any error
+ *     that occurred while the command was executing.  Do not attempt to
+ *     parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+       struct mmc_command *cmd, int retries)
+{
+       struct mmc_request mrq;
+       struct mmc_command appcmd;
+
+       int i, err;
+
+       BUG_ON(host->card_busy == NULL);
+       BUG_ON(retries < 0);
+
+       err = MMC_ERR_INVALID;
+
+       /*
+        * We have to resend MMC_APP_CMD for each attempt so
+        * we cannot use the retries field in mmc_command.
+        */
+       for (i = 0;i <= retries;i++) {
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               appcmd.opcode = MMC_APP_CMD;
+               appcmd.arg = rca << 16;
+               appcmd.flags = MMC_RSP_R1;
+               appcmd.retries = 0;
+               memset(appcmd.resp, 0, sizeof(appcmd.resp));
+               appcmd.data = NULL;
+
+               mrq.cmd = &appcmd;
+               appcmd.data = NULL;
+
+               mmc_wait_for_req(host, &mrq);
+
+               if (appcmd.error) {
+                       err = appcmd.error;
+                       continue;
+               }
+
+               /* Check that card supported application commands */
+               if (!(appcmd.resp[0] & R1_APP_CMD))
+                       return MMC_ERR_FAILED;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               memset(cmd->resp, 0, sizeof(cmd->resp));
+               cmd->retries = 0;
+
+               mrq.cmd = cmd;
+               cmd->data = NULL;
 
+               mmc_wait_for_req(host, &mrq);
+
+               err = cmd->error;
+               if (cmd->error == MMC_ERR_NONE)
+                       break;
+       }
+
+       return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
 
 /**
  *     __mmc_claim_host - exclusively claim a host
@@ -206,16 +284,10 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
 
-       if (card != (void *)-1 && host->card_selected != card) {
-               struct mmc_command cmd;
-
-               host->card_selected = card;
-
-               cmd.opcode = MMC_SELECT_CARD;
-               cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_R1;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+       if (card != (void *)-1) {
+               err = mmc_select_card(host, card);
+               if (err != MMC_ERR_NONE)
+                       return err;
        }
 
        return err;
@@ -245,6 +317,63 @@ void mmc_release_host(struct mmc_host *host)
 
 EXPORT_SYMBOL(mmc_release_host);
 
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(host->card_busy == NULL);
+
+       if (host->card_selected == card)
+               return MMC_ERR_NONE;
+
+       host->card_selected = card;
+
+       cmd.opcode = MMC_SELECT_CARD;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R1;
+
+       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       /*
+        * Default bus width is 1 bit.
+        */
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+       /*
+        * We can only change the bus width of the selected
+        * card so therefore we have to put the handling
+        * here.
+        */
+       if (host->caps & MMC_CAP_4_BIT_DATA) {
+               /*
+                * The card is in 1 bit mode by default so
+                * we only need to change if it supports the
+                * wider version.
+                */
+               if (mmc_card_sd(card) &&
+                       (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+                       struct mmc_command cmd;
+                       cmd.opcode = SD_APP_SET_BUS_WIDTH;
+                       cmd.arg = SD_BUS_WIDTH_4;
+                       cmd.flags = MMC_RSP_R1;
+
+                       err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
+                               CMD_RETRIES);
+                       if (err != MMC_ERR_NONE)
+                               return err;
+
+                       host->ios.bus_width = MMC_BUS_WIDTH_4;
+               }
+       }
+
+       host->ops->set_ios(host, &host->ios);
+
+       return MMC_ERR_NONE;
+}
+
 /*
  * Ensure that no card is selected.
  */
@@ -322,48 +451,69 @@ static void mmc_decode_cid(struct mmc_card *card)
 
        memset(&card->cid, 0, sizeof(struct mmc_cid));
 
-       /*
-        * The selection of the format here is guesswork based upon
-        * information people have sent to date.
-        */
-       switch (card->csd.mmca_vsn) {
-       case 0: /* MMC v1.? */
-       case 1: /* MMC v1.4 */
-               card->cid.manfid        = UNSTUFF_BITS(resp, 104, 24);
-               card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
-               card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
-               card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
-               card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
-               card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
-               card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
-               card->cid.prod_name[6]  = UNSTUFF_BITS(resp, 48, 8);
-               card->cid.hwrev         = UNSTUFF_BITS(resp, 44, 4);
-               card->cid.fwrev         = UNSTUFF_BITS(resp, 40, 4);
-               card->cid.serial        = UNSTUFF_BITS(resp, 16, 24);
-               card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
-               card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
-               break;
-
-       case 2: /* MMC v2.x ? */
-       case 3: /* MMC v3.x ? */
-               card->cid.manfid        = UNSTUFF_BITS(resp, 120, 8);
-               card->cid.oemid         = UNSTUFF_BITS(resp, 104, 16);
-               card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
-               card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
-               card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
-               card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
-               card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
-               card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
-               card->cid.serial        = UNSTUFF_BITS(resp, 16, 32);
-               card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
-               card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
-               break;
-
-       default:
-               printk("%s: card has unknown MMCA version %d\n",
-                       mmc_hostname(card->host), card->csd.mmca_vsn);
-               mmc_card_set_bad(card);
-               break;
+       if (mmc_card_sd(card)) {
+               /*
+                * SD doesn't currently have a version field so we will
+                * have to assume we can parse this.
+                */
+               card->cid.manfid                = UNSTUFF_BITS(resp, 120, 8);
+               card->cid.oemid                 = UNSTUFF_BITS(resp, 104, 16);
+               card->cid.prod_name[0]          = UNSTUFF_BITS(resp, 96, 8);
+               card->cid.prod_name[1]          = UNSTUFF_BITS(resp, 88, 8);
+               card->cid.prod_name[2]          = UNSTUFF_BITS(resp, 80, 8);
+               card->cid.prod_name[3]          = UNSTUFF_BITS(resp, 72, 8);
+               card->cid.prod_name[4]          = UNSTUFF_BITS(resp, 64, 8);
+               card->cid.hwrev                 = UNSTUFF_BITS(resp, 60, 4);
+               card->cid.fwrev                 = UNSTUFF_BITS(resp, 56, 4);
+               card->cid.serial                = UNSTUFF_BITS(resp, 24, 32);
+               card->cid.year                  = UNSTUFF_BITS(resp, 12, 8);
+               card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
+
+               card->cid.year += 2000; /* SD cards year offset */
+       } else {
+               /*
+                * The selection of the format here is based upon published
+                * specs from sandisk and from what people have reported.
+                */
+               switch (card->csd.mmca_vsn) {
+               case 0: /* MMC v1.0 - v1.2 */
+               case 1: /* MMC v1.4 */
+                       card->cid.manfid        = UNSTUFF_BITS(resp, 104, 24);
+                       card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
+                       card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
+                       card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
+                       card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
+                       card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
+                       card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
+                       card->cid.prod_name[6]  = UNSTUFF_BITS(resp, 48, 8);
+                       card->cid.hwrev         = UNSTUFF_BITS(resp, 44, 4);
+                       card->cid.fwrev         = UNSTUFF_BITS(resp, 40, 4);
+                       card->cid.serial        = UNSTUFF_BITS(resp, 16, 24);
+                       card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
+                       card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
+                       break;
+
+               case 2: /* MMC v2.0 - v2.2 */
+               case 3: /* MMC v3.1 - v3.3 */
+                       card->cid.manfid        = UNSTUFF_BITS(resp, 120, 8);
+                       card->cid.oemid         = UNSTUFF_BITS(resp, 104, 16);
+                       card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
+                       card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
+                       card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
+                       card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
+                       card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
+                       card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
+                       card->cid.serial        = UNSTUFF_BITS(resp, 16, 32);
+                       card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
+                       card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
+                       break;
+
+               default:
+                       printk("%s: card has unknown MMCA version %d\n",
+                               mmc_hostname(card->host), card->csd.mmca_vsn);
+                       mmc_card_set_bad(card);
+                       break;
+               }
        }
 }
 
@@ -376,34 +526,86 @@ static void mmc_decode_csd(struct mmc_card *card)
        unsigned int e, m, csd_struct;
        u32 *resp = card->raw_csd;
 
-       /*
-        * We only understand CSD structure v1.1 and v2.
-        * v2 has extra information in bits 15, 11 and 10.
-        */
-       csd_struct = UNSTUFF_BITS(resp, 126, 2);
-       if (csd_struct != 1 && csd_struct != 2) {
-               printk("%s: unrecognised CSD structure version %d\n",
-                       mmc_hostname(card->host), csd_struct);
-               mmc_card_set_bad(card);
-               return;
+       if (mmc_card_sd(card)) {
+               csd_struct = UNSTUFF_BITS(resp, 126, 2);
+               if (csd_struct != 0) {
+                       printk("%s: unrecognised CSD structure version %d\n",
+                               mmc_hostname(card->host), csd_struct);
+                       mmc_card_set_bad(card);
+                       return;
+               }
+
+               m = UNSTUFF_BITS(resp, 115, 4);
+               e = UNSTUFF_BITS(resp, 112, 3);
+               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               e = UNSTUFF_BITS(resp, 47, 3);
+               m = UNSTUFF_BITS(resp, 62, 12);
+               csd->capacity     = (1 + m) << (e + 2);
+
+               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+       } else {
+               /*
+                * We only understand CSD structure v1.1 and v1.2.
+                * v1.2 has extra information in bits 15, 11 and 10.
+                */
+               csd_struct = UNSTUFF_BITS(resp, 126, 2);
+               if (csd_struct != 1 && csd_struct != 2) {
+                       printk("%s: unrecognised CSD structure version %d\n",
+                               mmc_hostname(card->host), csd_struct);
+                       mmc_card_set_bad(card);
+                       return;
+               }
+
+               csd->mmca_vsn    = UNSTUFF_BITS(resp, 122, 4);
+               m = UNSTUFF_BITS(resp, 115, 4);
+               e = UNSTUFF_BITS(resp, 112, 3);
+               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               e = UNSTUFF_BITS(resp, 47, 3);
+               m = UNSTUFF_BITS(resp, 62, 12);
+               csd->capacity     = (1 + m) << (e + 2);
+
+               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
        }
+}
 
-       csd->mmca_vsn    = UNSTUFF_BITS(resp, 122, 4);
-       m = UNSTUFF_BITS(resp, 115, 4);
-       e = UNSTUFF_BITS(resp, 112, 3);
-       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static void mmc_decode_scr(struct mmc_card *card)
+{
+       struct sd_scr *scr = &card->scr;
+       unsigned int scr_struct;
+       u32 resp[4];
+
+       BUG_ON(!mmc_card_sd(card));
 
-       m = UNSTUFF_BITS(resp, 99, 4);
-       e = UNSTUFF_BITS(resp, 96, 3);
-       csd->max_dtr      = tran_exp[e] * tran_mant[m];
-       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+       resp[3] = card->raw_scr[1];
+       resp[2] = card->raw_scr[0];
 
-       e = UNSTUFF_BITS(resp, 47, 3);
-       m = UNSTUFF_BITS(resp, 62, 12);
-       csd->capacity     = (1 + m) << (e + 2);
+       scr_struct = UNSTUFF_BITS(resp, 60, 4);
+       if (scr_struct != 0) {
+               printk("%s: unrecognised SCR structure version %d\n",
+                       mmc_hostname(card->host), scr_struct);
+               mmc_card_set_bad(card);
+               return;
+       }
 
-       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
 }
 
 /*
@@ -487,6 +689,7 @@ static void mmc_power_up(struct mmc_host *host)
        host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_UP;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
        host->ops->set_ios(host, &host->ios);
 
        mmc_delay(1);
@@ -505,6 +708,7 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_OFF;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
        host->ops->set_ios(host, &host->ios);
 }
 
@@ -536,6 +740,34 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
        return err;
 }
 
+static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+       struct mmc_command cmd;
+       int i, err = 0;
+
+       cmd.opcode = SD_APP_OP_COND;
+       cmd.arg = ocr;
+       cmd.flags = MMC_RSP_R3;
+
+       for (i = 100; i; i--) {
+               err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
+               if (err != MMC_ERR_NONE)
+                       break;
+
+               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+                       break;
+
+               err = MMC_ERR_TIMEOUT;
+
+               mmc_delay(10);
+       }
+
+       if (rocr)
+               *rocr = cmd.resp[0];
+
+       return err;
+}
+
 /*
  * Discover cards by requesting their CID.  If this command
  * times out, it is not an error; there are no further cards
@@ -579,13 +811,38 @@ static void mmc_discover_cards(struct mmc_host *host)
 
                card->state &= ~MMC_STATE_DEAD;
 
-               cmd.opcode = MMC_SET_RELATIVE_ADDR;
-               cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_R1;
+               if (host->mode == MMC_MODE_SD) {
+                       mmc_card_set_sd(card);
 
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE)
-                       mmc_card_set_dead(card);
+                       cmd.opcode = SD_SEND_RELATIVE_ADDR;
+                       cmd.arg = 0;
+                       cmd.flags = MMC_RSP_R1;
+
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE)
+                               mmc_card_set_dead(card);
+                       else {
+                               card->rca = cmd.resp[0] >> 16;
+
+                               if (!host->ops->get_ro) {
+                                       printk(KERN_WARNING "%s: host does not "
+                                               "support reading read-only "
+                                               "switch. assuming write-enable.\n",
+                                               mmc_hostname(host));
+                               } else {
+                                       if (host->ops->get_ro(host))
+                                               mmc_card_set_readonly(card);
+                               }
+                       }
+               } else {
+                       cmd.opcode = MMC_SET_RELATIVE_ADDR;
+                       cmd.arg = card->rca << 16;
+                       cmd.flags = MMC_RSP_R1;
+
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE)
+                               mmc_card_set_dead(card);
+               }
        }
 }
 
@@ -617,6 +874,79 @@ static void mmc_read_csds(struct mmc_host *host)
        }
 }
 
+static void mmc_read_scrs(struct mmc_host *host)
+{
+       int err;
+       struct mmc_card *card;
+
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+
+       struct scatterlist sg;
+
+       list_for_each_entry(card, &host->cards, node) {
+               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+                       continue;
+               if (!mmc_card_sd(card))
+                       continue;
+
+               err = mmc_select_card(host, card);
+               if (err != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = MMC_APP_CMD;
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1;
+
+               err = mmc_wait_for_cmd(host, &cmd, 0);
+               if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = SD_APP_SEND_SCR;
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1;
+
+               memset(&data, 0, sizeof(struct mmc_data));
+
+               data.timeout_ns = card->csd.tacc_ns * 10;
+               data.timeout_clks = card->csd.tacc_clks * 10;
+               data.blksz_bits = 3;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               mrq.cmd = &cmd;
+               mrq.data = &data;
+
+               sg_init_one(&sg, (u8*)card->raw_scr, 8);
+
+               err = mmc_wait_for_req(host, &mrq);
+               if (err != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               card->raw_scr[0] = ntohl(card->raw_scr[0]);
+               card->raw_scr[1] = ntohl(card->raw_scr[1]);
+
+               mmc_decode_scr(card);
+       }
+
+       mmc_deselect_cards(host);
+}
+
 static unsigned int mmc_calculate_clock(struct mmc_host *host)
 {
        struct mmc_card *card;
@@ -669,12 +999,24 @@ static void mmc_setup(struct mmc_host *host)
                int err;
                u32 ocr;
 
+               host->mode = MMC_MODE_SD;
+
                mmc_power_up(host);
                mmc_idle_cards(host);
 
-               err = mmc_send_op_cond(host, 0, &ocr);
-               if (err != MMC_ERR_NONE)
-                       return;
+               err = mmc_send_app_op_cond(host, 0, &ocr);
+
+               /*
+                * If we fail to detect any SD cards then try
+                * searching for MMC cards.
+                */
+               if (err != MMC_ERR_NONE) {
+                       host->mode = MMC_MODE_MMC;
+
+                       err = mmc_send_op_cond(host, 0, &ocr);
+                       if (err != MMC_ERR_NONE)
+                               return;
+               }
 
                host->ocr = mmc_select_voltage(host, ocr);
 
@@ -714,7 +1056,10 @@ static void mmc_setup(struct mmc_host *host)
         * all get the idea that they should be ready for CMD2.
         * (My SanDisk card seems to need this.)
         */
-       mmc_send_op_cond(host, host->ocr, NULL);
+       if (host->mode == MMC_MODE_SD)
+               mmc_send_app_op_cond(host, host->ocr, NULL);
+       else
+               mmc_send_op_cond(host, host->ocr, NULL);
 
        mmc_discover_cards(host);
 
@@ -725,6 +1070,9 @@ static void mmc_setup(struct mmc_host *host)
        host->ops->set_ios(host, &host->ios);
 
        mmc_read_csds(host);
+
+       if (host->mode == MMC_MODE_SD)
+               mmc_read_scrs(host);
 }
 
 
index d4eee99c2bf65ffe86798deb86cdd5ef0a2e81da..fa83f15fdf161d8eafda24958a8e9ccb6ebc2573 100644 (file)
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
                if (md->usage == 2)
                        check_disk_change(inode->i_bdev);
                ret = 0;
+
+               if ((filp->f_mode & FMODE_WRITE) &&
+                       mmc_card_readonly(md->queue.card))
+                       ret = -EROFS;
        }
 
        return ret;
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card)
        if (err)
                goto out;
 
-       printk(KERN_INFO "%s: %s %s %dKiB\n",
+       printk(KERN_INFO "%s: %s %s %dKiB %s\n",
                md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
-               (card->csd.capacity << card->csd.read_blkbits) / 1024);
+               (card->csd.capacity << card->csd.read_blkbits) / 1024,
+               mmc_card_readonly(card)?"(ro)":"");
 
        mmc_set_drvdata(card, md);
        add_disk(md->disk);
index ad8949810fc5cbeb79de505265ed57fb1aeba6b9..3f4a66ca9555e6c354c468266d22609adf56c628 100644 (file)
@@ -34,6 +34,7 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
        card->raw_cid[2], card->raw_cid[3]);
 MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
        card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
 MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
 MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
 MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
@@ -57,6 +58,8 @@ static struct device_attribute mmc_dev_attrs[] = {
        __ATTR_NULL
 };
 
+static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
+
 
 static void mmc_release_card(struct device *dev)
 {
@@ -207,10 +210,20 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
  */
 int mmc_register_card(struct mmc_card *card)
 {
+       int ret;
+
        snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
                 "%s:%04x", mmc_hostname(card->host), card->rca);
 
-       return device_add(&card->dev);
+       ret = device_add(&card->dev);
+       if (ret == 0) {
+               if (mmc_card_sd(card)) {
+                       ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
+                       if (ret)
+                               device_del(&card->dev);
+               }
+       }
+       return ret;
 }
 
 /*
@@ -219,8 +232,12 @@ int mmc_register_card(struct mmc_card *card)
  */
 void mmc_remove_card(struct mmc_card *card)
 {
-       if (mmc_card_present(card))
+       if (mmc_card_present(card)) {
+               if (mmc_card_sd(card))
+                       device_remove_file(&card->dev, &mmc_dev_attr_scr);
+
                device_del(&card->dev);
+       }
 
        put_device(&card->dev);
 }
index b78beb1b0159cc66748c15c19e05407c8c12d076..e99a53b09e321390d683362cf483923774d535a7 100644 (file)
@@ -362,6 +362,16 @@ static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        pxamci_start_cmd(host, mrq->cmd, cmdat);
 }
 
+static int pxamci_get_ro(struct mmc_host *mmc)
+{
+       struct pxamci_host *host = mmc_priv(mmc);
+
+       if (host->pdata && host->pdata->get_ro)
+               return host->pdata->get_ro(mmc->dev);
+       /* Host doesn't support read only detection so assume writeable */
+       return 0;
+}
+
 static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct pxamci_host *host = mmc_priv(mmc);
@@ -401,6 +411,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 static struct mmc_host_ops pxamci_ops = {
        .request        = pxamci_request,
+       .get_ro         = pxamci_get_ro,
        .set_ios        = pxamci_set_ios,
 };
 
index 08ae22aed9e8f7f38a1c61af4a0b87b92b563a0b..dec01d38c782fce5935ffb575ca90122934260e7 100644 (file)
@@ -720,11 +720,28 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
         * calculate CRC.
         *
         * Space for CRC must be included in the size.
+        * Two bytes are needed for each data line.
         */
-       blksize = (1 << data->blksz_bits) + 2;
+       if (host->bus_width == MMC_BUS_WIDTH_1)
+       {
+               blksize = (1 << data->blksz_bits) + 2;
+
+               wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       }
+       else if (host->bus_width == MMC_BUS_WIDTH_4)
+       {
+               blksize = (1 << data->blksz_bits) + 2 * 4;
        
-       wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
-       wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+               wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
+                       | WBSD_DATA_WIDTH);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       }
+       else
+       {
+               data->error = MMC_ERR_INVALID;
+               return;
+       }
 
        /*
         * Clear the FIFO. This is needed even for DMA
@@ -960,9 +977,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
        struct wbsd_host* host = mmc_priv(mmc);
        u8 clk, setup, pwr;
        
-       DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n",
-               ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
-               ios->vdd);
+       DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+            ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
+            ios->vdd, ios->bus_width);
 
        spin_lock_bh(&host->lock);
 
@@ -1010,6 +1027,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
        setup = wbsd_read_index(host, WBSD_IDX_SETUP);
        if (ios->chip_select == MMC_CS_HIGH)
        {
+               BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
                setup |= WBSD_DAT3_H;
                host->flags |= WBSD_FIGNORE_DETECT;
        }
@@ -1025,12 +1043,41 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
        }
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
        
+       /*
+        * Store bus width for later. Will be used when
+        * setting up the data transfer.
+        */
+       host->bus_width = ios->bus_width;
+
        spin_unlock_bh(&host->lock);
 }
 
+static int wbsd_get_ro(struct mmc_host* mmc)
+{
+       struct wbsd_host* host = mmc_priv(mmc);
+       u8 csr;
+
+       spin_lock_bh(&host->lock);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr |= WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       mdelay(1);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr &= ~WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       spin_unlock_bh(&host->lock);
+
+       return csr & WBSD_WRPT;
+}
+
 static struct mmc_host_ops wbsd_ops = {
        .request        = wbsd_request,
        .set_ios        = wbsd_set_ios,
+       .get_ro         = wbsd_get_ro,
 };
 
 /*****************************************************************************\
@@ -1355,6 +1402,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
        mmc->f_min = 375000;
        mmc->f_max = 24000000;
        mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_4_BIT_DATA;
        
        spin_lock_init(&host->lock);
        
index 8af43549f5d5b95b34bbe8b17b1fad18199be236..9005b5241b3cce44c132f13be7e9b5270cfc691c 100644 (file)
 #define WBSD_CLK_16M           0x02
 #define WBSD_CLK_24M           0x03
 
+#define WBSD_DATA_WIDTH                0x01
+
 #define WBSD_DAT3_H            0x08
 #define WBSD_FIFO_RESET                0x04
 #define WBSD_SOFT_RESET                0x02
@@ -164,6 +166,7 @@ struct wbsd_host
        int                     firsterr;       /* See fifo functions */
        
        u8                      clk;            /* Current clock speed */
+       unsigned char           bus_width;      /* Current bus width */
        
        int                     config;         /* Config port */
        u8                      unlock_code;    /* Code to unlock config */
index eee5115658c8c37bc3bf91136f48494e4221cb16..04e54318bc6a603f2c44b32e3b2f8b5b260a64dc 100644 (file)
@@ -526,6 +526,7 @@ static void nand_wait_ready(struct mtd_info *mtd)
        do {
                if (this->dev_ready(mtd))
                        return;
+               touch_softlockup_watchdog();
        } while (time_before(jiffies, timeo));  
 }
 
index 07746b95fd83754cb3875bdea4ebe9b545bbcf6c..455ba915ede738adc53f533f1b0a672cb07228d9 100644 (file)
@@ -973,6 +973,11 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
                        netif_device_detach(dev);
                        vortex_down(dev, 1);
                }
+               pci_save_state(pdev);
+               pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+               free_irq(dev->irq, dev);
+               pci_disable_device(pdev);
+               pci_set_power_state(pdev, pci_choose_state(pdev, state));
        }
        return 0;
 }
@@ -980,8 +985,19 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
 static int vortex_resume (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
+       struct vortex_private *vp = netdev_priv(dev);
 
-       if (dev && dev->priv) {
+       if (dev && vp) {
+               pci_set_power_state(pdev, PCI_D0);
+               pci_restore_state(pdev);
+               pci_enable_device(pdev);
+               pci_set_master(pdev);
+               if (request_irq(dev->irq, vp->full_bus_master_rx ?
+                               &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
+                       printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+                       pci_disable_device(pdev);
+                       return -EBUSY;
+               }
                if (netif_running(dev)) {
                        vortex_up(dev);
                        netif_device_attach(dev);
@@ -1873,6 +1889,7 @@ vortex_timer(unsigned long data)
                {
                        spin_lock_bh(&vp->lock);
                        mii_status = mdio_read(dev, vp->phys[0], 1);
+                       mii_status = mdio_read(dev, vp->phys[0], 1);
                        ok = 1;
                        if (vortex_debug > 2)
                                printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
index 4f9f69e22c1bd3c2f63c17f245d95f67e3565ca3..12ef52c193a39a2e1743bda3292110c4f76279d8 100644 (file)
@@ -597,7 +597,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
        struct ArcProto *proto;
        int txbuf;
        unsigned long flags;
-       int freeskb = 0;
+       int freeskb, retval;
 
        BUGMSG(D_DURING,
               "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
@@ -615,7 +615,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
        if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
                BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
                dev_kfree_skb(skb);
-               return 0;       /* don't try again */
+               return NETDEV_TX_OK;    /* don't try again */
        }
 
        /* We're busy transmitting a packet... */
@@ -623,8 +623,11 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
 
        spin_lock_irqsave(&lp->lock, flags);
        AINTMASK(0);
-
-       txbuf = get_arcbuf(dev);
+       if(lp->next_tx == -1)
+               txbuf = get_arcbuf(dev);
+       else {
+               txbuf = -1;
+       }
        if (txbuf != -1) {
                if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
                    !proto->ack_tx) {
@@ -638,6 +641,8 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
                        lp->outgoing.skb = skb;
                        lp->outgoing.pkt = pkt;
 
+                       freeskb = 0;
+
                        if (proto->continue_tx &&
                            proto->continue_tx(dev, txbuf)) {
                          BUGMSG(D_NORMAL,
@@ -645,10 +650,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
                                 "(proto='%c')\n", proto->suffix);
                        }
                }
-
+               retval = NETDEV_TX_OK;
+               dev->trans_start = jiffies;
                lp->next_tx = txbuf;
        } else {
-               freeskb = 1;
+               retval = NETDEV_TX_BUSY;
+               freeskb = 0;
        }
 
        BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
@@ -664,7 +671,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
        if (freeskb) {
                dev_kfree_skb(skb);
        }
-       return 0;               /* no need to try again */
+       return retval;          /* no need to try again */
 }
 
 
@@ -690,7 +697,6 @@ static int go_tx(struct net_device *dev)
        /* start sending */
        ACOMMAND(TXcmd | (lp->cur_tx << 3));
 
-       dev->trans_start = jiffies;
        lp->stats.tx_packets++;
        lp->lasttrans_dest = lp->lastload_dest;
        lp->lastload_dest = 0;
@@ -917,6 +923,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                        BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
                               status);
+                       /* MYRECON bit is at bit 7 of diagstatus */
+                       if(diagstatus & 0x80)
+                               BUGMSG(D_RECON,"Put out that recon myself\n");
 
                        /* is the RECON info empty or old? */
                        if (!lp->first_recon || !lp->last_recon ||
index d9df1d9a5739c471c82ec43186c8312c90f6b63f..bc9a3bf8d5605d2301ad300b9f848cfefa267465 100644 (file)
@@ -204,6 +204,10 @@ KERN_INFO "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>
 
 #define RUN_AT(x) (jiffies + (x))
 
+#ifndef ADDRLEN
+#define ADDRLEN 32
+#endif
+
 /* Condensed bus+endian portability operations. */
 #if ADDRLEN == 64
 #define cpu_to_leXX(addr)      cpu_to_le64(addr)
index 10125a1dba22bb33bd941b258779bf4f9b486ba2..dd89bda1f1315914349fe692029108b30dd6262a 100644 (file)
@@ -4,10 +4,10 @@
  * Description:   Driver for the SMC Infrared Communications Controller
  * Status:        Experimental.
  * Author:        Daniele Peri (peri@csai.unipa.it)
- * Created at:    
- * Modified at:   
- * Modified by:   
- * 
+ * Created at:
+ * Modified at:
+ * Modified by:
+ *
  *     Copyright (c) 2002      Daniele Peri
  *     All Rights Reserved.
  *     Copyright (c) 2002      Jean Tourrilhes
  *
  *     Copyright (c) 2001      Stefani Seibold
  *     Copyright (c) 1999-2001 Dag Brattli
- *     Copyright (c) 1998-1999 Thomas Davis, 
+ *     Copyright (c) 1998-1999 Thomas Davis,
  *
  *     and irport.c:
  *
  *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
  *
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- * 
+ *
  *     This program is distributed in the hope that it will be useful,
  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License 
- *     along with this program; if not, write to the Free Software 
- *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  *     MA 02111-1307 USA
  *
  ********************************************************************/
 #include "smsc-ircc2.h"
 #include "smsc-sio.h"
 
+
+MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
+MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
+MODULE_LICENSE("GPL");
+
+static int ircc_dma = 255;
+module_param(ircc_dma, int, 0);
+MODULE_PARM_DESC(ircc_dma, "DMA channel");
+
+static int ircc_irq = 255;
+module_param(ircc_irq, int, 0);
+MODULE_PARM_DESC(ircc_irq, "IRQ line");
+
+static int ircc_fir;
+module_param(ircc_fir, int, 0);
+MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
+
+static int ircc_sir;
+module_param(ircc_sir, int, 0);
+MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
+
+static int ircc_cfg;
+module_param(ircc_cfg, int, 0);
+MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
+
+static int ircc_transceiver;
+module_param(ircc_transceiver, int, 0);
+MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
+
 /* Types */
 
 struct smsc_transceiver {
        char *name;
-       void (*set_for_speed)(int fir_base, u32 speed); 
+       void (*set_for_speed)(int fir_base, u32 speed);
        int  (*probe)(int fir_base);
 };
-typedef struct smsc_transceiver smsc_transceiver_t;
-
-#if 0
-struct smc_chip {
-       char *name;
-       u16 flags;
-       u8 devid;
-       u8 rev;
-};
-typedef struct smc_chip smc_chip_t;
-#endif
 
 struct smsc_chip {
        char *name;
@@ -96,20 +114,18 @@ struct smsc_chip {
        u8 devid;
        u8 rev;
 };
-typedef struct smsc_chip smsc_chip_t;
 
 struct smsc_chip_address {
        unsigned int cfg_base;
        unsigned int type;
 };
-typedef struct smsc_chip_address smsc_chip_address_t;
 
 /* Private data for each instance */
 struct smsc_ircc_cb {
        struct net_device *netdev;     /* Yes! we are some kind of netdevice */
        struct net_device_stats stats;
        struct irlap_cb    *irlap; /* The link layer we are binded to */
-       
+
        chipio_t io;               /* IrDA controller information */
        iobuff_t tx_buff;          /* Transmit buffer */
        iobuff_t rx_buff;          /* Receive buffer */
@@ -119,7 +135,7 @@ struct smsc_ircc_cb {
        struct qos_info qos;       /* QoS capabilities for this device */
 
        spinlock_t lock;           /* For serializing operations */
-       
+
        __u32 new_speed;
        __u32 flags;               /* Interface flags */
 
@@ -127,18 +143,20 @@ struct smsc_ircc_cb {
        int tx_len;                /* Number of frames in tx_buff */
 
        int transceiver;
-       struct pm_dev *pmdev;
+       struct platform_device *pldev;
 };
 
 /* Constants */
 
-static const char *driver_name = "smsc-ircc2";
-#define        DIM(x)  (sizeof(x)/(sizeof(*(x))))
+#define SMSC_IRCC2_DRIVER_NAME                 "smsc-ircc2"
+
 #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED       9600
 #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER       1
-#define SMSC_IRCC2_C_NET_TIMEOUT                       0
+#define SMSC_IRCC2_C_NET_TIMEOUT               0
 #define SMSC_IRCC2_C_SIR_STOP                  0
 
+static const char *driver_name = SMSC_IRCC2_DRIVER_NAME;
+
 /* Prototypes */
 
 static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
@@ -147,15 +165,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base,
 static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
 static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
 static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
-static int  smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase); 
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase);
+static int  smsc_ircc_dma_receive(struct smsc_ircc_cb *self);
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self);
 static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self);
 static int  smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
 static int  smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs);
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase);
-static void smsc_ircc_change_speed(void *priv, u32 speed);
-static void smsc_ircc_set_sir_speed(void *priv, u32 speed);
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs);
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self);
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed);
+static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed);
 static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev);
 static void smsc_ircc_sir_start(struct smsc_ircc_cb *self);
@@ -171,7 +189,6 @@ static int  smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm
 static void smsc_ircc_timeout(struct net_device *dev);
 #endif
 static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
-static int  smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
 static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
 static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
@@ -179,9 +196,9 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self);
 
 /* Probing */
 static int __init smsc_ircc_look_for_chips(void);
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type);
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type);
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
+static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
 static int __init smsc_superio_fdc(unsigned short cfg_base);
 static int __init smsc_superio_lpc(unsigned short cfg_base);
 
@@ -196,21 +213,26 @@ static int  smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
 
 /* Power Management */
 
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self);
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self);
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
+static int smsc_ircc_resume(struct device *dev, u32 level);
 
+static struct device_driver smsc_ircc_driver = {
+       .name           = SMSC_IRCC2_DRIVER_NAME,
+       .bus            = &platform_bus_type,
+       .suspend        = smsc_ircc_suspend,
+       .resume         = smsc_ircc_resume,
+};
 
 /* Transceivers for SMSC-ircc */
 
-static smsc_transceiver_t smsc_transceivers[]=
+static struct smsc_transceiver smsc_transceivers[] =
 {
-       { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
-       { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
-       { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc},
-       { NULL, NULL}
+       { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800 },
+       { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select },
+       { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc },
+       { NULL, NULL }
 };
-#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1)
+#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (ARRAY_SIZE(smsc_transceivers) - 1)
 
 /*  SMC SuperIO chipsets definitions */
 
@@ -221,7 +243,7 @@ static smsc_transceiver_t smsc_transceivers[]=
 #define        FIR     4       /* SuperIO Chip has fast IRDA */
 #define        SERx4   8       /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
 
-static smsc_chip_t __initdata fdc_chips_flat[]=
+static struct smsc_chip __initdata fdc_chips_flat[] =
 {
        /* Base address 0x3f0 or 0x370 */
        { "37C44",      KEY55_1|NoIRDA,         0x00, 0x00 }, /* This chip cannot be detected */
@@ -235,7 +257,7 @@ static smsc_chip_t __initdata fdc_chips_flat[]=
        { NULL }
 };
 
-static smsc_chip_t __initdata fdc_chips_paged[]=
+static struct smsc_chip __initdata fdc_chips_paged[] =
 {
        /* Base address 0x3f0 or 0x370 */
        { "37B72X",     KEY55_1|SIR|SERx4,      0x4c, 0x00 },
@@ -254,7 +276,7 @@ static smsc_chip_t __initdata fdc_chips_paged[]=
        { NULL }
 };
 
-static smsc_chip_t __initdata lpc_chips_flat[]=
+static struct smsc_chip __initdata lpc_chips_flat[] =
 {
        /* Base address 0x2E or 0x4E */
        { "47N227",     KEY55_1|FIR|SERx4,      0x5a, 0x00 },
@@ -262,7 +284,7 @@ static smsc_chip_t __initdata lpc_chips_flat[]=
        { NULL }
 };
 
-static smsc_chip_t __initdata lpc_chips_paged[]=
+static struct smsc_chip __initdata lpc_chips_paged[] =
 {
        /* Base address 0x2E or 0x4E */
        { "47B27X",     KEY55_1|SIR|SERx4,      0x51, 0x00 },
@@ -281,33 +303,25 @@ static smsc_chip_t __initdata lpc_chips_paged[]=
 #define SMSCSIO_TYPE_FLAT      4
 #define SMSCSIO_TYPE_PAGED     8
 
-static smsc_chip_address_t __initdata possible_addresses[]=
+static struct smsc_chip_address __initdata possible_addresses[] =
 {
-       {0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
-       {0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
-       {0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
-       {0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
-       {0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
-       {0,0}
+       { 0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+       { 0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+       { 0xe0,  SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+       { 0x2e,  SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+       { 0x4e,  SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+       { 0, 0 }
 };
 
 /* Globals */
 
-static struct smsc_ircc_cb *dev_self[] = { NULL, NULL};
-
-static int ircc_irq=255;
-static int ircc_dma=255;
-static int ircc_fir=0;
-static int ircc_sir=0;
-static int ircc_cfg=0;
-static int ircc_transceiver=0;
-
-static unsigned short  dev_count=0;
+static struct smsc_ircc_cb *dev_self[] = { NULL, NULL };
+static unsigned short dev_count;
 
 static inline void register_bank(int iobase, int bank)
 {
-        outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
-               iobase+IRCC_MASTER);
+        outb(((inb(iobase + IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+               iobase + IRCC_MASTER);
 }
 
 
@@ -327,34 +341,44 @@ static inline void register_bank(int iobase, int bank)
  */
 static int __init smsc_ircc_init(void)
 {
-       int ret=-ENODEV;
+       int ret;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
-       dev_count=0;
-       if ((ircc_fir>0)&&(ircc_sir>0)) {
+       ret = driver_register(&smsc_ircc_driver);
+       if (ret) {
+               IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+               return ret;
+       }
+
+       dev_count = 0;
+
+       if (ircc_fir > 0 && ircc_sir > 0) {
                IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
                IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
 
-               if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0)
-                       return 0;
-
-               return -ENODEV;
-       }
+               if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
+                       ret = -ENODEV;
+       } else {
+               ret = -ENODEV;
+
+               /* try user provided configuration register base address */
+               if (ircc_cfg > 0) {
+                       IRDA_MESSAGE(" Overriding configuration address "
+                                    "0x%04x\n", ircc_cfg);
+                       if (!smsc_superio_fdc(ircc_cfg))
+                               ret = 0;
+                       if (!smsc_superio_lpc(ircc_cfg))
+                               ret = 0;
+               }
 
-       /* try user provided configuration register base address */
-       if (ircc_cfg>0) {
-               IRDA_MESSAGE(" Overriding configuration address 0x%04x\n",
-                            ircc_cfg);
-               if (!smsc_superio_fdc(ircc_cfg))
-                       ret = 0;
-               if (!smsc_superio_lpc(ircc_cfg))
+               if (smsc_ircc_look_for_chips() > 0)
                        ret = 0;
        }
-       
-       if(smsc_ircc_look_for_chips()>0) ret = 0;
-       
+
+       if (ret)
+               driver_unregister(&smsc_ircc_driver);
+
        return ret;
 }
 
@@ -369,15 +393,15 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
        struct smsc_ircc_cb *self;
        struct net_device *dev;
        int err;
-       
+
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
        err = smsc_ircc_present(fir_base, sir_base);
-       if(err) 
+       if (err)
                goto err_out;
-               
+
        err = -ENOMEM;
-       if (dev_count > DIM(dev_self)) {
+       if (dev_count >= ARRAY_SIZE(dev_self)) {
                IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__);
                goto err_out1;
        }
@@ -396,14 +420,14 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
        dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
 #if SMSC_IRCC2_C_NET_TIMEOUT
        dev->tx_timeout      = smsc_ircc_timeout;
-       dev->watchdog_timeo  = HZ*2;  /* Allow enough time for speed change */
+       dev->watchdog_timeo  = HZ * 2;  /* Allow enough time for speed change */
 #endif
        dev->open            = smsc_ircc_net_open;
        dev->stop            = smsc_ircc_net_close;
        dev->do_ioctl        = smsc_ircc_net_ioctl;
        dev->get_stats       = smsc_ircc_net_get_stats;
-       
-       self = dev->priv;
+
+       self = netdev_priv(dev);
        self->netdev = dev;
 
        /* Make ifconfig display some details */
@@ -411,10 +435,10 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
        dev->irq = self->io.irq = irq;
 
        /* Need to store self somewhere */
-       dev_self[dev_count++] = self;
+       dev_self[dev_count] = self;
        spin_lock_init(&self->lock);
 
-       self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; 
+       self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
        self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
 
        self->rx_buff.head =
@@ -442,33 +466,40 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
        self->rx_buff.state = OUTSIDE_FRAME;
        self->tx_buff.data = self->tx_buff.head;
        self->rx_buff.data = self->rx_buff.head;
-          
-       smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
 
+       smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
        smsc_ircc_setup_qos(self);
-
        smsc_ircc_init_chip(self);
-       
-       if(ircc_transceiver > 0  && 
-          ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
+
+       if (ircc_transceiver > 0  &&
+           ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
                self->transceiver = ircc_transceiver;
        else
                smsc_ircc_probe_transceiver(self);
 
        err = register_netdev(self->netdev);
-       if(err) {
+       if (err) {
                IRDA_ERROR("%s, Network device registration failed!\n",
                           driver_name);
                goto err_out4;
        }
 
-       self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
-       if (self->pmdev)
-               self->pmdev->data = self;
+       self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME,
+                                                     dev_count, NULL, 0);
+       if (IS_ERR(self->pldev)) {
+               err = PTR_ERR(self->pldev);
+               goto err_out5;
+       }
+       dev_set_drvdata(&self->pldev->dev, self);
 
        IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
+       dev_count++;
 
        return 0;
+
+ err_out5:
+       unregister_netdev(self->netdev);
+
  err_out4:
        dma_free_coherent(NULL, self->tx_buff.truesize,
                          self->tx_buff.head, self->tx_buff_dma);
@@ -477,7 +508,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
                          self->rx_buff.head, self->rx_buff_dma);
  err_out2:
        free_netdev(self->netdev);
-       dev_self[--dev_count] = NULL;
+       dev_self[dev_count] = NULL;
  err_out1:
        release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
        release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
@@ -511,16 +542,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
 
        register_bank(fir_base, 3);
 
-       high    = inb(fir_base+IRCC_ID_HIGH);
-       low     = inb(fir_base+IRCC_ID_LOW);
-       chip    = inb(fir_base+IRCC_CHIP_ID);
-       version = inb(fir_base+IRCC_VERSION);
-       config  = inb(fir_base+IRCC_INTERFACE);
+       high    = inb(fir_base + IRCC_ID_HIGH);
+       low     = inb(fir_base + IRCC_ID_LOW);
+       chip    = inb(fir_base + IRCC_CHIP_ID);
+       version = inb(fir_base + IRCC_VERSION);
+       config  = inb(fir_base + IRCC_INTERFACE);
        dma     = config & IRCC_INTERFACE_DMA_MASK;
        irq     = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
 
-       if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
-               IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
+       if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
+               IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
                             __FUNCTION__, fir_base);
                goto out3;
        }
@@ -529,6 +560,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
                     chip & 0x0f, version, fir_base, sir_base, dma, irq);
 
        return 0;
+
  out3:
        release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
  out2:
@@ -543,16 +575,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
  *    Setup I/O
  *
  */
-static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, 
-                              unsigned int fir_base, unsigned int sir_base, 
+static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
+                              unsigned int fir_base, unsigned int sir_base,
                               u8 dma, u8 irq)
 {
        unsigned char config, chip_dma, chip_irq;
 
        register_bank(fir_base, 3);
-       config  = inb(fir_base+IRCC_INTERFACE);
-       chip_dma     = config & IRCC_INTERFACE_DMA_MASK;
-       chip_irq     = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
+       config = inb(fir_base + IRCC_INTERFACE);
+       chip_dma = config & IRCC_INTERFACE_DMA_MASK;
+       chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
 
        self->io.fir_base  = fir_base;
        self->io.sir_base  = sir_base;
@@ -566,17 +598,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
                        IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
                                     driver_name, chip_irq, irq);
                self->io.irq = irq;
-       }
-       else
+       } else
                self->io.irq = chip_irq;
-       
+
        if (dma < 255) {
                if (dma != chip_dma)
                        IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
                                     driver_name, chip_dma, dma);
                self->io.dma = dma;
-       }
-       else
+       } else
                self->io.dma = chip_dma;
 
 }
@@ -591,7 +621,7 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
 {
        /* Initialize QoS for this device */
        irda_init_max_qos_capabilies(&self->qos);
-       
+
        self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
                IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 
@@ -608,43 +638,43 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
  */
 static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
 {
-       int iobase, ir_mode, ctrl, fast; 
-       
-       IRDA_ASSERT( self != NULL, return; );
-       iobase = self->io.fir_base;
+       int iobase, ir_mode, ctrl, fast;
+
+       IRDA_ASSERT(self != NULL, return;);
 
+       iobase = self->io.fir_base;
        ir_mode = IRCC_CFGA_IRDA_SIR_A;
        ctrl = 0;
        fast = 0;
 
        register_bank(iobase, 0);
-       outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-       outb(0x00, iobase+IRCC_MASTER);
+       outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+       outb(0x00, iobase + IRCC_MASTER);
 
        register_bank(iobase, 1);
-       outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode), 
-            iobase+IRCC_SCE_CFGA);
+       outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode),
+            iobase + IRCC_SCE_CFGA);
 
 #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */
-       outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), 
-            iobase+IRCC_SCE_CFGB);
-#else  
-       outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
-            iobase+IRCC_SCE_CFGB);
-#endif 
-       (void) inb(iobase+IRCC_FIFO_THRESHOLD);
-       outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase+IRCC_FIFO_THRESHOLD);
-       
+       outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+            iobase + IRCC_SCE_CFGB);
+#else
+       outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+            iobase + IRCC_SCE_CFGB);
+#endif
+       (void) inb(iobase + IRCC_FIFO_THRESHOLD);
+       outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD);
+
        register_bank(iobase, 4);
-       outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
-       
+       outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL);
+
        register_bank(iobase, 0);
-       outb(fast, iobase+IRCC_LCR_A);
+       outb(fast, iobase + IRCC_LCR_A);
 
        smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
-       
+
        /* Power on device */
-       outb(0x00, iobase+IRCC_MASTER);
+       outb(0x00, iobase + IRCC_MASTER);
 }
 
 /*
@@ -662,12 +692,12 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
 
        IRDA_ASSERT(dev != NULL, return -1;);
 
-       self = dev->priv;
+       self = netdev_priv(dev);
 
        IRDA_ASSERT(self != NULL, return -1;);
 
        IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
-       
+
        switch (cmd) {
        case SIOCSBANDWIDTH: /* Set bandwidth */
                if (!capable(CAP_NET_ADMIN))
@@ -703,14 +733,14 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
        default:
                ret = -EOPNOTSUPP;
        }
-       
+
        return ret;
 }
 
 static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
 {
-       struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) dev->priv;
-       
+       struct smsc_ircc_cb *self = netdev_priv(dev);
+
        return &self->stats;
 }
 
@@ -724,11 +754,9 @@ static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
 
 static void smsc_ircc_timeout(struct net_device *dev)
 {
-       struct smsc_ircc_cb *self;
+       struct smsc_ircc_cb *self = netdev_priv(dev);
        unsigned long flags;
 
-       self = (struct smsc_ircc_cb *) dev->priv;
-       
        IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n",
                     dev->name, self->io.speed);
        spin_lock_irqsave(&self->lock, flags);
@@ -751,26 +779,23 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
 {
        struct smsc_ircc_cb *self;
        unsigned long flags;
-       int iobase;
        s32 speed;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
        IRDA_ASSERT(dev != NULL, return 0;);
-       
-       self = (struct smsc_ircc_cb *) dev->priv;
-       IRDA_ASSERT(self != NULL, return 0;);
 
-       iobase = self->io.sir_base;
+       self = netdev_priv(dev);
+       IRDA_ASSERT(self != NULL, return 0;);
 
        netif_stop_queue(dev);
-       
+
        /* Make sure test of self->io.speed & speed change are atomic */
        spin_lock_irqsave(&self->lock, flags);
 
        /* Check if we need to change the speed */
        speed = irda_get_next_speed(skb);
-       if ((speed != self->io.speed) && (speed != -1)) {
+       if (speed != self->io.speed && speed != -1) {
                /* Check for empty frame */
                if (!skb->len) {
                        /*
@@ -787,27 +812,26 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
                        spin_unlock_irqrestore(&self->lock, flags);
                        dev_kfree_skb(skb);
                        return 0;
-               } else {
-                       self->new_speed = speed;
                }
+               self->new_speed = speed;
        }
 
        /* Init tx buffer */
        self->tx_buff.data = self->tx_buff.head;
 
        /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
-       self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+       self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
                                           self->tx_buff.truesize);
-       
+
        self->stats.tx_bytes += self->tx_buff.len;
 
        /* Turn on transmit finished interrupt. Will fire immediately!  */
-       outb(UART_IER_THRI, iobase+UART_IER); 
+       outb(UART_IER_THRI, self->io.sir_base + UART_IER);
 
        spin_unlock_irqrestore(&self->lock, flags);
 
        dev_kfree_skb(skb);
-       
+
        return 0;
 }
 
@@ -826,9 +850,9 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
 
        self->io.speed = speed;
 
-       switch(speed) {
+       switch (speed) {
        default:
-       case 576000:            
+       case 576000:
                ir_mode = IRCC_CFGA_IRDA_HDLC;
                ctrl = IRCC_CRC;
                fast = 0;
@@ -853,14 +877,14 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
        Now in tranceiver!
        /* This causes an interrupt */
        register_bank(fir_base, 0);
-       outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast, fir_base+IRCC_LCR_A);
+       outb((inb(fir_base + IRCC_LCR_A) &  0xbf) | fast, fir_base + IRCC_LCR_A);
        #endif
-       
+
        register_bank(fir_base, 1);
-       outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base+IRCC_SCE_CFGA);
-       
+       outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA);
+
        register_bank(fir_base, 4);
-       outb((inb(fir_base+IRCC_CONTROL) & 0x30) | ctrl, fir_base+IRCC_CONTROL);
+       outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL);
 }
 
 /*
@@ -885,31 +909,31 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self)
        /* Reset everything */
 
        /* Install FIR transmit handler */
-       dev->hard_start_xmit = smsc_ircc_hard_xmit_fir; 
+       dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;
 
        /* Clear FIFO */
-       outb(inb(fir_base+IRCC_LCR_A)|IRCC_LCR_A_FIFO_RESET, fir_base+IRCC_LCR_A);
+       outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A);
 
        /* Enable interrupt */
-       /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/
+       /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/
 
        register_bank(fir_base, 1);
 
-       /* Select the TX/RX interface */        
+       /* Select the TX/RX interface */
 #ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */
-       outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), 
-            fir_base+IRCC_SCE_CFGB);
-#else  
-       outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
-            fir_base+IRCC_SCE_CFGB);
-#endif 
-       (void) inb(fir_base+IRCC_FIFO_THRESHOLD);
+       outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+            fir_base + IRCC_SCE_CFGB);
+#else
+       outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+            fir_base + IRCC_SCE_CFGB);
+#endif
+       (void) inb(fir_base + IRCC_FIFO_THRESHOLD);
 
        /* Enable SCE interrupts */
-       outb(0, fir_base+IRCC_MASTER);
+       outb(0, fir_base + IRCC_MASTER);
        register_bank(fir_base, 0);
-       outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);
-       outb(IRCC_MASTER_INT_EN, fir_base+IRCC_MASTER);
+       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER);
+       outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER);
 }
 
 /*
@@ -923,13 +947,13 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
        int fir_base;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-       
+
        IRDA_ASSERT(self != NULL, return;);
 
        fir_base = self->io.fir_base;
        register_bank(fir_base, 0);
-       /*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/      
-       outb(inb(fir_base+IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base+IRCC_LCR_B);
+       /*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/
+       outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B);
 }
 
 
@@ -941,18 +965,15 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
  * This function *must* be called with spinlock held, because it may
  * be called from the irq handler. - Jean II
  */
-static void smsc_ircc_change_speed(void *priv, u32 speed)
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed)
 {
-       struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
        struct net_device *dev;
-       int iobase;
        int last_speed_was_sir;
-       
+
        IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);
 
        IRDA_ASSERT(self != NULL, return;);
        dev = self->netdev;
-       iobase = self->io.fir_base;
 
        last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED;
 
@@ -961,30 +982,30 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
        speed= 1152000;
        self->io.speed = speed;
        last_speed_was_sir = 0;
-       smsc_ircc_fir_start(self);      
+       smsc_ircc_fir_start(self);
        #endif
-       
-       if(self->io.speed == 0)
+
+       if (self->io.speed == 0)
                smsc_ircc_sir_start(self);
 
        #if 0
-       if(!last_speed_was_sir) speed = self->io.speed;
+       if (!last_speed_was_sir) speed = self->io.speed;
        #endif
 
-       if(self->io.speed != speed) smsc_ircc_set_transceiver_for_speed(self, speed);
+       if (self->io.speed != speed)
+               smsc_ircc_set_transceiver_for_speed(self, speed);
 
        self->io.speed = speed;
-       
-       if(speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
-               if(!last_speed_was_sir) {
+
+       if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+               if (!last_speed_was_sir) {
                        smsc_ircc_fir_stop(self);
                        smsc_ircc_sir_start(self);
                }
-               smsc_ircc_set_sir_speed(self, speed); 
-       }
-       else {
-               if(last_speed_was_sir) {
-                       #if SMSC_IRCC2_C_SIR_STOP               
+               smsc_ircc_set_sir_speed(self, speed);
+       } else {
+               if (last_speed_was_sir) {
+                       #if SMSC_IRCC2_C_SIR_STOP
                        smsc_ircc_sir_stop(self);
                        #endif
                        smsc_ircc_fir_start(self);
@@ -994,13 +1015,13 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
                #if 0
                self->tx_buff.len = 10;
                self->tx_buff.data = self->tx_buff.head;
-               
-               smsc_ircc_dma_xmit(self, iobase, 4000);
+
+               smsc_ircc_dma_xmit(self, 4000);
                #endif
                /* Be ready for incoming frames */
-               smsc_ircc_dma_receive(self, iobase);
+               smsc_ircc_dma_receive(self);
        }
-       
+
        netif_wake_queue(dev);
 }
 
@@ -1010,10 +1031,9 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
  *    Set speed of IrDA port to specified baudrate
  *
  */
-void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
+void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed)
 {
-       struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
-       int iobase; 
+       int iobase;
        int fcr;    /* FIFO control reg */
        int lcr;    /* Line control reg */
        int divisor;
@@ -1022,38 +1042,36 @@ void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
 
        IRDA_ASSERT(self != NULL, return;);
        iobase = self->io.sir_base;
-       
+
        /* Update accounting for new speed */
        self->io.speed = speed;
 
        /* Turn off interrupts */
-       outb(0, iobase+UART_IER); 
+       outb(0, iobase + UART_IER);
+
+       divisor = SMSC_IRCC2_MAX_SIR_SPEED / speed;
 
-       divisor = SMSC_IRCC2_MAX_SIR_SPEED/speed;
-       
        fcr = UART_FCR_ENABLE_FIFO;
 
-       /* 
+       /*
         * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
         * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
-        * about this timeout since it will always be fast enough. 
+        * about this timeout since it will always be fast enough.
         */
-       if (self->io.speed < 38400)
-               fcr |= UART_FCR_TRIGGER_1;
-       else 
-               fcr |= UART_FCR_TRIGGER_14;
-        
+       fcr |= self->io.speed < 38400 ?
+               UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
+
        /* IrDA ports use 8N1 */
        lcr = UART_LCR_WLEN8;
-       
-       outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
-       outb(divisor & 0xff,      iobase+UART_DLL); /* Set speed */
-       outb(divisor >> 8,        iobase+UART_DLM);
-       outb(lcr,                 iobase+UART_LCR); /* Set 8N1  */
-       outb(fcr,                 iobase+UART_FCR); /* Enable FIFO's */
+
+       outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */
+       outb(divisor & 0xff,      iobase + UART_DLL); /* Set speed */
+       outb(divisor >> 8,        iobase + UART_DLM);
+       outb(lcr,                 iobase + UART_LCR); /* Set 8N1 */
+       outb(fcr,                 iobase + UART_FCR); /* Enable FIFO's */
 
        /* Turn on interrups */
-       outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+       outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 
        IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed);
 }
@@ -1070,15 +1088,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
        struct smsc_ircc_cb *self;
        unsigned long flags;
        s32 speed;
-       int iobase;
        int mtt;
 
        IRDA_ASSERT(dev != NULL, return 0;);
-       self = (struct smsc_ircc_cb *) dev->priv;
+       self = netdev_priv(dev);
        IRDA_ASSERT(self != NULL, return 0;);
 
-       iobase = self->io.fir_base;
-
        netif_stop_queue(dev);
 
        /* Make sure test of self->io.speed & speed change are atomic */
@@ -1086,30 +1101,31 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
 
        /* Check if we need to change the speed after this frame */
        speed = irda_get_next_speed(skb);
-       if ((speed != self->io.speed) && (speed != -1)) {
+       if (speed != self->io.speed && speed != -1) {
                /* Check for empty frame */
                if (!skb->len) {
                        /* Note : you should make sure that speed changes
                         * are not going to corrupt any outgoing frame.
                         * Look at nsc-ircc for the gory details - Jean II */
-                       smsc_ircc_change_speed(self, speed); 
+                       smsc_ircc_change_speed(self, speed);
                        spin_unlock_irqrestore(&self->lock, flags);
                        dev_kfree_skb(skb);
                        return 0;
-               } else
-                       self->new_speed = speed;
+               }
+
+               self->new_speed = speed;
        }
-       
+
        memcpy(self->tx_buff.head, skb->data, skb->len);
 
        self->tx_buff.len = skb->len;
        self->tx_buff.data = self->tx_buff.head;
-       
-       mtt = irda_get_mtt(skb);        
+
+       mtt = irda_get_mtt(skb);
        if (mtt) {
                int bofs;
 
-               /* 
+               /*
                 * Compute how many BOFs (STA or PA's) we need to waste the
                 * min turn time given the speed of the link.
                 */
@@ -1117,11 +1133,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
                if (bofs > 4095)
                        bofs = 4095;
 
-               smsc_ircc_dma_xmit(self, iobase, bofs);
+               smsc_ircc_dma_xmit(self, bofs);
        } else {
                /* Transmit frame */
-               smsc_ircc_dma_xmit(self, iobase, 0);
+               smsc_ircc_dma_xmit(self, 0);
        }
+
        spin_unlock_irqrestore(&self->lock, flags);
        dev_kfree_skb(skb);
 
@@ -1129,43 +1146,44 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
 }
 
 /*
- * Function smsc_ircc_dma_xmit (self, iobase)
+ * Function smsc_ircc_dma_xmit (self, bofs)
  *
  *    Transmit data using DMA
  *
  */
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs)
 {
+       int iobase = self->io.fir_base;
        u8 ctrl;
 
        IRDA_DEBUG(3, "%s\n", __FUNCTION__);
 #if 1
        /* Disable Rx */
        register_bank(iobase, 0);
-       outb(0x00, iobase+IRCC_LCR_B);
+       outb(0x00, iobase + IRCC_LCR_B);
 #endif
        register_bank(iobase, 1);
-       outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
-            iobase+IRCC_SCE_CFGB);
+       outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+            iobase + IRCC_SCE_CFGB);
 
        self->io.direction = IO_XMIT;
 
        /* Set BOF additional count for generating the min turn time */
        register_bank(iobase, 4);
-       outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
-       ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
-       outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+       outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO);
+       ctrl = inb(iobase + IRCC_CONTROL) & 0xf0;
+       outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI);
 
        /* Set max Tx frame size */
-       outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
-       outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
+       outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI);
+       outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO);
 
        /*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/
-       
+
        /* Enable burst mode chip Tx DMA */
        register_bank(iobase, 1);
-       outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
-            IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+       outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+            IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
 
        /* Setup DMA controller (must be done after enabling chip DMA) */
        irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
@@ -1174,50 +1192,52 @@ static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
        /* Enable interrupt */
 
        register_bank(iobase, 0);
-       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
-       outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-       
+       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+       outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
+
        /* Enable transmit */
-       outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
+       outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase + IRCC_LCR_B);
 }
 
 /*
  * Function smsc_ircc_dma_xmit_complete (self)
  *
- *    The transfer of a frame in finished. This function will only be called 
+ *    The transfer of a frame in finished. This function will only be called
  *    by the interrupt handler
  *
  */
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self)
 {
+       int iobase = self->io.fir_base;
+
        IRDA_DEBUG(3, "%s\n", __FUNCTION__);
 #if 0
        /* Disable Tx */
        register_bank(iobase, 0);
-       outb(0x00, iobase+IRCC_LCR_B);
+       outb(0x00, iobase + IRCC_LCR_B);
 #endif
-       register_bank(self->io.fir_base, 1);
-       outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
-            self->io.fir_base+IRCC_SCE_CFGB);
+       register_bank(iobase, 1);
+       outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+            iobase + IRCC_SCE_CFGB);
 
        /* Check for underrun! */
        register_bank(iobase, 0);
-       if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
+       if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) {
                self->stats.tx_errors++;
                self->stats.tx_fifo_errors++;
 
                /* Reset error condition */
                register_bank(iobase, 0);
-               outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
-               outb(0x00, iobase+IRCC_MASTER);
+               outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER);
+               outb(0x00, iobase + IRCC_MASTER);
        } else {
                self->stats.tx_packets++;
-               self->stats.tx_bytes +=  self->tx_buff.len;
+               self->stats.tx_bytes += self->tx_buff.len;
        }
 
        /* Check if it's time to change the speed */
        if (self->new_speed) {
-               smsc_ircc_change_speed(self, self->new_speed);          
+               smsc_ircc_change_speed(self, self->new_speed);
                self->new_speed = 0;
        }
 
@@ -1231,31 +1251,32 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
  *    if it starts to receive a frame.
  *
  */
-static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase) 
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self)
 {
+       int iobase = self->io.fir_base;
 #if 0
        /* Turn off chip DMA */
        register_bank(iobase, 1);
-       outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
-            iobase+IRCC_SCE_CFGB);
+       outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+            iobase + IRCC_SCE_CFGB);
 #endif
-       
+
        /* Disable Tx */
        register_bank(iobase, 0);
-       outb(0x00, iobase+IRCC_LCR_B);
+       outb(0x00, iobase + IRCC_LCR_B);
 
        /* Turn off chip DMA */
        register_bank(iobase, 1);
-       outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
-            iobase+IRCC_SCE_CFGB);
+       outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+            iobase + IRCC_SCE_CFGB);
 
        self->io.direction = IO_RECV;
        self->rx_buff.data = self->rx_buff.head;
 
        /* Set max Rx frame size */
        register_bank(iobase, 4);
-       outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
-       outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+       outb((2050 >> 8) & 0x0f, iobase + IRCC_RX_SIZE_HI);
+       outb(2050 & 0xff, iobase + IRCC_RX_SIZE_LO);
 
        /* Setup DMA controller */
        irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
@@ -1263,83 +1284,83 @@ static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase)
 
        /* Enable burst mode chip Rx DMA */
        register_bank(iobase, 1);
-       outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | 
-            IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+       outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+            IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
 
        /* Enable interrupt */
        register_bank(iobase, 0);
-       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
-       outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
+       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+       outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
 
        /* Enable receiver */
        register_bank(iobase, 0);
-       outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, 
-            iobase+IRCC_LCR_B);
-       
+       outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
+            iobase + IRCC_LCR_B);
+
        return 0;
 }
 
 /*
- * Function smsc_ircc_dma_receive_complete(self, iobase)
+ * Function smsc_ircc_dma_receive_complete(self)
  *
  *    Finished with receiving frames
  *
  */
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
 {
        struct sk_buff *skb;
        int len, msgcnt, lsr;
-       
+       int iobase = self->io.fir_base;
+
        register_bank(iobase, 0);
-       
+
        IRDA_DEBUG(3, "%s\n", __FUNCTION__);
 #if 0
        /* Disable Rx */
        register_bank(iobase, 0);
-       outb(0x00, iobase+IRCC_LCR_B);
+       outb(0x00, iobase + IRCC_LCR_B);
 #endif
        register_bank(iobase, 0);
-       outb(inb(iobase+IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase+IRCC_LSAR);
-       lsr= inb(iobase+IRCC_LSR);
-       msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
+       outb(inb(iobase + IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase + IRCC_LSAR);
+       lsr= inb(iobase + IRCC_LSR);
+       msgcnt = inb(iobase + IRCC_LCR_B) & 0x08;
 
        IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__,
                   get_dma_residue(self->io.dma));
 
        len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
 
-       /* Look for errors 
-        */     
-
-       if(lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
+       /* Look for errors */
+       if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
                self->stats.rx_errors++;
-               if(lsr & IRCC_LSR_FRAME_ERROR) self->stats.rx_frame_errors++;
-               if(lsr & IRCC_LSR_CRC_ERROR) self->stats.rx_crc_errors++;
-               if(lsr & IRCC_LSR_SIZE_ERROR) self->stats.rx_length_errors++;
-               if(lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) self->stats.rx_length_errors++;
+               if (lsr & IRCC_LSR_FRAME_ERROR)
+                       self->stats.rx_frame_errors++;
+               if (lsr & IRCC_LSR_CRC_ERROR)
+                       self->stats.rx_crc_errors++;
+               if (lsr & IRCC_LSR_SIZE_ERROR)
+                       self->stats.rx_length_errors++;
+               if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN))
+                       self->stats.rx_length_errors++;
                return;
        }
+
        /* Remove CRC */
-       if (self->io.speed < 4000000)
-               len -= 2;
-       else
-               len -= 4;
+       len -= self->io.speed < 4000000 ? 2 : 4;
 
-       if ((len < 2) || (len > 2050)) {
+       if (len < 2 || len > 2050) {
                IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
                return;
        }
        IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len);
 
-       skb = dev_alloc_skb(len+1);
-       if (!skb)  {
+       skb = dev_alloc_skb(len + 1);
+       if (!skb) {
                IRDA_WARNING("%s(), memory squeeze, dropping frame.\n",
                             __FUNCTION__);
                return;
-       }                       
+       }
        /* Make sure IP header gets aligned */
-       skb_reserve(skb, 1); 
+       skb_reserve(skb, 1);
 
        memcpy(skb_put(skb, len), self->rx_buff.data, len);
        self->stats.rx_packets++;
@@ -1357,7 +1378,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase
  *    Receive one frame from the infrared port
  *
  */
-static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) 
+static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
 {
        int boguscount = 0;
        int iobase;
@@ -1366,20 +1387,20 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
 
        iobase = self->io.sir_base;
 
-       /*  
-        * Receive all characters in Rx FIFO, unwrap and unstuff them. 
-         * async_unwrap_char will deliver all found frames  
+       /*
+        * Receive all characters in Rx FIFO, unwrap and unstuff them.
+         * async_unwrap_char will deliver all found frames
         */
        do {
-               async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
-                                 inb(iobase+UART_RX));
+               async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+                                 inb(iobase + UART_RX));
 
                /* Make sure we don't stay here to long */
                if (boguscount++ > 32) {
                        IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__);
                        break;
                }
-       } while (inb(iobase+UART_LSR) & UART_LSR_DR);   
+       } while (inb(iobase + UART_LSR) & UART_LSR_DR);
 }
 
 
@@ -1397,18 +1418,19 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
        irqreturn_t ret = IRQ_NONE;
 
        if (dev == NULL) {
-               printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
+               printk(KERN_WARNING "%s: irq %d for unknown device.\n",
                       driver_name, irq);
                goto irq_ret;
        }
-       self = (struct smsc_ircc_cb *) dev->priv;
+
+       self = netdev_priv(dev);
        IRDA_ASSERT(self != NULL, return IRQ_NONE;);
 
        /* Serialise the interrupt handler in various CPUs, stop Tx path */
-       spin_lock(&self->lock); 
+       spin_lock(&self->lock);
 
        /* Check if we should use the SIR interrupt handler */
-       if (self->io.speed <=  SMSC_IRCC2_MAX_SIR_SPEED) {
+       if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
                ret = smsc_ircc_interrupt_sir(dev);
                goto irq_ret_unlock;
        }
@@ -1416,25 +1438,25 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
        iobase = self->io.fir_base;
 
        register_bank(iobase, 0);
-       iir = inb(iobase+IRCC_IIR);
-       if (iir == 0) 
+       iir = inb(iobase + IRCC_IIR);
+       if (iir == 0)
                goto irq_ret_unlock;
        ret = IRQ_HANDLED;
 
        /* Disable interrupts */
-       outb(0, iobase+IRCC_IER);
-       lcra = inb(iobase+IRCC_LCR_A);
-       lsr = inb(iobase+IRCC_LSR);
-       
+       outb(0, iobase + IRCC_IER);
+       lcra = inb(iobase + IRCC_LCR_A);
+       lsr = inb(iobase + IRCC_LSR);
+
        IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir);
 
        if (iir & IRCC_IIR_EOM) {
                if (self->io.direction == IO_RECV)
-                       smsc_ircc_dma_receive_complete(self, iobase);
+                       smsc_ircc_dma_receive_complete(self);
                else
-                       smsc_ircc_dma_xmit_complete(self, iobase);
-               
-               smsc_ircc_dma_receive(self, iobase);
+                       smsc_ircc_dma_xmit_complete(self);
+
+               smsc_ircc_dma_receive(self);
        }
 
        if (iir & IRCC_IIR_ACTIVE_FRAME) {
@@ -1444,7 +1466,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
        /* Enable interrupts again */
 
        register_bank(iobase, 0);
-       outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+       outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
 
  irq_ret_unlock:
        spin_unlock(&self->lock);
@@ -1459,7 +1481,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
  */
 static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
 {
-       struct smsc_ircc_cb *self = dev->priv;
+       struct smsc_ircc_cb *self = netdev_priv(dev);
        int boguscount = 0;
        int iobase;
        int iir, lsr;
@@ -1469,14 +1491,14 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
 
        iobase = self->io.sir_base;
 
-       iir = inb(iobase+UART_IIR) & UART_IIR_ID;
+       iir = inb(iobase + UART_IIR) & UART_IIR_ID;
        if (iir == 0)
                return IRQ_NONE;
        while (iir) {
                /* Clear interrupt */
-               lsr = inb(iobase+UART_LSR);
+               lsr = inb(iobase + UART_LSR);
 
-               IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+               IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
                            __FUNCTION__, iir, lsr, iobase);
 
                switch (iir) {
@@ -1496,13 +1518,13 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
                        IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n",
                                   __FUNCTION__, iir);
                        break;
-               } 
-               
+               }
+
                /* Make sure we don't stay here to long */
                if (boguscount++ > 100)
                        break;
 
-               iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+               iir = inb(iobase + UART_IIR) & UART_IIR_ID;
        }
        /*spin_unlock(&self->lock);*/
        return IRQ_HANDLED;
@@ -1529,7 +1551,7 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
                   get_dma_residue(self->io.dma));
 
        status = (self->rx_buff.state != OUTSIDE_FRAME);
-       
+
        return status;
 }
 #endif /* unused */
@@ -1544,19 +1566,16 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
 static int smsc_ircc_net_open(struct net_device *dev)
 {
        struct smsc_ircc_cb *self;
-       int iobase;
        char hwname[16];
        unsigned long flags;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-       
+
        IRDA_ASSERT(dev != NULL, return -1;);
-       self = (struct smsc_ircc_cb *) dev->priv;
+       self = netdev_priv(dev);
        IRDA_ASSERT(self != NULL, return 0;);
-       
-       iobase = self->io.fir_base;
 
-       if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, 
+       if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
                        (void *) dev)) {
                IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
                           __FUNCTION__, self->io.irq);
@@ -1568,14 +1587,14 @@ static int smsc_ircc_net_open(struct net_device *dev)
        self->io.speed = 0;
        smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
        spin_unlock_irqrestore(&self->lock, flags);
-       
+
        /* Give self a hardware name */
        /* It would be cool to offer the chip revision here - Jean II */
        sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base);
 
-       /* 
+       /*
         * Open new IrLAP layer instance, now that everything should be
-        * initialized properly 
+        * initialized properly
         */
        self->irlap = irlap_open(dev, &self->qos, hwname);
 
@@ -1590,7 +1609,7 @@ static int smsc_ircc_net_open(struct net_device *dev)
                             __FUNCTION__, self->io.dma);
                return -EAGAIN;
        }
-       
+
        netif_start_queue(dev);
 
        return 0;
@@ -1605,73 +1624,53 @@ static int smsc_ircc_net_open(struct net_device *dev)
 static int smsc_ircc_net_close(struct net_device *dev)
 {
        struct smsc_ircc_cb *self;
-       int iobase;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-       
+
        IRDA_ASSERT(dev != NULL, return -1;);
-       self = (struct smsc_ircc_cb *) dev->priv;       
+       self = netdev_priv(dev);
        IRDA_ASSERT(self != NULL, return 0;);
-       
-       iobase = self->io.fir_base;
 
        /* Stop device */
        netif_stop_queue(dev);
-       
+
        /* Stop and remove instance of IrLAP */
        if (self->irlap)
                irlap_close(self->irlap);
        self->irlap = NULL;
 
        free_irq(self->io.irq, dev);
-
        disable_dma(self->io.dma);
-
        free_dma(self->io.dma);
 
        return 0;
 }
 
-
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
 {
-       IRDA_MESSAGE("%s, Suspending\n", driver_name);
+       struct smsc_ircc_cb *self = dev_get_drvdata(dev);
 
-       if (self->io.suspended)
-               return;
+       IRDA_MESSAGE("%s, Suspending\n", driver_name);
 
-       smsc_ircc_net_close(self->netdev);
+       if (level == SUSPEND_DISABLE && !self->io.suspended) {
+               smsc_ircc_net_close(self->netdev);
+               self->io.suspended = 1;
+       }
 
-       self->io.suspended = 1;
+       return 0;
 }
 
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self)
+static int smsc_ircc_resume(struct device *dev, u32 level)
 {
-       if (!self->io.suspended)
-               return;
+       struct smsc_ircc_cb *self = dev_get_drvdata(dev);
 
-       /* The code was doing a "cli()" here, but this can't be right.
-        * If you need protection, do it in net_open with a spinlock
-        * or give a good reason. - Jean II */
+       if (level == RESUME_ENABLE && self->io.suspended) {
 
-       smsc_ircc_net_open(self->netdev);
-       
-       IRDA_MESSAGE("%s, Waking up\n", driver_name);
-}
+               smsc_ircc_net_open(self->netdev);
+               self->io.suspended = 0;
 
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-        struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data;
-        if (self) {
-                switch (rqst) {
-                case PM_SUSPEND:
-                        smsc_ircc_suspend(self);
-                        break;
-                case PM_RESUME:
-                        smsc_ircc_wakeup(self);
-                        break;
-                }
-        }
+               IRDA_MESSAGE("%s, Waking up\n", driver_name);
+       }
        return 0;
 }
 
@@ -1690,10 +1689,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
 
        IRDA_ASSERT(self != NULL, return -1;);
 
-       iobase = self->io.fir_base;
-
-       if (self->pmdev)
-               pm_unregister(self->pmdev);
+       platform_device_unregister(self->pldev);
 
        /* Remove netdevice */
        unregister_netdev(self->netdev);
@@ -1702,15 +1698,16 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
        spin_lock_irqsave(&self->lock, flags);
 
        /* Stop interrupts */
+       iobase = self->io.fir_base;
        register_bank(iobase, 0);
-       outb(0, iobase+IRCC_IER);
-       outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-       outb(0x00, iobase+IRCC_MASTER);
+       outb(0, iobase + IRCC_IER);
+       outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+       outb(0x00, iobase + IRCC_MASTER);
 #if 0
        /* Reset to SIR mode */
        register_bank(iobase, 1);
-        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
-        outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
+        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA);
+        outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB);
 #endif
        spin_unlock_irqrestore(&self->lock, flags);
 
@@ -1720,7 +1717,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
 
        release_region(self->io.fir_base, self->io.fir_ext);
 
-       IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, 
+       IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
                   self->io.sir_base);
 
        release_region(self->io.sir_base, self->io.sir_ext);
@@ -1728,7 +1725,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
        if (self->tx_buff.head)
                dma_free_coherent(NULL, self->tx_buff.truesize,
                                  self->tx_buff.head, self->tx_buff_dma);
-       
+
        if (self->rx_buff.head)
                dma_free_coherent(NULL, self->rx_buff.truesize,
                                  self->rx_buff.head, self->rx_buff_dma);
@@ -1744,10 +1741,12 @@ static void __exit smsc_ircc_cleanup(void)
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
-       for (i=0; i < 2; i++) {
+       for (i = 0; i < 2; i++) {
                if (dev_self[i])
                        smsc_ircc_close(dev_self[i]);
        }
+
+       driver_unregister(&smsc_ircc_driver);
 }
 
 /*
@@ -1763,34 +1762,34 @@ void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
 
        IRDA_DEBUG(3, "%s\n", __FUNCTION__);
 
-       IRDA_ASSERT(self != NULL, return;);     
-       dev= self->netdev;
-       IRDA_ASSERT(dev != NULL, return;);              
+       IRDA_ASSERT(self != NULL, return;);
+       dev = self->netdev;
+       IRDA_ASSERT(dev != NULL, return;);
        dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir;
 
        fir_base = self->io.fir_base;
        sir_base = self->io.sir_base;
 
        /* Reset everything */
-       outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);
+       outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);
 
        #if SMSC_IRCC2_C_SIR_STOP
        /*smsc_ircc_sir_stop(self);*/
        #endif
 
        register_bank(fir_base, 1);
-       outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base+IRCC_SCE_CFGA);
+       outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base + IRCC_SCE_CFGA);
 
        /* Initialize UART */
-       outb(UART_LCR_WLEN8, sir_base+UART_LCR);  /* Reset DLAB */
-       outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base+UART_MCR);
-       
+       outb(UART_LCR_WLEN8, sir_base + UART_LCR);  /* Reset DLAB */
+       outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base + UART_MCR);
+
        /* Turn on interrups */
-       outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base+UART_IER);
+       outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER);
 
        IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__);
 
-       outb(0x00, fir_base+IRCC_MASTER);
+       outb(0x00, fir_base + IRCC_MASTER);
 }
 
 #if SMSC_IRCC2_C_SIR_STOP
@@ -1802,10 +1801,10 @@ void smsc_ircc_sir_stop(struct smsc_ircc_cb *self)
        iobase = self->io.sir_base;
 
        /* Reset UART */
-       outb(0, iobase+UART_MCR);
-       
+       outb(0, iobase + UART_MCR);
+
        /* Turn off interrupts */
-       outb(0, iobase+UART_IER);
+       outb(0, iobase + UART_IER);
 }
 #endif
 
@@ -1831,16 +1830,16 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
        /* Finished with frame?  */
        if (self->tx_buff.len > 0)  {
                /* Write data left in transmit buffer */
-               actual = smsc_ircc_sir_write(iobase, self->io.fifo_size, 
+               actual = smsc_ircc_sir_write(iobase, self->io.fifo_size,
                                      self->tx_buff.data, self->tx_buff.len);
                self->tx_buff.data += actual;
                self->tx_buff.len  -= actual;
        } else {
-       
+
        /*if (self->tx_buff.len ==0)  {*/
-               
-               /* 
-                *  Now serial buffer is almost free & we can start 
+
+               /*
+                *  Now serial buffer is almost free & we can start
                 *  transmission of another packet. But first we must check
                 *  if we need to change the speed of the hardware
                 */
@@ -1856,21 +1855,19 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
                }
                self->stats.tx_packets++;
 
-               if(self->io.speed <= 115200) {
-               /* 
-                * Reset Rx FIFO to make sure that all reflected transmit data
-                * is discarded. This is needed for half duplex operation
-                */
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
-               if (self->io.speed < 38400)
-                       fcr |= UART_FCR_TRIGGER_1;
-               else 
-                       fcr |= UART_FCR_TRIGGER_14;
+               if (self->io.speed <= 115200) {
+                       /*
+                        * Reset Rx FIFO to make sure that all reflected transmit data
+                        * is discarded. This is needed for half duplex operation
+                        */
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
+                       fcr |= self->io.speed < 38400 ?
+                                       UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
 
-               outb(fcr, iobase+UART_FCR);
+                       outb(fcr, iobase + UART_FCR);
 
-               /* Turn on receive interrupts */
-               outb(UART_IER_RDI, iobase+UART_IER);
+                       /* Turn on receive interrupts */
+                       outb(UART_IER_RDI, iobase + UART_IER);
                }
        }
 }
@@ -1884,17 +1881,17 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
 static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
 {
        int actual = 0;
-       
+
        /* Tx FIFO should be empty! */
-       if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+       if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) {
                IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
                return 0;
        }
-        
+
        /* Fill FIFO with current frame */
-       while ((fifo_size-- > 0) && (actual < len)) {
+       while (fifo_size-- > 0 && actual < len) {
                /* Transmit next byte */
-               outb(buf[actual], iobase+UART_TX);
+               outb(buf[actual], iobase + UART_TX);
                actual++;
        }
        return actual;
@@ -1921,20 +1918,21 @@ static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
 static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
 {
        unsigned int    i;
-       
+
        IRDA_ASSERT(self != NULL, return;);
-       
-       for(i=0; smsc_transceivers[i].name!=NULL; i++) 
-               if((*smsc_transceivers[i].probe)(self->io.fir_base)) {
+
+       for (i = 0; smsc_transceivers[i].name != NULL; i++)
+               if (smsc_transceivers[i].probe(self->io.fir_base)) {
                        IRDA_MESSAGE(" %s transceiver found\n",
                                     smsc_transceivers[i].name);
-                       self->transceiver= i+1;
+                       self->transceiver= i + 1;
                        return;
                }
+
        IRDA_MESSAGE("No transceiver found. Defaulting to %s\n",
                     smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
-                       
-       self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
+
+       self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
 }
 
 
@@ -1947,9 +1945,10 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
 static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed)
 {
        unsigned int trx;
-       
+
        trx = self->transceiver;
-       if(trx>0) (*smsc_transceivers[trx-1].set_for_speed)(self->io.fir_base, speed);
+       if (trx > 0)
+               smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed);
 }
 
 /*
@@ -1977,16 +1976,14 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s
 
 static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
 {
-       int iobase;
+       int iobase = self->io.sir_base;
        int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US;
-       
-       iobase = self->io.sir_base;
-       
+
        /* Calibrated busy loop */
-       while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+       while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT))
                udelay(1);
 
-       if(count == 0)
+       if (count == 0)
                IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
 }
 
@@ -1998,40 +1995,42 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
 
 static int __init smsc_ircc_look_for_chips(void)
 {
-       smsc_chip_address_t *address;
-       char    *type;
+       struct smsc_chip_address *address;
+       char *type;
        unsigned int cfg_base, found;
-       
+
        found = 0;
        address = possible_addresses;
-       
-       while(address->cfg_base){
+
+       while (address->cfg_base) {
                cfg_base = address->cfg_base;
-               
+
                /*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/
-               
-               if( address->type & SMSCSIO_TYPE_FDC){
+
+               if (address->type & SMSCSIO_TYPE_FDC) {
                        type = "FDC";
-                       if((address->type) & SMSCSIO_TYPE_FLAT) {
-                               if(!smsc_superio_flat(fdc_chips_flat,cfg_base, type)) found++;
-                       }
-                       if((address->type) & SMSCSIO_TYPE_PAGED) {
-                               if(!smsc_superio_paged(fdc_chips_paged,cfg_base, type)) found++;                
-                       }                       
+                       if (address->type & SMSCSIO_TYPE_FLAT)
+                               if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type))
+                                       found++;
+
+                       if (address->type & SMSCSIO_TYPE_PAGED)
+                               if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type))
+                                       found++;
                }
-               if( address->type & SMSCSIO_TYPE_LPC){
+               if (address->type & SMSCSIO_TYPE_LPC) {
                        type = "LPC";
-                       if((address->type) & SMSCSIO_TYPE_FLAT) {
-                               if(!smsc_superio_flat(lpc_chips_flat,cfg_base,type)) found++;
-                       }
-                       if((address->type) & SMSCSIO_TYPE_PAGED) {
-                               if(!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) found++;                
-                       }                       
+                       if (address->type & SMSCSIO_TYPE_FLAT)
+                               if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type))
+                                       found++;
+
+                       if (address->type & SMSCSIO_TYPE_PAGED)
+                               if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type))
+                                       found++;
                }
                address++;
        }
        return found;
-} 
+}
 
 /*
  * Function smsc_superio_flat (chip, base, type)
@@ -2039,7 +2038,7 @@ static int __init smsc_ircc_look_for_chips(void)
  *    Try to get configuration of a smc SuperIO chip with flat register model
  *
  */
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfgbase, char *type)
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type)
 {
        unsigned short firbase, sirbase;
        u8 mode, dma, irq;
@@ -2047,39 +2046,37 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
-       if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type)==NULL)
+       if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL)
                return ret;
 
        outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase);
-       mode = inb(cfgbase+1);
-       
+       mode = inb(cfgbase + 1);
+
        /*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/
-       
-       if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
+
+       if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
                IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
 
        outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);
-       sirbase = inb(cfgbase+1) << 2;
+       sirbase = inb(cfgbase + 1) << 2;
 
-       /* FIR iobase */
+       /* FIR iobase */
        outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase);
-       firbase = inb(cfgbase+1) << 3;
+       firbase = inb(cfgbase + 1) << 3;
 
        /* DMA */
        outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase);
-       dma = inb(cfgbase+1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
-       
+       dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
+
        /* IRQ */
        outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);
-       irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+       irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
 
        IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
 
-       if (firbase) {
-               if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
-                       ret=0; 
-       }
-       
+       if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
+               ret = 0;
+
        /* Exit configuration */
        outb(SMSCSIO_CFGEXITKEY, cfgbase);
 
@@ -2092,26 +2089,26 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
  *    Try  to get configuration of a smc SuperIO chip with paged register model
  *
  */
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type)
+static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type)
 {
        unsigned short fir_io, sir_io;
        int ret = -ENODEV;
-       
+
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
-       if (smsc_ircc_probe(cfg_base,0x20,chips,type)==NULL)
+       if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL)
                return ret;
-       
+
        /* Select logical device (UART2) */
        outb(0x07, cfg_base);
        outb(0x05, cfg_base + 1);
-               
+
        /* SIR iobase */
        outb(0x60, cfg_base);
-       sir_io  = inb(cfg_base + 1) << 8;
+       sir_io = inb(cfg_base + 1) << 8;
        outb(0x61, cfg_base);
        sir_io |= inb(cfg_base + 1);
-               
+
        /* Read FIR base */
        outb(0x62, cfg_base);
        fir_io = inb(cfg_base + 1) << 8;
@@ -2119,11 +2116,9 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
        fir_io |= inb(cfg_base + 1);
        outb(0x2b, cfg_base); /* ??? */
 
-       if (fir_io) {
-               if (smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
-                       ret=0; 
-       }
-       
+       if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
+               ret = 0;
+
        /* Exit configuration */
        outb(SMSCSIO_CFGEXITKEY, cfg_base);
 
@@ -2131,21 +2126,17 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
 }
 
 
-static int __init smsc_access(unsigned short cfg_base,unsigned char reg)
+static int __init smsc_access(unsigned short cfg_base, unsigned char reg)
 {
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
        outb(reg, cfg_base);
-
-       if (inb(cfg_base)!=reg)
-               return -1;
-
-       return 0;
+       return inb(cfg_base) != reg ? -1 : 0;
 }
 
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type)
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type)
 {
-       u8 devid,xdevid,rev; 
+       u8 devid, xdevid, rev;
 
        IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
@@ -2158,7 +2149,7 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
 
        outb(reg, cfg_base);
 
-       xdevid=inb(cfg_base+1);
+       xdevid = inb(cfg_base + 1);
 
        /* Enter configuration */
 
@@ -2168,51 +2159,49 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
        if (smsc_access(cfg_base,0x55)) /* send second key and check */
                return NULL;
        #endif
-       
+
        /* probe device ID */
 
-       if (smsc_access(cfg_base,reg))
+       if (smsc_access(cfg_base, reg))
                return NULL;
 
-       devid=inb(cfg_base+1);
-       
-       if (devid==0)                   /* typical value for unused port */
-               return NULL;
+       devid = inb(cfg_base + 1);
 
-       if (devid==0xff)                /* typical value for unused port */
+       if (devid == 0 || devid == 0xff)        /* typical values for unused port */
                return NULL;
 
        /* probe revision ID */
 
-       if (smsc_access(cfg_base,reg+1))
+       if (smsc_access(cfg_base, reg + 1))
                return NULL;
 
-       rev=inb(cfg_base+1);
+       rev = inb(cfg_base + 1);
 
-       if (rev>=128)                   /* i think this will make no sense */
+       if (rev >= 128)                 /* i think this will make no sense */
                return NULL;
 
-       if (devid==xdevid)              /* protection against false positives */        
+       if (devid == xdevid)            /* protection against false positives */
                return NULL;
 
        /* Check for expected device ID; are there others? */
 
-       while(chip->devid!=devid) {
+       while (chip->devid != devid) {
 
                chip++;
 
-               if (chip->name==NULL)
+               if (chip->name == NULL)
                        return NULL;
        }
 
-       IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+       IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",
+                    devid, rev, cfg_base, type, chip->name);
 
-       if (chip->rev>rev){
-               IRDA_MESSAGE("Revision higher than expected\n");        
+       if (chip->rev > rev) {
+               IRDA_MESSAGE("Revision higher than expected\n");
                return NULL;
        }
-       
-       if (chip->flags&NoIRDA)
+
+       if (chip->flags & NoIRDA)
                IRDA_MESSAGE("chipset does not support IRDA\n");
 
        return chip;
@@ -2226,8 +2215,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base)
                IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
                             __FUNCTION__, cfg_base);
        } else {
-               if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")
-                   ||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+               if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") ||
+                   !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC"))
                        ret =  0;
 
                release_region(cfg_base, 2);
@@ -2244,9 +2233,10 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
                IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
                             __FUNCTION__, cfg_base);
        } else {
-               if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")
-                   ||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+               if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") ||
+                   !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC"))
                        ret = 0;
+
                release_region(cfg_base, 2);
        }
        return ret;
@@ -2269,18 +2259,23 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
 static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed)
 {
        unsigned long jiffies_now, jiffies_timeout;
-       u8      val;
-       
-       jiffies_now= jiffies;
-       jiffies_timeout= jiffies+SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
-       
+       u8 val;
+
+       jiffies_now = jiffies;
+       jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
+
        /* ATC */
        register_bank(fir_base, 4);
-       outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC);
-       while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout));
-       if(val)
+       outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE,
+            fir_base + IRCC_ATC);
+
+       while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) &&
+               !time_after(jiffies, jiffies_timeout))
+               /* empty */;
+
+       if (val)
                IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
-                            inb(fir_base+IRCC_ATC));
+                            inb(fir_base + IRCC_ATC));
 }
 
 /*
@@ -2298,34 +2293,32 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base)
 /*
  * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed)
  *
- *    Set transceiver 
+ *    Set transceiver
  *
  */
 
 static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed)
 {
-       u8      fast_mode;
-       
-       switch(speed)
-       {
-               default:
-               case 576000 :
-               fast_mode = 0; 
+       u8 fast_mode;
+
+       switch (speed) {
+       default:
+       case 576000 :
+               fast_mode = 0;
                break;
-               case 1152000 :
-               case 4000000 :
+       case 1152000 :
+       case 4000000 :
                fast_mode = IRCC_LCR_A_FAST;
                break;
-               
        }
        register_bank(fir_base, 0);
-       outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+       outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);
 }
 
 /*
  * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base)
  *
- *    Probe transceiver 
+ *    Probe transceiver
  *
  */
 
@@ -2337,35 +2330,34 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base)
 /*
  * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed)
  *
- *    Set transceiver 
+ *    Set transceiver
  *
  */
 
 static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed)
 {
-       u8      fast_mode;
-       
-       switch(speed)
-       {
-               default:
-               case 576000 :
-               fast_mode = 0; 
+       u8 fast_mode;
+
+       switch (speed) {
+       default:
+       case 576000 :
+               fast_mode = 0;
                break;
-               case 1152000 :
-               case 4000000 :
+       case 1152000 :
+       case 4000000 :
                fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA;
                break;
-               
+
        }
        /* This causes an interrupt */
        register_bank(fir_base, 0);
-       outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+       outb((inb(fir_base + IRCC_LCR_A) &  0xbf) | fast_mode, fir_base + IRCC_LCR_A);
 }
 
 /*
  * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base)
  *
- *    Probe transceiver 
+ *    Probe transceiver
  *
  */
 
@@ -2377,20 +2369,3 @@ static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base)
 
 module_init(smsc_ircc_init);
 module_exit(smsc_ircc_cleanup);
-
-MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
-MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
-MODULE_LICENSE("GPL");
-
-module_param(ircc_dma, int, 0);
-MODULE_PARM_DESC(ircc_dma, "DMA channel");
-module_param(ircc_irq, int, 0);
-MODULE_PARM_DESC(ircc_irq, "IRQ line");
-module_param(ircc_fir, int, 0);
-MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
-module_param(ircc_sir, int, 0);
-MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
-module_param(ircc_cfg, int, 0);
-MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
-module_param(ircc_transceiver, int, 0);
-MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
index 458611cc0d40c8d027a8e3aacf2701e34854dd65..0c36286d87f7022f3530b0f13bfa9d0b37ae46ef 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************************
- * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $               
+ * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
  *
  * Description:   Definitions for the SMC IrCC chipset
  * Status:        Experimental.
@@ -9,25 +9,25 @@
  *     All Rights Reserved.
  *
  * Based on smc-ircc.h:
- * 
+ *
  *     Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
  *     All Rights Reserved
  *
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- * 
+ *
  *     This program is distributed in the hope that it will be useful,
  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License 
- *     along with this program; if not, write to the Free Software 
- *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  *     MA 02111-1307 USA
  *
  ********************************************************************/
 
 #define   IRCC_CFGA_COM                                0x00
 #define                IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK      0x87
-#define        IRCC_CFGA_IRDA_SIR_A    0x08
-#define        IRCC_CFGA_ASK_SIR               0x10
-#define        IRCC_CFGA_IRDA_SIR_B    0x18
-#define        IRCC_CFGA_IRDA_HDLC             0x20
+#define                IRCC_CFGA_IRDA_SIR_A    0x08
+#define                IRCC_CFGA_ASK_SIR               0x10
+#define                IRCC_CFGA_IRDA_SIR_B    0x18
+#define                IRCC_CFGA_IRDA_HDLC             0x20
 #define                IRCC_CFGA_IRDA_4PPM             0x28
 #define                IRCC_CFGA_CONSUMER              0x30
 #define                IRCC_CFGA_RAW_IR                0x38
 #define IRCC_CFGB_LPBCK_TX_CRC    0x10
 #define IRCC_CFGB_NOWAIT          0x08
 #define IRCC_CFGB_STRING_MOVE     0x04
-#define IRCC_CFGB_DMA_BURST       0x02
+#define IRCC_CFGB_DMA_BURST       0x02
 #define IRCC_CFGB_DMA_ENABLE      0x01
 
 #define IRCC_CFGB_MUX_COM          0x00
 /* Register block 3 - Identification Registers! */
 #define IRCC_ID_HIGH              0x00   /* 0x10 */
 #define IRCC_ID_LOW               0x01   /* 0xB8 */
-#define IRCC_CHIP_ID              0x02   /* 0xF1 */
+#define IRCC_CHIP_ID              0x02   /* 0xF1 */
 #define IRCC_VERSION              0x03   /* 0x01 */
 #define IRCC_INTERFACE            0x04   /* low 4 = DMA, high 4 = IRQ */
-#define        IRCC_INTERFACE_DMA_MASK 0x0F   /* low 4 = DMA, high 4 = IRQ */
-#define        IRCC_INTERFACE_IRQ_MASK 0xF0   /* low 4 = DMA, high 4 = IRQ */
+#define                IRCC_INTERFACE_DMA_MASK 0x0F   /* low 4 = DMA, high 4 = IRQ */
+#define                IRCC_INTERFACE_IRQ_MASK 0xF0   /* low 4 = DMA, high 4 = IRQ */
 
 /* Register block 4 - IrDA */
 #define IRCC_CONTROL               0x00
 
 /* Register block 5 - IrDA */
 #define IRCC_ATC                                       0x00
-#define        IRCC_ATC_nPROGREADY             0x80
-#define        IRCC_ATC_SPEED                  0x40
-#define        IRCC_ATC_ENABLE                 0x20
-#define        IRCC_ATC_MASK                   0xE0
+#define                IRCC_ATC_nPROGREADY             0x80
+#define                IRCC_ATC_SPEED                  0x40
+#define                IRCC_ATC_ENABLE                 0x20
+#define                IRCC_ATC_MASK                   0xE0
 
 
 #define IRCC_IRHALFDUPLEX_TIMEOUT      0x01
  */
 
 #define SMSC_IRCC2_MAX_SIR_SPEED               115200
-#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT  8
-#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT  8
+#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT  8
+#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT  8
 #define SMSC_IRCC2_FIFO_SIZE                   16
 #define SMSC_IRCC2_FIFO_THRESHOLD              64
 /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
index 7cfe1669ae9db65489c7388da52aaaacfd3ff67d..c829e6a2e8a681242b03fbcb6f26210c633aeb2e 100644 (file)
@@ -354,7 +354,7 @@ static int init_shared_mem(struct s2io_nic *nic)
        int lst_size, lst_per_page;
        struct net_device *dev = nic->dev;
 #ifdef CONFIG_2BUFF_MODE
-       u64 tmp;
+       unsigned long tmp;
        buffAdd_t *ba;
 #endif
 
@@ -562,18 +562,18 @@ static int init_shared_mem(struct s2io_nic *nic)
                                    (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_0_org)
                                        return -ENOMEM;
-                               tmp = (u64) ba->ba_0_org;
+                               tmp = (unsigned long) ba->ba_0_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((u64) ALIGN_SIZE);
+                               tmp &= ~((unsigned long) ALIGN_SIZE);
                                ba->ba_0 = (void *) tmp;
 
                                ba->ba_1_org = (void *) kmalloc
                                    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_1_org)
                                        return -ENOMEM;
-                               tmp = (u64) ba->ba_1_org;
+                               tmp = (unsigned long) ba->ba_1_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((u64) ALIGN_SIZE);
+                               tmp &= ~((unsigned long) ALIGN_SIZE);
                                ba->ba_1 = (void *) tmp;
                                k++;
                        }
index a9b06b8d8e3ff185ffbd9cb90ff00e1ee0528fc3..ac9ce6509eee78af13c014d184b27bb0f5922e64 100644 (file)
@@ -986,7 +986,7 @@ static const char * chip_ids[ 16 ] =  {
        })
 #endif
 
-#if SMC_CAN_USE_DATACS
+#ifdef SMC_CAN_USE_DATACS
 #define SMC_PUSH_DATA(p, l)                                            \
        if ( lp->datacs ) {                                             \
                unsigned char *__ptr = (p);                             \
index 4598c6a9212df977024db0fd43311a0f7dcf1530..97f723179f621d15ed3f9283a8a80446aa4a2cb0 100644 (file)
@@ -2739,6 +2739,7 @@ enum parport_pc_pci_cards {
        syba_2p_epp,
        syba_1p_ecp,
        titan_010l,
+       titan_1284p1,
        titan_1284p2,
        avlab_1p,
        avlab_2p,
@@ -2811,6 +2812,7 @@ static struct parport_pc_pci {
        /* syba_2p_epp AP138B */        { 2, { { 0, 0x078 }, { 0, 0x178 }, } },
        /* syba_1p_ecp W83787 */        { 1, { { 0, 0x078 }, } },
        /* titan_010l */                { 1, { { 3, -1 }, } },
+       /* titan_1284p1 */              { 1, { { 0, 1 }, } },
        /* titan_1284p2 */              { 2, { { 0, 1 }, { 2, 3 }, } },
        /* avlab_1p             */      { 1, { { 0, 1}, } },
        /* avlab_2p             */      { 2, { { 0, 1}, { 2, 3 },} },
@@ -2884,6 +2886,7 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+       { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 },
        { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
        /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
        { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */
index 2b85aa39f9544dd4069f5f9ef2b2abaca4ee145b..532f73bb2224af802af190aa0a38ea66242aa188 100644 (file)
@@ -91,6 +91,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
 {
        struct msi_desc *entry;
        struct msg_address address;
+       unsigned int irq = vector;
 
        entry = (struct msi_desc *)msi_desc[vector];
        if (!entry || !entry->dev)
@@ -112,6 +113,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
                entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
                pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
                        address.lo_address.value);
+               set_native_irq_info(irq, cpu_mask);
                break;
        }
        case PCI_CAP_ID_MSIX:
@@ -125,22 +127,13 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
                        MSI_TARGET_CPU_SHIFT);
                entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
                writel(address.lo_address.value, entry->mask_base + offset);
+               set_native_irq_info(irq, cpu_mask);
                break;
        }
        default:
                break;
        }
 }
-
-#ifdef CONFIG_IRQBALANCE
-static inline void move_msi(int vector)
-{
-       if (!cpus_empty(pending_irq_balance_cpumask[vector])) {
-               set_msi_affinity(vector, pending_irq_balance_cpumask[vector]);
-               cpus_clear(pending_irq_balance_cpumask[vector]);
-       }
-}
-#endif /* CONFIG_IRQBALANCE */
 #endif /* CONFIG_SMP */
 
 static void mask_MSI_irq(unsigned int vector)
@@ -191,13 +184,13 @@ static void shutdown_msi_irq(unsigned int vector)
 
 static void end_msi_irq_wo_maskbit(unsigned int vector)
 {
-       move_msi(vector);
+       move_native_irq(vector);
        ack_APIC_irq();
 }
 
 static void end_msi_irq_w_maskbit(unsigned int vector)
 {
-       move_msi(vector);
+       move_native_irq(vector);
        unmask_MSI_irq(vector);
        ack_APIC_irq();
 }
index 390f1851c0f11b4d88206f13f720bd0b8c1b5ffa..402136a5c9e43c1af7ff107e8e20cd992657c30c 100644 (file)
@@ -19,7 +19,6 @@
 #define NR_HP_RESERVED_VECTORS         20
 
 extern int vector_irq[NR_VECTORS];
-extern cpumask_t pending_irq_balance_cpumask[NR_IRQS];
 extern void (*interrupt[NR_IRQS])(void);
 extern int pci_vector_resources(int last, int nr_released);
 
@@ -29,10 +28,6 @@ extern int pci_vector_resources(int last, int nr_released);
 #define set_msi_irq_affinity   NULL
 #endif
 
-#ifndef CONFIG_IRQBALANCE
-static inline void move_msi(int vector) {}
-#endif
-
 /*
  * MSI-X Address Register
  */
index be420bb291135a8cee511c9df3edf91e79b1ea27..edccfa5bb40087b0a0b9cbefae7bdbae5d781348 100644 (file)
 #define  TOPIC97_AVS_AUDIO_CONTROL     0x02
 #define  TOPIC97_AVS_VIDEO_CONTROL     0x01
 
+#define TOPIC_EXCA_IF_CONTROL          0x3e    /* 8 bit */
+#define TOPIC_EXCA_IFC_33V_ENA         0x01
 
 static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
 {
@@ -137,4 +139,19 @@ static int topic97_override(struct yenta_socket *socket)
        return 0;
 }
 
+
+static int topic95_override(struct yenta_socket *socket)
+{
+       u8 fctrl;
+
+       /* enable 3.3V support for 16bit cards */
+       fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
+       exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA);
+
+       /* tell yenta to use exca registers to power 16bit cards */
+       socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
+
+       return 0;
+}
+
 #endif /* _LINUX_TOPIC_H */
index 62fd705203fb0d48ecc55d16b8c68b6376fa852a..0347a29f297bea94f55df5f1ecc3db6795bb648f 100644 (file)
@@ -184,22 +184,52 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
        return 0;
 }
 
-static int yenta_Vcc_power(u32 control)
+static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
 {
-       switch (control & CB_SC_VCC_MASK) {
-       case CB_SC_VCC_5V: return 50;
-       case CB_SC_VCC_3V: return 33;
-       default: return 0;
-       }
-}
+       if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+           (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+               u8 reg, vcc, vpp;
+
+               reg = exca_readb(socket, I365_POWER);
+               vcc = reg & I365_VCC_MASK;
+               vpp = reg & I365_VPP1_MASK;
+               state->Vcc = state->Vpp = 0;
+
+               if (socket->flags & YENTA_16BIT_POWER_DF) {
+                       if (vcc == I365_VCC_3V)
+                               state->Vcc = 33;
+                       if (vcc == I365_VCC_5V)
+                               state->Vcc = 50;
+                       if (vpp == I365_VPP1_5V)
+                               state->Vpp = state->Vcc;
+                       if (vpp == I365_VPP1_12V)
+                               state->Vpp = 120;
+               } else {
+                       if (reg & I365_VCC_5V) {
+                               state->Vcc = 50;
+                               if (vpp == I365_VPP1_5V)
+                                       state->Vpp = 50;
+                               if (vpp == I365_VPP1_12V)
+                                       state->Vpp = 120;
+                       }
+               }
+       } else {
+               u32 control;
 
-static int yenta_Vpp_power(u32 control)
-{
-       switch (control & CB_SC_VPP_MASK) {
-       case CB_SC_VPP_12V: return 120;
-       case CB_SC_VPP_5V: return 50;
-       case CB_SC_VPP_3V: return 33;
-       default: return 0;
+               control = cb_readl(socket, CB_SOCKET_CONTROL);
+
+               switch (control & CB_SC_VCC_MASK) {
+               case CB_SC_VCC_5V: state->Vcc = 50; break;
+               case CB_SC_VCC_3V: state->Vcc = 33; break;
+               default: state->Vcc = 0;
+               }
+
+               switch (control & CB_SC_VPP_MASK) {
+               case CB_SC_VPP_12V: state->Vpp = 120; break;
+               case CB_SC_VPP_5V: state->Vpp = 50; break;
+               case CB_SC_VPP_3V: state->Vpp = 33; break;
+               default: state->Vpp = 0;
+               }
        }
 }
 
@@ -211,8 +241,7 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 
        control = cb_readl(socket, CB_SOCKET_CONTROL);
 
-       state->Vcc = yenta_Vcc_power(control);
-       state->Vpp = yenta_Vpp_power(control);
+       yenta_get_power(socket, state);
        state->io_irq = socket->io_irq;
 
        if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
@@ -246,19 +275,54 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 
 static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
 {
-       u32 reg = 0;    /* CB_SC_STPCLK? */
-       switch (state->Vcc) {
-       case 33: reg = CB_SC_VCC_3V; break;
-       case 50: reg = CB_SC_VCC_5V; break;
-       default: reg = 0; break;
-       }
-       switch (state->Vpp) {
-       case 33:  reg |= CB_SC_VPP_3V; break;
-       case 50:  reg |= CB_SC_VPP_5V; break;
-       case 120: reg |= CB_SC_VPP_12V; break;
+       /* some birdges require to use the ExCA registers to power 16bit cards */
+       if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+           (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+               u8 reg, old;
+               reg = old = exca_readb(socket, I365_POWER);
+               reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK);
+
+               /* i82365SL-DF style */
+               if (socket->flags & YENTA_16BIT_POWER_DF) {
+                       switch (state->Vcc) {
+                       case 33: reg |= I365_VCC_3V; break;
+                       case 50: reg |= I365_VCC_5V; break;
+                       default: reg = 0; break;
+                       }
+                       switch (state->Vpp) {
+                       case 33:
+                       case 50: reg |= I365_VPP1_5V; break;
+                       case 120: reg |= I365_VPP1_12V; break;
+                       }
+               } else {
+                       /* i82365SL-B style */
+                       switch (state->Vcc) {
+                       case 50: reg |= I365_VCC_5V; break;
+                       default: reg = 0; break;
+                       }
+                       switch (state->Vpp) {
+                       case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
+                       case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
+                       }
+               }
+
+               if (reg != old)
+                       exca_writeb(socket, I365_POWER, reg);
+       } else {
+               u32 reg = 0;    /* CB_SC_STPCLK? */
+               switch (state->Vcc) {
+               case 33: reg = CB_SC_VCC_3V; break;
+               case 50: reg = CB_SC_VCC_5V; break;
+               default: reg = 0; break;
+               }
+               switch (state->Vpp) {
+               case 33:  reg |= CB_SC_VPP_3V; break;
+               case 50:  reg |= CB_SC_VPP_5V; break;
+               case 120: reg |= CB_SC_VPP_12V; break;
+               }
+               if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
+                       cb_writel(socket, CB_SOCKET_CONTROL, reg);
        }
-       if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
-               cb_writel(socket, CB_SOCKET_CONTROL, reg);
 }
 
 static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
@@ -751,6 +815,7 @@ enum {
        CARDBUS_TYPE_TI12XX,
        CARDBUS_TYPE_TI1250,
        CARDBUS_TYPE_RICOH,
+       CARDBUS_TYPE_TOPIC95,
        CARDBUS_TYPE_TOPIC97,
        CARDBUS_TYPE_O2MICRO,
 };
@@ -789,6 +854,9 @@ static struct cardbus_type cardbus_type[] = {
                .save_state     = ricoh_save_state,
                .restore_state  = ricoh_restore_state,
        },
+       [CARDBUS_TYPE_TOPIC95]  = {
+               .override       = topic95_override,
+       },
        [CARDBUS_TYPE_TOPIC97]  = {
                .override       = topic97_override,
        },
@@ -1196,6 +1264,7 @@ static struct pci_device_id yenta_table [] = {
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
 
+       CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
        CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
        CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
 
index 4e637eef207652a33beaa752d1c6d6fdd2367ea3..4e75e9e258cd1419e105439ae7b995f79e2cff68 100644 (file)
  */
 #define CB_MEM_PAGE(map)       (0x40 + (map))
 
+
+/* control how 16bit cards are powered */
+#define YENTA_16BIT_POWER_EXCA 0x00000001
+#define YENTA_16BIT_POWER_DF   0x00000002
+
+
 struct yenta_socket;
 
 struct cardbus_type {
@@ -113,6 +119,8 @@ struct yenta_socket {
        struct pcmcia_socket socket;
        struct cardbus_type *type;
 
+       u32 flags;
+
        /* for PCI interrupt probing */
        unsigned int probe_status;
 
index 6e5229e92fbc7bc9fa6a443a9f78fff7f9867b32..e95ed67d4f050afddf5918d34628e4586ba70951 100644 (file)
@@ -8,13 +8,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
index 1d037c2a82acb0a5bfbd8002ae0274128fb01ee3..33da25f3213f4614a6dc338b9743034452dab3de 100644 (file)
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
index 82c5edd5b9ee016795b00116cd64f02f7f526dab..beedd86800f4e26093643ec765961a2fbd6f0e25 100644 (file)
@@ -142,17 +142,6 @@ static void isapnp_write_word(unsigned char idx, unsigned short val)
        isapnp_write_byte(idx+1, val);
 }
 
-static void *isapnp_alloc(long size)
-{
-       void *result;
-
-       result = kmalloc(size, GFP_KERNEL);
-       if (!result)
-               return NULL;
-       memset(result, 0, size);
-       return result;
-}
-
 static void isapnp_key(void)
 {
        unsigned char code = 0x6a, msb;
@@ -406,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne
        struct pnp_id * id;
        if (!dev)
                return;
-       id = isapnp_alloc(sizeof(struct pnp_id));
+       id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
        if (!id)
                return;
        sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -430,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
        struct pnp_dev *dev;
 
        isapnp_peek(tmp, size);
-       dev = isapnp_alloc(sizeof(struct pnp_dev));
+       dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
        if (!dev)
                return NULL;
        dev->number = number;
@@ -461,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
        unsigned long bits;
 
        isapnp_peek(tmp, size);
-       irq = isapnp_alloc(sizeof(struct pnp_irq));
+       irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
        if (!irq)
                return;
        bits = (tmp[1] << 8) | tmp[0];
@@ -485,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
        struct pnp_dma *dma;
 
        isapnp_peek(tmp, size);
-       dma = isapnp_alloc(sizeof(struct pnp_dma));
+       dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
        if (!dma)
                return;
        dma->map = tmp[0];
@@ -505,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
        struct pnp_port *port;
 
        isapnp_peek(tmp, size);
-       port = isapnp_alloc(sizeof(struct pnp_port));
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = (tmp[2] << 8) | tmp[1];
@@ -528,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
        struct pnp_port *port;
 
        isapnp_peek(tmp, size);
-       port = isapnp_alloc(sizeof(struct pnp_port));
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = port->max = (tmp[1] << 8) | tmp[0];
@@ -550,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
        struct pnp_mem *mem;
 
        isapnp_peek(tmp, size);
-       mem = isapnp_alloc(sizeof(struct pnp_mem));
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
@@ -573,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
        struct pnp_mem *mem;
 
        isapnp_peek(tmp, size);
-       mem = isapnp_alloc(sizeof(struct pnp_mem));
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -595,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
        struct pnp_mem *mem;
 
        isapnp_peek(tmp, size);
-       mem = isapnp_alloc(sizeof(struct pnp_mem));
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -838,7 +827,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
 
 static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
 {
-       struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
+       struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
        if (!id)
                return;
        sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -874,7 +863,7 @@ static int __init isapnp_build_device_list(void)
                        header[4], header[5], header[6], header[7], header[8]);
                printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
 #endif
-               if ((card = isapnp_alloc(sizeof(struct pnp_card))) == NULL)
+               if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
                        continue;
 
                card->number = csn;
index 6c510c19ad7d9097581d70ac25fd5983b13df76d..94442ffd4aeddcd100ba9d573c6a8866fdb21b1b 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-
-#ifdef CONFIG_PNP_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
index 8655dd2e5b83cea720d98b0c0e9d4e02220fb6b0..1a8915e74160bba5b0b4a94f2ecbe6322168b8e6 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  
+#include <linux/config.h>
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 #include <acpi/acpi_bus.h>
@@ -41,14 +42,6 @@ static inline int is_exclusive_device(struct acpi_device *dev)
        return (!acpi_match_ids(dev, excluded_id_list));
 }
 
-void *pnpacpi_kmalloc(size_t size, int f)
-{
-       void *p = kmalloc(size, f);
-       if (p)
-               memset(p, 0, size);
-       return p;
-}
-
 /*
  * Compatible Device IDs
  */
@@ -143,7 +136,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
                return 0;
 
        pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
-       dev =  pnpacpi_kmalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+       dev =  kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
        if (!dev) {
                pnp_err("Out of memory");
                return -ENOMEM;
@@ -173,7 +166,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
        dev->number = num;
        
        /* set the initial values for the PnP device */
-       dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+       dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
        if (!dev_id)
                goto err;
        pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
@@ -205,8 +198,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
                for (i = 0; i < cid_list->count; i++) {
                        if (!ispnpidacpi(cid_list->id[i].value))
                                continue;
-                       dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), 
-                               GFP_KERNEL);
+                       dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
                        if (!dev_id)
                                continue;
 
index 76f907e09ee62af18e53c574e72c48efecdae2d9..f28e2ed66fa34e6e1d2de9fa8ea1262ad703103d 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 
-void *pnpacpi_kmalloc(size_t size, int f);
 acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*);
 acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*);
 int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *);
index 75575f6c349c65919871f32afe3dc8e83fbc3219..675b76a42403fdf8b39f01ab28b65ba2408fa519 100644 (file)
@@ -244,7 +244,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
 
        if (p->number_of_channels == 0)
                return;
-       dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+       dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
        if (!dma)
                return;
 
@@ -300,7 +300,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option,
        
        if (p->number_of_interrupts == 0)
                return;
-       irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+       irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
        if (!irq)
                return;
 
@@ -321,7 +321,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
 
        if (p->number_of_interrupts == 0)
                return;
-       irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+       irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
        if (!irq)
                return;
 
@@ -342,7 +342,7 @@ pnpacpi_parse_port_option(struct pnp_option *option,
 
        if (io->range_length == 0)
                return;
-       port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = io->min_base_address;
@@ -363,7 +363,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
 
        if (io->range_length == 0)
                return;
-       port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = port->max = io->base_address;
@@ -382,7 +382,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
 
        if (p->range_length == 0)
                return;
-       mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = p->min_base_address;
@@ -405,7 +405,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
 
        if (p->range_length == 0)
                return;
-       mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = p->min_base_address;
@@ -428,7 +428,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
 
        if (p->range_length == 0)
                return;
-       mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = mem->max = p->range_base_address;
@@ -612,7 +612,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
        if (!res_cnt)
                return -EINVAL;
        buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
-       buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL);
+       buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
        if (!buffer->pointer)
                return -ENOMEM;
        pnp_dbg("Res cnt %d", res_cnt);
index 778a324028f4135bdb90bb4e655bac513c17e43d..f49674f07949bcf505632d3d4c842a7c4b542e50 100644 (file)
@@ -86,16 +86,6 @@ int pnp_bios_present(void)
 
 struct pnp_dev_node_info node_info;
 
-void *pnpbios_kmalloc(size_t size, int f)
-{
-       void *p = kmalloc( size, f );
-       if ( p == NULL )
-               printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
-       else
-               memset(p, 0, size);
-       return p;
-}
-
 /*
  *
  * DOCKING FUNCTIONS
@@ -121,10 +111,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
        if (!current->fs->root) {
                return -EAGAIN;
        }
-       if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+       if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
                return -ENOMEM;
        }
-       if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
+       if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
                kfree (envp);
                return -ENOMEM;
        }
@@ -231,7 +221,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table
        if(!pnpbios_is_dynamic(dev))
                return -EPERM;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node)
                return -1;
        if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -254,7 +244,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table
        if (!pnpbios_is_dynamic(dev))
                return -EPERM;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node)
                return -1;
        if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -305,7 +295,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev)
        if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
                return -EPERM;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node)
                return -ENOMEM;
 
@@ -347,7 +337,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
        }
 
        /* set the initial values for the PnP device */
-       dev_id = pnpbios_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+       dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
        if (!dev_id)
                return -1;
        pnpid32_to_pnpid(node->eisa_id,id);
@@ -385,7 +375,7 @@ static void __init build_devlist(void)
        struct pnp_bios_node *node;
        struct pnp_dev *dev;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node)
                return;
 
@@ -402,7 +392,7 @@ static void __init build_devlist(void)
                                break;
                }
                nodes_got++;
-               dev =  pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL);
+               dev =  kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
                if (!dev)
                        break;
                if(insert_device(dev,node)<0)
index 01896e705ed45ad91348e34b60a27d7c6ad2fd40..d8cb2fd1f127a98a10673e937889802cf7d6b79b 100644 (file)
@@ -26,7 +26,6 @@ union pnp_bios_install_struct {
 
 extern int pnp_bios_present(void);
 extern int  pnpbios_dont_use_current_config;
-extern void *pnpbios_kmalloc(size_t size, int f);
 
 extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
 extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
index 6bb8e1973fd497a8807992336ebd089c8ac7b3f0..5a3dfc97f5e90ef655aac0ce5a7c6576a6274a70 100644 (file)
@@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
                return -EFBIG;
        }
 
-       tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
+       tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
        if (!tmpbuf) return -ENOMEM;
 
        if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
@@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos,
        if (pos >= 0xff)
                return 0;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node) return -ENOMEM;
 
        for (nodenum=pos; nodenum<0xff; ) {
@@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos,
        u8 nodenum = (long)data;
        int len;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node) return -ENOMEM;
        if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
                kfree(node);
@@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf,
        u8 nodenum = (long)data;
        int ret = count;
 
-       node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+       node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
        if (!node)
                return -ENOMEM;
        if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
index e305bb132c24e30eb418b656e6a1e4118b68928d..b0ca65b68645624e1ddd78ac1f4de6d71c4156e4 100644 (file)
@@ -247,7 +247,7 @@ static void
 pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_mem * mem;
-       mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = ((p[5] << 8) | p[4]) << 8;
@@ -263,7 +263,7 @@ static void
 pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_mem * mem;
-       mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -279,7 +279,7 @@ static void
 pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_mem * mem;
-       mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+       mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
        if (!mem)
                return;
        mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -296,7 +296,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option)
        struct pnp_irq * irq;
        unsigned long bits;
 
-       irq = pnpbios_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+       irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
        if (!irq)
                return;
        bits = (p[2] << 8) | p[1];
@@ -313,7 +313,7 @@ static void
 pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_dma * dma;
-       dma = pnpbios_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+       dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
        if (!dma)
                return;
        dma->map = p[1];
@@ -326,7 +326,7 @@ static void
 pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_port * port;
-       port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = (p[3] << 8) | p[2];
@@ -342,7 +342,7 @@ static void
 pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
 {
        struct pnp_port * port;
-       port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+       port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
        if (!port)
                return;
        port->min = port->max = (p[2] << 8) | p[1];
@@ -530,7 +530,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de
                case SMALL_TAG_COMPATDEVID: /* compatible ID */
                        if (len != 4)
                                goto len_err;
-                       dev_id =  pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
+                       dev_id =  kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
                        if (!dev_id)
                                return NULL;
                        memset(dev_id, 0, sizeof(struct pnp_id));
index 596a02d7e03d12308a6c6992f155eb73548cf101..8936b0cb2ec3718bc60937efcace3bc22c27b2fb 100644 (file)
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
index b952aec491899b7698dd0b808befd2945a0a8ed1..61fe998944bd1ce0d0f6816687f964861e8d8934 100644 (file)
@@ -8,13 +8,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
-
-#ifdef CONFIG_PNP_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pnp.h>
 #include "base.h"
 
index f8ec6fe7d85855a03457b0dabb80104f9f7d838f..d40ba0bd68a3b776699f62ff56e9b9ba89059950 100644 (file)
  */
 #include <scsi/scsi_dbg.h>
 
+#ifndef NDEBUG
+#define NDEBUG 0
+#endif
+#ifndef NDEBUG
+#define NDEBUG_ABORT 0
+#endif
+
 #if (NDEBUG & NDEBUG_LISTS)
 #define LIST(x,y) {printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }
 #define REMOVE(w,x,y,z) {printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }
@@ -359,7 +366,7 @@ static struct {
        {PHASE_UNKNOWN, "UNKNOWN"}
 };
 
-#ifdef NDEBUG
+#if NDEBUG
 static struct {
        unsigned char mask;
        const char *name;
index 79ae73b2368029bb3fe35f3ce8ff0a5a3e0b93b0..e1f2246ee7cda1ca97360e913b9982b599f496a3 100644 (file)
@@ -62,7 +62,7 @@
 
 #define SYNC_MODE 0            /* Synchronous transfer mode */
 
-#if DEBUG
+#ifdef DEBUG
 #undef NCR53C406A_DEBUG
 #define NCR53C406A_DEBUG 1
 #endif
index 029c2482e12770bca69a5ef53b6572d8825526aa..ffcdeb68641cf5a2493abf7be5b68b1da32f329c 100644 (file)
@@ -494,7 +494,7 @@ static int qs_port_start(struct ata_port *ap)
        if (rc)
                return rc;
        qs_enter_reg_mode(ap);
-       pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
        if (!pp) {
                rc = -ENOMEM;
                goto err_out;
index 9097f2f7b12a6bb5a1dbfb88a79c6a40ed14051b..2efb317153ce19a8ca7d974c3b18b03bddb62c60 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 
index b116122e569ab3592b5e3abaa23f24d83c39e9d5..170c9d2a749cc1ce8f2c3820dd603435bbcbf7ad 100644 (file)
@@ -2474,8 +2474,7 @@ static struct tty_operations rs_360_ops = {
        .tiocmset = rs_360_tiocmset,
 };
 
-/* int __init rs_360_init(void) */
-int rs_360_init(void)
+static int __init rs_360_init(void)
 {
        struct serial_state * state;
        ser_info_t      *info;
@@ -2827,10 +2826,7 @@ int rs_360_init(void)
 
        return 0;
 }
-
-
-
-
+module_init(rs_360_init);
 
 /* This must always be called before the rs_360_init() function, otherwise
  * it blows away the port control information.
index 5690594b257bb4f7aabc64b9cc82ea41e1a6de1b..40d3e7139cfea2518fff6c2a758e0bdc4c5cd53d 100644 (file)
@@ -446,7 +446,6 @@ static char *serial_version = "$Revision: 1.25 $";
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/bitops.h>
 #include <linux/delay.h>
 
index 79f8df4d66b799e06625ea9218371eacd268224b..eb31125c6a30f84de2416f80c939bc1eae412fc8 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/bitops.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 8c40167778dea949e077954a10445736f9f6ea21..43b03c55f453859a2902c7dc50d72f741b508e20 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/semaphore.h>
 #include <asm/delay.h>
 #include <asm/coldfire.h>
index 32f808d157a15ee8a57f3a73645cc5024e054c90..8302376800c07da15b3c905a0b50baa3a8f9407b 100644 (file)
@@ -207,7 +207,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
                return;
        }
        if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
-               lh7a40xuart_stop_tx (port, 0);
+               lh7a40xuart_stop_tx (port);
                return;
        }
 
@@ -229,7 +229,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
                uart_write_wakeup (port);
 
        if (uart_circ_empty (xmit))
-               lh7a40xuart_stop_tx (port, 0);
+               lh7a40xuart_stop_tx (port);
 }
 
 static void lh7a40xuart_modem_status (struct uart_port* port)
index bb1db19598549ee10322f9d7ff0562f4f11cad2c..c466739428b2c501eb99c809f02226f55c7c9a76 100644 (file)
@@ -960,7 +960,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
                        intf->altsetting->desc.bInterfaceNumber);
 
        /* instance init */
-       instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
+       instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
        if (!instance) {
                dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
                return -ENOMEM;
index 9f44e83c6a6903f3dfb02a89088d1667cbe19812..12ecdb03ee5f20afd3bcef220e8aded0bb30857c 100644 (file)
@@ -1669,7 +1669,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 {
        struct usb_hcd *hcd;
 
-       hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
+       hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
        if (!hcd) {
                dev_dbg (dev, "hcd alloc failed\n");
                return NULL;
index b56f25864ed60084028e174e035c552bedc6a331..4c972b57c7c3a5ac1fd026269698f83375f4de1a 100644 (file)
@@ -638,7 +638,7 @@ iso_stream_alloc (unsigned mem_flags)
 {
        struct ehci_iso_stream *stream;
 
-       stream = kcalloc(1, sizeof *stream, mem_flags);
+       stream = kzalloc(sizeof *stream, mem_flags);
        if (likely (stream != NULL)) {
                INIT_LIST_HEAD(&stream->td_list);
                INIT_LIST_HEAD(&stream->free_list);
index 76cb496c5836ca3f222cbe688bf67fe2d6a2f1f7..75128c3718008a698cb0695c3eba0a0589bb2928 100644 (file)
@@ -717,7 +717,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
        }
        /* avoid all allocations within spinlocks: request or endpoint */
        if (!hep->hcpriv) {
-               ep = kcalloc(1, sizeof *ep, mem_flags);
+               ep = kzalloc(sizeof *ep, mem_flags);
                if (!ep)
                        return -ENOMEM;
        }
index 80eaf659c1984b0921acd9b956600bcdc0a5b348..d2a1fd40dfcb846e148faef3e9102142c2ba7cc6 100644 (file)
@@ -835,7 +835,7 @@ static int sl811h_urb_enqueue(
 
        /* avoid all allocations within spinlocks */
        if (!hep->hcpriv)
-               ep = kcalloc(1, sizeof *ep, mem_flags);
+               ep = kzalloc(sizeof *ep, mem_flags);
 
        spin_lock_irqsave(&sl811->lock, flags);
 
index 13532f3e3efc4325ea1c4b516d2045fad3cfd0d4..74f8760d7c07c0c689c7fa6fe5e0b50665b670c3 100644 (file)
@@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
        maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-       acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL);
+       acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
        if (!acecad)
                return -ENOMEM;
 
index 0dc439f10823a90f1d13bbe4d7658f4c441cf3f3..becb87efb869f6800b8c7829a5dcc71d0fbd8968 100644 (file)
@@ -166,7 +166,7 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
 
-       if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) {
+       if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) {
                err("%s - Out of memory.", __FUNCTION__);
                return -ENOMEM;
        }
index 25696386347812769419a5f2a870845c0f836b8d..acc71ec560e9578dec1f34dd88dc6d90b523b8f3 100644 (file)
@@ -263,7 +263,7 @@ int hid_pid_init(struct hid_device *hid)
        struct hid_ff_pid *private;
        struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
 
-       private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+       private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
        if (!private)
                return -ENOMEM;
 
index 9aae884475beab045f67487866e085ad13539224..4af321fae3901a42c0e9b1473fb138d5ebfb696f 100644 (file)
@@ -3,3 +3,4 @@
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)  += corgi_bl.o
+obj-$(CONFIG_SHARP_LOCOMO)     += locomolcd.o
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
new file mode 100644 (file)
index 0000000..ada6e75
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Backlight control code for Sharp Zaurus SL-5500
+ *
+ * Copyright 2005 John Lenz <lenz@cs.wisc.edu>
+ * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
+ * GPL v2
+ *
+ * This driver assumes single CPU. That's okay, because collie is
+ * slightly old hardware, and noone is going to retrofit second CPU to
+ * old PDA.
+ */
+
+/* LCD power functions */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware/locomo.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch/collie.h>
+#else
+#include <asm/arch/poodle.h>
+#endif
+
+extern void (*sa1100fb_lcd_power)(int on);
+
+static struct locomo_dev *locomolcd_dev;
+
+static void locomolcd_on(int comadj)
+{
+       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+       mdelay(2);
+
+       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+       mdelay(2);
+
+       locomo_m62332_senddata(locomolcd_dev, comadj, 0);
+       mdelay(5);
+
+       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
+       mdelay(10);
+
+       /* TFTCRST | CPSOUT=0 | CPSEN */
+       locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
+
+       /* Set CPSD */
+       locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
+
+       /* TFTCRST | CPSOUT=0 | CPSEN */
+       locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
+       mdelay(10);
+
+       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
+}
+
+static void locomolcd_off(int comadj)
+{
+       /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
+       locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
+       mdelay(1);
+
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+       mdelay(110);
+
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+       mdelay(700);
+
+       /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
+       locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+}
+
+void locomolcd_power(int on)
+{
+       int comadj = 118;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       if (!locomolcd_dev) {
+               local_irq_restore(flags);
+               return;
+       }
+
+       /* read comadj */
+#ifdef CONFIG_MACH_POODLE
+       comadj = 118;
+#else
+       comadj = 128;
+#endif
+
+       if (on)
+               locomolcd_on(comadj);
+       else
+               locomolcd_off(comadj);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(locomolcd_power);
+
+static int poodle_lcd_probe(struct locomo_dev *dev)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       locomolcd_dev = dev;
+
+       /* the poodle_lcd_power function is called for the first time
+        * from fs_initcall, which is before locomo is activated.
+        * We need to recall poodle_lcd_power here*/
+#ifdef CONFIG_MACH_POODLE
+       locomolcd_power(1);
+#endif
+       local_irq_restore(flags);
+       return 0;
+}
+
+static int poodle_lcd_remove(struct locomo_dev *dev)
+{
+       unsigned long flags;
+       local_irq_save(flags);
+       locomolcd_dev = NULL;
+       local_irq_restore(flags);
+       return 0;
+}
+
+static struct locomo_driver poodle_lcd_driver = {
+       .drv = {
+               .name = "locomo-backlight",
+       },
+       .devid  = LOCOMO_DEVID_BACKLIGHT,
+       .probe  = poodle_lcd_probe,
+       .remove = poodle_lcd_remove,
+};
+
+static int __init poodle_lcd_init(void)
+{
+       int ret = locomo_driver_register(&poodle_lcd_driver);
+       if (ret) return ret;
+
+#ifdef CONFIG_SA1100_COLLIE
+       sa1100fb_lcd_power = locomolcd_power;
+#endif
+       return 0;
+}
+device_initcall(poodle_lcd_init);
+
index 71b69da0c40d761b36f1891f02b2448a1caac7de..162012bb9264edd2bb58af8b4d9b609e4b940697 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/q40_master.h>
 #include <linux/fb.h>
index adcda697ea60d537accf3c9f9fa5e93f6695b856..0030c071da8fd5409ebb1e3276ccb09fec4bbcd3 100644 (file)
@@ -5,9 +5,15 @@
  *
  * Copyright (C) 2002, ATI Corp.
  * Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton
  *
  * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
  *
+ * Generic platform support by Ian Molton <spyro@f2s.com>
+ * and Richard Purdie <rpurdie@rpsys.net>
+ *
+ * w32xx support by Ian Molton
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -21,7 +27,7 @@
 #include <linux/mm.h>
 #include <linux/device.h>
 #include <linux/string.h>
-#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <video/w100fb.h>
 /*
  * Prototypes
  */
-static void w100fb_save_buffer(void);
-static void w100fb_clear_buffer(void);
-static void w100fb_restore_buffer(void);
-static void w100fb_clear_screen(u32 mode, long int offset);
-static void w100_resume(void);
 static void w100_suspend(u32 mode);
-static void w100_init_qvga_rotation(u16 deg);
-static void w100_init_vga_rotation(u16 deg);
 static void w100_vsync(void);
-static void w100_init_sharp_lcd(u32 mode);
-static void w100_pwm_setup(void);
-static void w100_InitExtMem(u32 mode);
-static void w100_hw_init(void);
-static u16 w100_set_fastsysclk(u16 Freq);
-
-static void lcdtg_hw_init(u32 mode);
-static void lcdtg_lcd_change(u32 mode);
-static void lcdtg_resume(void);
-static void lcdtg_suspend(void);
-
-
-/* Register offsets & lengths */
-#define REMAPPED_FB_LEN   0x15ffff
-
-#define BITS_PER_PIXEL    16
+static void w100_hw_init(struct w100fb_par*);
+static void w100_pwm_setup(struct w100fb_par*);
+static void w100_init_clocks(struct w100fb_par*);
+static void w100_setup_memory(struct w100fb_par*);
+static void w100_init_lcd(struct w100fb_par*);
+static void w100_set_dispregs(struct w100fb_par*);
+static void w100_update_enable(void);
+static void w100_update_disable(void);
+static void calc_hsync(struct w100fb_par *par);
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
 
 /* Pseudo palette size */
 #define MAX_PALETTES      16
 
-/* for resolution change */
-#define LCD_MODE_INIT (-1)
-#define LCD_MODE_480    0
-#define LCD_MODE_320    1
-#define LCD_MODE_240    2
-#define LCD_MODE_640    3
-
-#define LCD_SHARP_QVGA 0
-#define LCD_SHARP_VGA  1
-
-#define LCD_MODE_PORTRAIT      0
-#define LCD_MODE_LANDSCAPE     1
-
 #define W100_SUSPEND_EXTMEM 0
 #define W100_SUSPEND_ALL    1
 
-/* General frame buffer data structures */
-struct w100fb_par {
-       u32 xres;
-       u32 yres;
-       int fastsysclk_mode;
-       int lcdMode;
-       int rotation_flag;
-       int blanking_flag;
-       int comadj;
-       int phadadj;
-};
-
-static struct w100fb_par *current_par;
+#define BITS_PER_PIXEL    16
 
 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
 static void *remapped_base;
 static void *remapped_regs;
 static void *remapped_fbuf;
 
-/* External Function */
-static void(*w100fb_ssp_send)(u8 adrs, u8 data);
+#define REMAPPED_FB_LEN   0x15ffff
+
+/* This is the offset in the w100's address space we map the current
+   framebuffer memory to. We use the position of external memory as
+   we can remap internal memory to there if external isn't present. */
+#define W100_FB_BASE MEM_EXT_BASE_VALUE
+
 
 /*
  * Sysfs functions
  */
-
-static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct w100fb_par *par=info->par;
 
-       return sprintf(buf, "%d\n",par->rotation_flag);
+       return sprintf(buf, "%d\n",par->flip);
 }
 
-static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       unsigned int rotate;
+       unsigned int flip;
        struct fb_info *info = dev_get_drvdata(dev);
        struct w100fb_par *par=info->par;
 
-       rotate = simple_strtoul(buf, NULL, 10);
+       flip = simple_strtoul(buf, NULL, 10);
+
+       if (flip > 0)
+               par->flip = 1;
+       else
+               par->flip = 0;
 
-       if (rotate > 0) par->rotation_flag = 1;
-       else par->rotation_flag = 0;
+       w100_update_disable();
+       w100_set_dispregs(par);
+       w100_update_enable();
 
-       if (par->lcdMode == LCD_MODE_320)
-               w100_init_qvga_rotation(par->rotation_flag ? 270 : 90);
-       else if (par->lcdMode == LCD_MODE_240)
-               w100_init_qvga_rotation(par->rotation_flag ? 180 : 0);
-       else if (par->lcdMode == LCD_MODE_640)
-               w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
-       else if (par->lcdMode == LCD_MODE_480)
-               w100_init_vga_rotation(par->rotation_flag ? 180 : 0);
+       calc_hsync(par);
 
        return count;
 }
 
-static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store);
+static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
 
 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       unsigned long param;
-       unsigned long regs;
+       unsigned long regs, param;
        regs = simple_strtoul(buf, NULL, 16);
        param = readl(remapped_regs + regs);
        printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
@@ -148,8 +118,7 @@ static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
 
 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       unsigned long regs;
-       unsigned long param;
+       unsigned long regs, param;
        sscanf(buf, "%lx %lx", &regs, &param);
 
        if (regs <= 0x2000) {
@@ -163,54 +132,56 @@ static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *att
 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
 
 
-static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct w100fb_par *par=info->par;
 
-       return sprintf(buf, "%d\n",par->fastsysclk_mode);
+       return sprintf(buf, "%d\n",par->fastpll_mode);
 }
 
-static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       int param;
        struct fb_info *info = dev_get_drvdata(dev);
        struct w100fb_par *par=info->par;
 
-       param = simple_strtoul(buf, NULL, 10);
-
-       if (param == 75) {
-               printk("Set fastsysclk %d\n", param);
-               par->fastsysclk_mode = param;
-               w100_set_fastsysclk(par->fastsysclk_mode);
-       } else if (param == 100) {
-               printk("Set fastsysclk %d\n", param);
-               par->fastsysclk_mode = param;
-               w100_set_fastsysclk(par->fastsysclk_mode);
+       if (simple_strtoul(buf, NULL, 10) > 0) {
+               par->fastpll_mode=1;
+               printk("w100fb: Using fast system clock (if possible)\n");
+       } else {
+               par->fastpll_mode=0;
+               printk("w100fb: Using normal system clock\n");
        }
+
+       w100_init_clocks(par);
+       calc_hsync(par);
+
        return count;
 }
 
-static DEVICE_ATTR(fastsysclk, 0644, fastsysclk_show, fastsysclk_store);
+static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
 
 /*
- * The touchscreen on this device needs certain information
- * from the video driver to function correctly. We export it here.
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
  */
-int w100fb_get_xres(void) {
-       return current_par->xres;
-}
+unsigned long w100fb_get_hsynclen(struct device *dev)
+{
+       struct fb_info *info = dev_get_drvdata(dev);
+       struct w100fb_par *par=info->par;
 
-int w100fb_get_blanking(void) {
-       return current_par->blanking_flag;
+       /* If display is blanked/suspended, hsync isn't active */
+       if (par->blanked)
+               return 0;
+       else
+               return par->hsync_len;
 }
+EXPORT_SYMBOL(w100fb_get_hsynclen);
 
-int w100fb_get_fastsysclk(void) {
-       return current_par->fastsysclk_mode;
+static void w100fb_clear_screen(struct w100fb_par *par)
+{
+       memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
 }
-EXPORT_SYMBOL(w100fb_get_xres);
-EXPORT_SYMBOL(w100fb_get_blanking);
-EXPORT_SYMBOL(w100fb_get_fastsysclk);
 
 
 /*
@@ -234,7 +205,6 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
         * according to the RGB bitfield information.
         */
        if (regno < MAX_PALETTES) {
-
                u32 *pal = info->pseudo_palette;
 
                val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -250,115 +220,90 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  */
 static int w100fb_blank(int blank_mode, struct fb_info *info)
 {
-       struct w100fb_par *par;
-       par=info->par;
+       struct w100fb_par *par = info->par;
+       struct w100_tg_info *tg = par->mach->tg;
 
        switch(blank_mode) {
 
-       case FB_BLANK_NORMAL: /* Normal blanking */
-       case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-       case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-       case FB_BLANK_POWERDOWN: /* Poweroff */
-               if (par->blanking_flag == 0) {
-                       w100fb_save_buffer();
-                       lcdtg_suspend();
-                       par->blanking_flag = 1;
+       case FB_BLANK_NORMAL:         /* Normal blanking */
+       case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
+       case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
+       case FB_BLANK_POWERDOWN:      /* Poweroff */
+               if (par->blanked == 0) {
+                       if(tg && tg->suspend)
+                               tg->suspend(par);
+                       par->blanked = 1;
                }
                break;
 
        case FB_BLANK_UNBLANK: /* Unblanking */
-               if (par->blanking_flag != 0) {
-                       w100fb_restore_buffer();
-                       lcdtg_resume();
-                       par->blanking_flag = 0;
+               if (par->blanked != 0) {
+                       if(tg && tg->resume)
+                               tg->resume(par);
+                       par->blanked = 0;
                }
                break;
        }
        return 0;
 }
 
+
 /*
  *  Change the resolution by calling the appropriate hardware functions
  */
-static void w100fb_changeres(int rotate_mode, u32 mode)
+static void w100fb_activate_var(struct w100fb_par *par)
 {
-       u16 rotation=0;
-
-       switch(rotate_mode) {
-       case LCD_MODE_LANDSCAPE:
-               rotation=(current_par->rotation_flag ? 270 : 90);
-               break;
-       case LCD_MODE_PORTRAIT:
-               rotation=(current_par->rotation_flag ? 180 : 0);
-               break;
-       }
+       struct w100_tg_info *tg = par->mach->tg;
 
-       w100_pwm_setup();
-       switch(mode) {
-       case LCD_SHARP_QVGA:
-               w100_vsync();
-               w100_suspend(W100_SUSPEND_EXTMEM);
-               w100_init_sharp_lcd(LCD_SHARP_QVGA);
-               w100_init_qvga_rotation(rotation);
-               w100_InitExtMem(LCD_SHARP_QVGA);
-               w100fb_clear_screen(LCD_SHARP_QVGA, 0);
-               lcdtg_lcd_change(LCD_SHARP_QVGA);
-               break;
-       case LCD_SHARP_VGA:
-               w100fb_clear_screen(LCD_SHARP_QVGA, 0);
-               writel(0xBFFFA000, remapped_regs + mmMC_EXT_MEM_LOCATION);
-               w100_InitExtMem(LCD_SHARP_VGA);
-               w100fb_clear_screen(LCD_SHARP_VGA, 0x200000);
-               w100_vsync();
-               w100_init_sharp_lcd(LCD_SHARP_VGA);
-               if (rotation != 0)
-                       w100_init_vga_rotation(rotation);
-               lcdtg_lcd_change(LCD_SHARP_VGA);
-               break;
-       }
+       w100_pwm_setup(par);
+       w100_setup_memory(par);
+       w100_init_clocks(par);
+       w100fb_clear_screen(par);
+       w100_vsync();
+
+       w100_update_disable();
+       w100_init_lcd(par);
+       w100_set_dispregs(par);
+       w100_update_enable();
+
+       calc_hsync(par);
+
+       if (!par->blanked && tg && tg->change)
+               tg->change(par);
 }
 
-/*
- * Set up the display for the fb subsystem
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
  */
-static void w100fb_activate_var(struct fb_info *info)
+static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
 {
-       u32 temp32;
-       struct w100fb_par *par=info->par;
-       struct fb_var_screeninfo *var = &info->var;
+       struct w100_mode *mode = NULL;
+       struct w100_mode *modelist = par->mach->modelist;
+       unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+       unsigned int i;
+
+       for (i = 0 ; i < par->mach->num_modes ; i++) {
+               if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
+                               modelist[i].xres < best_x && modelist[i].yres < best_y) {
+                       best_x = modelist[i].xres;
+                       best_y = modelist[i].yres;
+                       mode = &modelist[i];
+               } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
+                       modelist[i].xres < best_y && modelist[i].yres < best_x) {
+                       best_x = modelist[i].yres;
+                       best_y = modelist[i].xres;
+                       mode = &modelist[i];
+               }
+       }
 
-       /* Set the hardware to 565 */
-       temp32 = readl(remapped_regs + mmDISP_DEBUG2);
-       temp32 &= 0xff7fffff;
-       temp32 |= 0x00800000;
-       writel(temp32, remapped_regs + mmDISP_DEBUG2);
+       if (mode && saveval) {
+               *x = best_x;
+               *y = best_y;
+       }
 
-       if (par->lcdMode == LCD_MODE_INIT) {
-               w100_init_sharp_lcd(LCD_SHARP_VGA);
-               w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
-               par->lcdMode = LCD_MODE_640;
-               lcdtg_hw_init(LCD_SHARP_VGA);
-       } else if (var->xres == 320 && var->yres == 240) {
-               if (par->lcdMode != LCD_MODE_320) {
-                       w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_QVGA);
-                       par->lcdMode = LCD_MODE_320;
-               }
-       } else if (var->xres == 240 && var->yres == 320) {
-               if (par->lcdMode != LCD_MODE_240) {
-                       w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_QVGA);
-                       par->lcdMode = LCD_MODE_240;
-               }
-       } else if (var->xres == 640 && var->yres == 480) {
-               if (par->lcdMode != LCD_MODE_640) {
-                       w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_VGA);
-                       par->lcdMode = LCD_MODE_640;
-               }
-       } else if (var->xres == 480 && var->yres == 640) {
-               if (par->lcdMode != LCD_MODE_480) {
-                       w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_VGA);
-                       par->lcdMode = LCD_MODE_480;
-               }
-       } else printk(KERN_ERR "W100FB: Resolution error!\n");
+       return mode;
 }
 
 
@@ -366,31 +311,19 @@ static void w100fb_activate_var(struct fb_info *info)
  *  w100fb_check_var():
  *  Get the video params out of 'var'. If a value doesn't fit, round it up,
  *  if it's too big, return -EINVAL.
- *
  */
 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-       if (var->xres < var->yres) { /* Portrait mode */
-               if ((var->xres > 480) || (var->yres > 640)) {
-                       return -EINVAL;
-               } else if ((var->xres > 240) || (var->yres > 320)) {
-                       var->xres = 480;
-                       var->yres = 640;
-               } else {
-                       var->xres = 240;
-                       var->yres = 320;
-               }
-       } else { /* Landscape mode */
-               if ((var->xres > 640) || (var->yres > 480)) {
-                       return -EINVAL;
-               } else if ((var->xres > 320) || (var->yres > 240)) {
-                       var->xres = 640;
-                       var->yres = 480;
-               } else {
-                       var->xres = 320;
-                       var->yres = 240;
-               }
-       }
+       struct w100fb_par *par=info->par;
+
+       if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
+               return -EINVAL;
+
+       if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
+               return -EINVAL;
+
+       if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
+               return -EINVAL;
 
        var->xres_virtual = max(var->xres_virtual, var->xres);
        var->yres_virtual = max(var->yres_virtual, var->yres);
@@ -409,13 +342,11 @@ static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        var->transp.offset = var->transp.length = 0;
 
        var->nonstd = 0;
-
        var->height = -1;
        var->width = -1;
        var->vmode = FB_VMODE_NONINTERLACED;
-
        var->sync = 0;
-       var->pixclock = 0x04;   /* 171521; */
+       var->pixclock = 0x04;  /* 171521; */
 
        return 0;
 }
@@ -430,274 +361,286 @@ static int w100fb_set_par(struct fb_info *info)
 {
        struct w100fb_par *par=info->par;
 
-       par->xres = info->var.xres;
-       par->yres = info->var.yres;
-
-       info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-       info->fix.ypanstep = 0;
-       info->fix.ywrapstep = 0;
+       if (par->xres != info->var.xres || par->yres != info->var.yres) {
+               par->xres = info->var.xres;
+               par->yres = info->var.yres;
+               par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
 
-       if (par->blanking_flag)
-               w100fb_clear_buffer();
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               info->fix.ypanstep = 0;
+               info->fix.ywrapstep = 0;
+               info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
 
-       w100fb_activate_var(info);
+               if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
+                       par->extmem_active = 1;
+                       info->fix.smem_len = par->mach->mem->size+1;
+               } else {
+                       par->extmem_active = 0;
+                       info->fix.smem_len = MEM_INT_SIZE+1;
+               }
 
-       if (par->lcdMode == LCD_MODE_480) {
-               info->fix.line_length = (480 * BITS_PER_PIXEL) / 8;
-               info->fix.smem_len = 0x200000;
-       } else if (par->lcdMode == LCD_MODE_320) {
-               info->fix.line_length = (320 * BITS_PER_PIXEL) / 8;
-               info->fix.smem_len = 0x60000;
-       } else if (par->lcdMode == LCD_MODE_240) {
-               info->fix.line_length = (240 * BITS_PER_PIXEL) / 8;
-               info->fix.smem_len = 0x60000;
-       } else if (par->lcdMode == LCD_MODE_INIT || par->lcdMode == LCD_MODE_640) {
-               info->fix.line_length = (640 * BITS_PER_PIXEL) / 8;
-               info->fix.smem_len = 0x200000;
+               w100fb_activate_var(par);
        }
-
        return 0;
 }
 
 
 /*
- *      Frame buffer operations
+ *  Frame buffer operations
  */
 static struct fb_ops w100fb_ops = {
-       .owner = THIS_MODULE,
+       .owner        = THIS_MODULE,
        .fb_check_var = w100fb_check_var,
-       .fb_set_par = w100fb_set_par,
+       .fb_set_par   = w100fb_set_par,
        .fb_setcolreg = w100fb_setcolreg,
-       .fb_blank = w100fb_blank,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
+       .fb_blank     = w100fb_blank,
+       .fb_fillrect  = cfb_fillrect,
+       .fb_copyarea  = cfb_copyarea,
        .fb_imageblit = cfb_imageblit,
-       .fb_cursor = soft_cursor,
+       .fb_cursor    = soft_cursor,
 };
 
-
-static void w100fb_clear_screen(u32 mode, long int offset)
+#ifdef CONFIG_PM
+static void w100fb_save_vidmem(struct w100fb_par *par)
 {
-       int i, numPix = 0;
-
-       if (mode == LCD_SHARP_VGA)
-               numPix = 640 * 480;
-       else if (mode == LCD_SHARP_QVGA)
-               numPix = 320 * 240;
+       int memsize;
 
-       for (i = 0; i < numPix; i++)
-               writew(0xffff, remapped_fbuf + offset + (2*i));
-}
-
-
-/* Need to split up the buffers to stay within the limits of kmalloc */
-#define W100_BUF_NUM   6
-static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL };
-
-static void w100fb_save_buffer(void)
-{
-       int i, j, bufsize;
-
-       bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
-       for (i = 0; i < W100_BUF_NUM; i++) {
-               if (gSaveImagePtr[i] == NULL)
-                       gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL);
-               if (gSaveImagePtr[i] == NULL) {
-                       w100fb_clear_buffer();
-                       printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i);
-                       break;
-               }
-               for (j = 0; j < bufsize/4; j++)
-                       *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4);
+       if (par->extmem_active) {
+               memsize=par->mach->mem->size;
+               par->saved_extmem = vmalloc(memsize);
+               if (par->saved_extmem)
+                       memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
        }
+       memsize=MEM_INT_SIZE;
+       par->saved_intmem = vmalloc(memsize);
+       if (par->saved_intmem && par->extmem_active)
+               memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
+       else if (par->saved_intmem)
+               memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
 }
 
-
-static void w100fb_restore_buffer(void)
+static void w100fb_restore_vidmem(struct w100fb_par *par)
 {
-       int i, j, bufsize;
+       int memsize;
 
-       bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
-       for (i = 0; i < W100_BUF_NUM; i++) {
-               if (gSaveImagePtr[i] == NULL) {
-                       printk(KERN_WARNING "can't find pre-off image buffer %d\n", i);
-                       w100fb_clear_buffer();
-                       break;
-               }
-               for (j = 0; j < (bufsize/4); j++)
-                       writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4));
-               kfree(gSaveImagePtr[i]);
-               gSaveImagePtr[i] = NULL;
+       if (par->extmem_active && par->saved_extmem) {
+               memsize=par->mach->mem->size;
+               memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
+               vfree(par->saved_extmem);
        }
-}
-
-
-static void w100fb_clear_buffer(void)
-{
-       int i;
-       for (i = 0; i < W100_BUF_NUM; i++) {
-               kfree(gSaveImagePtr[i]);
-               gSaveImagePtr[i] = NULL;
+       if (par->saved_intmem) {
+               memsize=MEM_INT_SIZE;
+               if (par->extmem_active)
+                       memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
+               else
+                       memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
+               vfree(par->saved_intmem);
        }
 }
 
-
-#ifdef CONFIG_PM
-static int w100fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level)
 {
        if (level == SUSPEND_POWER_DOWN) {
                struct fb_info *info = dev_get_drvdata(dev);
                struct w100fb_par *par=info->par;
+               struct w100_tg_info *tg = par->mach->tg;
 
-               w100fb_save_buffer();
-               lcdtg_suspend();
+               w100fb_save_vidmem(par);
+               if(tg && tg->suspend)
+                       tg->suspend(par);
                w100_suspend(W100_SUSPEND_ALL);
-               par->blanking_flag = 1;
+               par->blanked = 1;
        }
        return 0;
 }
 
-static int w100fb_resume(struct device *dev, u32 level)
+static int w100fb_resume(struct device *dev, uint32_t level)
 {
        if (level == RESUME_POWER_ON) {
                struct fb_info *info = dev_get_drvdata(dev);
                struct w100fb_par *par=info->par;
-
-               w100_resume();
-               w100fb_restore_buffer();
-               lcdtg_resume();
-               par->blanking_flag = 0;
+               struct w100_tg_info *tg = par->mach->tg;
+
+               w100_hw_init(par);
+               w100fb_activate_var(par);
+               w100fb_restore_vidmem(par);
+               if(tg && tg->resume)
+                       tg->resume(par);
+               par->blanked = 0;
        }
        return 0;
 }
 #else
-#define w100fb_suspend NULL
-#define w100fb_resume  NULL
+#define w100fb_suspend  NULL
+#define w100fb_resume   NULL
 #endif
 
 
 int __init w100fb_probe(struct device *dev)
 {
+       int err = -EIO;
        struct w100fb_mach_info *inf;
-       struct fb_info *info;
+       struct fb_info *info = NULL;
        struct w100fb_par *par;
        struct platform_device *pdev = to_platform_device(dev);
        struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       unsigned int chip_id;
 
        if (!mem)
                return -EINVAL;
 
-       /* remap the areas we're going to use */
+       /* Remap the chip base address */
        remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
        if (remapped_base == NULL)
-               return -EIO;
+               goto out;
 
+       /* Map the register space */
        remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
-       if (remapped_regs == NULL) {
-               iounmap(remapped_base);
-               return -EIO;
+       if (remapped_regs == NULL)
+               goto out;
+
+       /* Identify the chip */
+       printk("Found ");
+       chip_id = readl(remapped_regs + mmCHIP_ID);
+       switch(chip_id) {
+               case CHIP_ID_W100:  printk("w100");  break;
+               case CHIP_ID_W3200: printk("w3200"); break;
+               case CHIP_ID_W3220: printk("w3220"); break;
+               default:
+                       printk("Unknown imageon chip ID\n");
+                       err = -ENODEV;
+                       goto out;
        }
+       printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
 
-       remapped_fbuf = ioremap_nocache(mem->start+MEM_EXT_BASE_VALUE, REMAPPED_FB_LEN);
-       if (remapped_fbuf == NULL) {
-               iounmap(remapped_base);
-               iounmap(remapped_regs);
-               return -EIO;
-       }
+       /* Remap the framebuffer */
+       remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
+       if (remapped_fbuf == NULL)
+               goto out;
 
        info=framebuffer_alloc(sizeof(struct w100fb_par), dev);
        if (!info) {
-               iounmap(remapped_base);
-               iounmap(remapped_regs);
-               iounmap(remapped_fbuf);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out;
        }
 
-       info->device=dev;
        par = info->par;
-       current_par=info->par;
        dev_set_drvdata(dev, info);
 
        inf = dev->platform_data;
-       par->phadadj = inf->phadadj;
-       par->comadj = inf->comadj;
-       par->fastsysclk_mode = 75;
-       par->lcdMode = LCD_MODE_INIT;
-       par->rotation_flag=0;
-       par->blanking_flag=0;
-       w100fb_ssp_send = inf->w100fb_ssp_send;
-
-       w100_hw_init();
-       w100_pwm_setup();
+       par->chip_id = chip_id;
+       par->mach = inf;
+       par->fastpll_mode = 0;
+       par->blanked = 0;
+
+       par->pll_table=w100_get_xtal_table(inf->xtal_freq);
+       if (!par->pll_table) {
+               printk(KERN_ERR "No matching Xtal definition found\n");
+               err = -EINVAL;
+               goto out;
+       }
 
        info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
        if (!info->pseudo_palette) {
-               iounmap(remapped_base);
-               iounmap(remapped_regs);
-               iounmap(remapped_fbuf);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out;
        }
 
        info->fbops = &w100fb_ops;
        info->flags = FBINFO_DEFAULT;
        info->node = -1;
-       info->screen_base = remapped_fbuf;
+       info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
        info->screen_size = REMAPPED_FB_LEN;
 
-       info->var.xres = 640;
+       strcpy(info->fix.id, "w100fb");
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.type_aux = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+       info->fix.smem_start = mem->start+W100_FB_BASE;
+       info->fix.mmio_start = mem->start+W100_REG_BASE;
+       info->fix.mmio_len = W100_REG_LEN;
+
+       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       par->mode = &inf->modelist[0];
+       if(inf->init_mode & INIT_MODE_ROTATED) {
+               info->var.xres = par->mode->yres;
+               info->var.yres = par->mode->xres;
+       }
+       else {
+               info->var.xres = par->mode->xres;
+               info->var.yres = par->mode->yres;
+       }
+
+       if(inf->init_mode &= INIT_MODE_FLIPPED)
+               par->flip = 1;
+       else
+               par->flip = 0;
+
        info->var.xres_virtual = info->var.xres;
-       info->var.yres = 480;
        info->var.yres_virtual = info->var.yres;
-       info->var.pixclock = 0x04;      /* 171521; */
+       info->var.pixclock = 0x04;  /* 171521; */
        info->var.sync = 0;
        info->var.grayscale = 0;
        info->var.xoffset = info->var.yoffset = 0;
        info->var.accel_flags = 0;
        info->var.activate = FB_ACTIVATE_NOW;
 
-       strcpy(info->fix.id, "w100fb");
-       info->fix.type = FB_TYPE_PACKED_PIXELS;
-       info->fix.type_aux = 0;
-       info->fix.accel = FB_ACCEL_NONE;
-       info->fix.smem_start = mem->start+MEM_EXT_BASE_VALUE;
-       info->fix.mmio_start = mem->start+W100_REG_BASE;
-       info->fix.mmio_len = W100_REG_LEN;
+       w100_hw_init(par);
+
+       if (w100fb_check_var(&info->var, info) < 0) {
+               err = -EINVAL;
+               goto out;
+       }
 
-       w100fb_check_var(&info->var, info);
        w100fb_set_par(info);
 
        if (register_framebuffer(info) < 0) {
-               kfree(info->pseudo_palette);
-               iounmap(remapped_base);
-               iounmap(remapped_regs);
-               iounmap(remapped_fbuf);
-               return -EINVAL;
+               err = -EINVAL;
+               goto out;
        }
 
-       device_create_file(dev, &dev_attr_fastsysclk);
+       device_create_file(dev, &dev_attr_fastpllclk);
        device_create_file(dev, &dev_attr_reg_read);
        device_create_file(dev, &dev_attr_reg_write);
-       device_create_file(dev, &dev_attr_rotation);
+       device_create_file(dev, &dev_attr_flip);
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
        return 0;
+out:
+       fb_dealloc_cmap(&info->cmap);
+       kfree(info->pseudo_palette);
+       if (remapped_fbuf != NULL)
+               iounmap(remapped_fbuf);
+       if (remapped_regs != NULL)
+               iounmap(remapped_regs);
+       if (remapped_base != NULL)
+               iounmap(remapped_base);
+       if (info)
+               framebuffer_release(info);
+       return err;
 }
 
 
 static int w100fb_remove(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
+       struct w100fb_par *par=info->par;
 
-       device_remove_file(dev, &dev_attr_fastsysclk);
+       device_remove_file(dev, &dev_attr_fastpllclk);
        device_remove_file(dev, &dev_attr_reg_read);
        device_remove_file(dev, &dev_attr_reg_write);
-       device_remove_file(dev, &dev_attr_rotation);
+       device_remove_file(dev, &dev_attr_flip);
 
        unregister_framebuffer(info);
 
-       w100fb_clear_buffer();
+       vfree(par->saved_intmem);
+       vfree(par->saved_extmem);
        kfree(info->pseudo_palette);
+       fb_dealloc_cmap(&info->cmap);
 
        iounmap(remapped_base);
        iounmap(remapped_regs);
@@ -721,10 +664,54 @@ static void w100_soft_reset(void)
        udelay(100);
 }
 
+static void w100_update_disable(void)
+{
+       union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+       /* Prevent display updates */
+       disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+       disp_db_buf_wr_cntl.f.update_db_buf = 0;
+       disp_db_buf_wr_cntl.f.en_db_buf = 0;
+       writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+static void w100_update_enable(void)
+{
+       union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+       /* Enable display updates */
+       disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+       disp_db_buf_wr_cntl.f.update_db_buf = 1;
+       disp_db_buf_wr_cntl.f.en_db_buf = 1;
+       writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+unsigned long w100fb_gpio_read(int port)
+{
+       unsigned long value;
+
+       if (port==W100_GPIO_PORT_A)
+               value = readl(remapped_regs + mmGPIO_DATA);
+       else
+               value = readl(remapped_regs + mmGPIO_DATA2);
+
+       return value;
+}
+
+void w100fb_gpio_write(int port, unsigned long value)
+{
+       if (port==W100_GPIO_PORT_A)
+               value = writel(value, remapped_regs + mmGPIO_DATA);
+       else
+               value = writel(value, remapped_regs + mmGPIO_DATA2);
+}
+EXPORT_SYMBOL(w100fb_gpio_read);
+EXPORT_SYMBOL(w100fb_gpio_write);
+
 /*
  * Initialization of critical w100 hardware
  */
-static void w100_hw_init(void)
+static void w100_hw_init(struct w100fb_par *par)
 {
        u32 temp32;
        union cif_cntl_u cif_cntl;
@@ -735,8 +722,8 @@ static void w100_hw_init(void)
        union cpu_defaults_u cpu_default;
        union cif_write_dbg_u cif_write_dbg;
        union wrap_start_dir_u wrap_start_dir;
-       union mc_ext_mem_location_u mc_ext_mem_loc;
        union cif_io_u cif_io;
+       struct w100_gpio_regs *gpio = par->mach->gpio;
 
        w100_soft_reset();
 
@@ -791,19 +778,6 @@ static void w100_hw_init(void)
        cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
        writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
 
-       /* This location is relative to internal w100 addresses */
-       writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
-
-       mc_ext_mem_loc.val = defMC_EXT_MEM_LOCATION;
-       mc_ext_mem_loc.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
-       mc_ext_mem_loc.f.mc_ext_mem_top = MEM_EXT_TOP_VALUE >> 8;
-       writel((u32) (mc_ext_mem_loc.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
-
-       if ((current_par->lcdMode == LCD_MODE_240) || (current_par->lcdMode == LCD_MODE_320))
-               w100_InitExtMem(LCD_SHARP_QVGA);
-       else
-               w100_InitExtMem(LCD_SHARP_VGA);
-
        wrap_start_dir.val = defWRAP_START_DIR;
        wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
        writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
@@ -813,21 +787,24 @@ static void w100_hw_init(void)
        writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
 
        writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
-}
 
+       /* Set the hardware to 565 colour */
+       temp32 = readl(remapped_regs + mmDISP_DEBUG2);
+       temp32 &= 0xff7fffff;
+       temp32 |= 0x00800000;
+       writel(temp32, remapped_regs + mmDISP_DEBUG2);
 
-/*
- * Types
- */
+       /* Initialise the GPIO lines */
+       if (gpio) {
+               writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
+               writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
+               writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
+               writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
+               writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
+               writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
+       }
+}
 
-struct pll_parm {
-       u16 freq;               /* desired Fout for PLL */
-       u8 M;
-       u8 N_int;
-       u8 N_fac;
-       u8 tfgoal;
-       u8 lock_time;
-};
 
 struct power_state {
        union clk_pin_cntl_u clk_pin_cntl;
@@ -835,317 +812,275 @@ struct power_state {
        union pll_cntl_u pll_cntl;
        union sclk_cntl_u sclk_cntl;
        union pclk_cntl_u pclk_cntl;
-       union clk_test_cntl_u clk_test_cntl;
        union pwrmgt_cntl_u pwrmgt_cntl;
-       u32 freq;               /* Fout for PLL calibration */
-       u8 tf100;               /* for pll calibration */
-       u8 tf80;                /* for pll calibration */
-       u8 tf20;                /* for pll calibration */
-       u8 M;                   /* for pll calibration */
-       u8 N_int;               /* for pll calibration */
-       u8 N_fac;               /* for pll calibration */
-       u8 lock_time;   /* for pll calibration */
-       u8 tfgoal;              /* for pll calibration */
-       u8 auto_mode;   /* hardware auto switch? */
-       u8 pwm_mode;            /* 0 fast, 1 normal/slow */
-       u16 fast_sclk;  /* fast clk freq */
-       u16 norm_sclk;  /* slow clk freq */
+       int auto_mode;  /* system clock auto changing? */
 };
 
 
-/*
- * Global state variables
- */
-
 static struct power_state w100_pwr_state;
 
-/* This table is specific for 12.5MHz ref crystal.  */
-static struct pll_parm gPLLTable[] = {
-    /*freq     M   N_int    N_fac  tfgoal  lock_time */
-    { 50,      0,   1,       0,     0xE0,        56}, /*  50.00 MHz */
-    { 75,      0,   5,       0,     0xDE,           37}, /*  75.00 MHz */
-    {100,      0,   7,       0,     0xE0,        28}, /* 100.00 MHz */
-    {125,      0,   9,       0,     0xE0,        22}, /* 125.00 MHz */
-    {150,      0,   11,      0,     0xE0,        17}, /* 150.00 MHz */
-    {  0,      0,   0,       0,        0,         0}  /* Terminator */
+/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
+
+/* 12.5MHz Crystal PLL Table */
+static struct w100_pll_info xtal_12500000[] = {
+       /*freq     M   N_int    N_fac  tfgoal  lock_time */
+       { 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
+       { 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
+       {100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
+       {125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
+       {150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
+       {  0,      0,   0,       0,        0,         0},  /* Terminator */
 };
 
+/* 14.318MHz Crystal PLL Table */
+static struct w100_pll_info xtal_14318000[] = {
+       /*freq     M   N_int    N_fac  tfgoal  lock_time */
+       { 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
+       { 50,      1,   6,       0,     0xe0,        64}, /*  50.05 MHz */
+       { 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
+       { 75,      0,   4,       3,     0xe0,        43}, /*  75.08 MHz */
+       {100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
+       {  0,      0,   0,       0,        0,         0},
+};
 
-static u8 w100_pll_get_testcount(u8 testclk_sel)
+/* 16MHz Crystal PLL Table */
+static struct w100_pll_info xtal_16000000[] = {
+       /*freq     M   N_int    N_fac  tfgoal  lock_time */
+       { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
+       { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
+       { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
+       {  0,      0,   0,       0,        0,         0},
+};
+
+static struct pll_entries {
+       int xtal_freq;
+       struct w100_pll_info *pll_table;
+} w100_pll_tables[] = {
+       { 12500000, &xtal_12500000[0] },
+       { 14318000, &xtal_14318000[0] },
+       { 16000000, &xtal_16000000[0] },
+       { 0 },
+};
+
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
 {
+       struct pll_entries *pll_entry = w100_pll_tables;
+
+       do {
+               if (freq == pll_entry->xtal_freq)
+                       return pll_entry->pll_table;
+               pll_entry++;
+       } while (pll_entry->xtal_freq);
+       return 0;
+}
+
+
+static unsigned int w100_get_testcount(unsigned int testclk_sel)
+{
+       union clk_test_cntl_u clk_test_cntl;
+
        udelay(5);
 
-       w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
-       w100_pwr_state.clk_test_cntl.f.testclk_sel = testclk_sel;
-       w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x1;      /*reset test count */
-       writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-       w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
-       writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+       /* Select the test clock source and reset */
+       clk_test_cntl.f.start_check_freq = 0x0;
+       clk_test_cntl.f.testclk_sel = testclk_sel;
+       clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
+       writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
 
-       w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x1;
-       writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+       clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
+       writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
 
+       /* Run clock test */
+       clk_test_cntl.f.start_check_freq = 0x1;
+       writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+       /* Give the test time to complete */
        udelay(20);
 
-       w100_pwr_state.clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
-       w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
-       writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+       /* Return the result */
+       clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
+       clk_test_cntl.f.start_check_freq = 0x0;
+       writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
 
-       return w100_pwr_state.clk_test_cntl.f.test_count;
+       return clk_test_cntl.f.test_count;
 }
 
 
-static u8 w100_pll_adjust(void)
+static int w100_pll_adjust(struct w100_pll_info *pll)
 {
+       unsigned int tf80;
+       unsigned int tf20;
+
+       /* Initial Settings */
+       w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
+       w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
+       w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
+       w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
+       w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
+       w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
+       w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
+
+       /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
+        * therefore, commented out the following lines
+        * tf80 meant tf100
+        */
        do {
-               /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
-                * therefore, commented out the following lines
-                * tf80 meant tf100
-                * set VCO input = 0.8 * VDD
-                */
+               /* set VCO input = 0.8 * VDD */
                w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
                writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-               w100_pwr_state.tf80 = w100_pll_get_testcount(0x1);      /* PLLCLK */
-               if (w100_pwr_state.tf80 >= (w100_pwr_state.tfgoal)) {
+               tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
+               if (tf80 >= (pll->tfgoal)) {
                        /* set VCO input = 0.2 * VDD */
                        w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
                        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-                       w100_pwr_state.tf20 = w100_pll_get_testcount(0x1);      /* PLLCLK */
-                       if (w100_pwr_state.tf20 <= (w100_pwr_state.tfgoal))
-                               return 1; // Success
+                       tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
+                       if (tf20 <= (pll->tfgoal))
+                               return 1;  /* Success */
 
                        if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
-                           ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
-                            (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
+                               ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
+                               (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
                                /* slow VCO config */
                                w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
                                w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
                                w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
-                               writel((u32) (w100_pwr_state.pll_cntl.val),
-                                       remapped_regs + mmPLL_CNTL);
                                continue;
                        }
                }
                if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
                        w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
-                       writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-                       continue;
-               }
-               if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
+               } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
                        w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
                        w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
-                       writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-                       continue;
+               } else {
+                       return 0;  /* Error */
                }
-               return 0; // error
        } while(1);
 }
 
 
 /*
  * w100_pll_calibration
- *                freq = target frequency of the PLL
- *                (note: crystal = 14.3MHz)
  */
-static u8 w100_pll_calibration(u32 freq)
+static int w100_pll_calibration(struct w100_pll_info *pll)
 {
-       u8 status;
-
-       /* initial setting */
-       w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;               /* power down */
-       w100_pwr_state.pll_cntl.f.pll_reset = 0x0;              /* not reset */
-       w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;     /* Hi-Z */
-       w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;                /* VCO gain = 0 */
-       w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;              /* VCO frequency range control = off */
-       w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;    /* current offset inside VCO = 0 */
-       w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
-       writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+       int status;
 
-       /* check for (tf80 >= tfgoal) && (tf20 =< tfgoal) */
-       if ((w100_pwr_state.tf80 < w100_pwr_state.tfgoal) || (w100_pwr_state.tf20 > w100_pwr_state.tfgoal)) {
-               status=w100_pll_adjust();
-       }
-       /* PLL Reset And Lock */
+       status = w100_pll_adjust(pll);
 
+       /* PLL Reset And Lock */
        /* set VCO input = 0.5 * VDD */
        w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-       /* reset time */
-       udelay(1);
+       udelay(1);  /* reset time */
 
        /* enable charge pump */
-       w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;     /* normal */
+       w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-       /* set VCO input = Hi-Z */
-       /* disable DAC */
+       /* set VCO input = Hi-Z, disable DAC */
        w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-       /* lock time */
-       udelay(400);    /* delay 400 us */
+       udelay(400);  /* lock time */
 
        /* PLL locked */
 
-       w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x1;  /* PLL clock */
-       writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
-       w100_pwr_state.tf100 = w100_pll_get_testcount(0x1);     /* PLLCLK */
-
        return status;
 }
 
 
-static u8 w100_pll_set_clk(void)
+static int w100_pll_set_clk(struct w100_pll_info *pll)
 {
-       u8 status;
+       int status;
 
-       if (w100_pwr_state.auto_mode == 1)      /* auto mode */
+       if (w100_pwr_state.auto_mode == 1)  /* auto mode */
        {
-               w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
-               w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
+               w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
+               w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
                writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
        }
 
-       w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0;  /* crystal clock */
+       /* Set system clock source to XTAL whilst adjusting the PLL! */
+       w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
        writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
 
-       w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = w100_pwr_state.M;
-       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = w100_pwr_state.N_int;
-       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = w100_pwr_state.N_fac;
-       w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = w100_pwr_state.lock_time;
+       w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
+       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
+       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
+       w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
        writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
 
        w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
        writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
 
-       status = w100_pll_calibration (w100_pwr_state.freq);
+       status = w100_pll_calibration(pll);
 
-       if (w100_pwr_state.auto_mode == 1)      /* auto mode */
+       if (w100_pwr_state.auto_mode == 1)  /* auto mode */
        {
-               w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
-               w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast  */
+               w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
+               w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
                writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
        }
        return status;
 }
 
-
-/* assume reference crystal clk is 12.5MHz,
- * and that doubling is not enabled.
- *
- * Freq = 12 == 12.5MHz.
- */
-static u16 w100_set_slowsysclk(u16 freq)
-{
-       if (w100_pwr_state.norm_sclk == freq)
-               return freq;
-
-       if (w100_pwr_state.auto_mode == 1)      /* auto mode */
-               return 0;
-
-       if (freq == 12) {
-               w100_pwr_state.norm_sclk = freq;
-               w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;    /* Pslow = 1 */
-               w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0;  /* crystal src */
-
-               writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
-               w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x1;
-               writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
-
-               w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x1;
-               w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;
-               writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
-               w100_pwr_state.pwm_mode = 1;    /* normal mode */
-               return freq;
-       } else
-               return 0;
-}
-
-
-static u16 w100_set_fastsysclk(u16 freq)
+/* freq = target frequency of the PLL */
+static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
 {
-       u16 pll_freq;
-       int i;
-
-       while(1) {
-               pll_freq = (u16) (freq * (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast + 1));
-               i = 0;
-               do {
-                       if (pll_freq == gPLLTable[i].freq) {
-                               w100_pwr_state.freq = gPLLTable[i].freq * 1000000;
-                               w100_pwr_state.M = gPLLTable[i].M;
-                               w100_pwr_state.N_int = gPLLTable[i].N_int;
-                               w100_pwr_state.N_fac = gPLLTable[i].N_fac;
-                               w100_pwr_state.tfgoal = gPLLTable[i].tfgoal;
-                               w100_pwr_state.lock_time = gPLLTable[i].lock_time;
-                               w100_pwr_state.tf20 = 0xff;     /* set highest */
-                               w100_pwr_state.tf80 = 0x00;     /* set lowest */
-
-                               w100_pll_set_clk();
-                               w100_pwr_state.pwm_mode = 0;    /* fast mode */
-                               w100_pwr_state.fast_sclk = freq;
-                               return freq;
-                       }
-                       i++;
-               } while(gPLLTable[i].freq);
+       struct w100_pll_info *pll = par->pll_table;
 
-               if (w100_pwr_state.auto_mode == 1)
-                       break;
-
-               if (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast == 0)
-                       break;
-
-               w100_pwr_state.sclk_cntl.f.sclk_post_div_fast -= 1;
-               writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-       }
+       do {
+               if (freq == pll->freq) {
+                       return w100_pll_set_clk(pll);
+               }
+               pll++;
+       } while(pll->freq);
        return 0;
 }
 
-
 /* Set up an initial state.  Some values/fields set
    here will be overwritten. */
-static void w100_pwm_setup(void)
+static void w100_pwm_setup(struct w100fb_par *par)
 {
        w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
        w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
        w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
        w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
-       w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = 0x0;      /* no freq doubling */
+       w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
        w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
        writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
 
-       w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0;  /* Crystal Clk */
-       w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;    /* Pfast = 1 */
+       w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
+       w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
        w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
-       w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;    /* Pslow = 1 */
+       w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
        w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
-       w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;        /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;       /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;      /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;       /* Dynamic */
-       w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;       /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
+       w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
        w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
        w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
        w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
        w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
        writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
 
-       w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x0;  /* Crystal Clk */
-       w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
-       w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;       /* Dynamic */
+       w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
+       w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
+       w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
        writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
 
-       w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;      /* M = 1 */
-       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;   /* N = 1.0 */
+       w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
+       w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
        w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
        w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
        w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
@@ -1154,7 +1089,7 @@ static void w100_pwm_setup(void)
        w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
        w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
        w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
-       w100_pwr_state.pll_cntl.f.pll_mode = 0x0;       /* uses VCO clock */
+       w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
        w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
        w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
        w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
@@ -1164,220 +1099,275 @@ static void w100_pwm_setup(void)
        w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
        w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
        w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
-       w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;     /* Hi-Z */
+       w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
        w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
        w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
        w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
        w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
 
-       w100_pwr_state.clk_test_cntl.f.testclk_sel = 0x1;       /* PLLCLK (for testing) */
-       w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
-       w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
-       writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
        w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
-       w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;        /* normal mode (0, 1, 3) */
+       w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
        w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
        w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
        w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
-       w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
-       w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
+       w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
+       w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
        w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
        w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
        writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
 
-       w100_pwr_state.auto_mode = 0;   /* manual mode */
-       w100_pwr_state.pwm_mode = 1;    /* normal mode (0, 1, 2) */
-       w100_pwr_state.freq = 50000000; /* 50 MHz */
-       w100_pwr_state.M = 3;   /* M = 4 */
-       w100_pwr_state.N_int = 6;       /* N = 7.0 */
-       w100_pwr_state.N_fac = 0;
-       w100_pwr_state.tfgoal = 0xE0;
-       w100_pwr_state.lock_time = 56;
-       w100_pwr_state.tf20 = 0xff;     /* set highest */
-       w100_pwr_state.tf80 = 0x00;     /* set lowest */
-       w100_pwr_state.tf100 = 0x00;    /* set lowest */
-       w100_pwr_state.fast_sclk = 50;  /* 50.0 MHz */
-       w100_pwr_state.norm_sclk = 12;  /* 12.5 MHz */
+       w100_pwr_state.auto_mode = 0;  /* manual mode */
 }
 
 
-static void w100_init_sharp_lcd(u32 mode)
+/*
+ * Setup the w100 clocks for the specified mode
+ */
+static void w100_init_clocks(struct w100fb_par *par)
 {
-       u32 temp32;
-       union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+       struct w100_mode *mode = par->mode;
 
-       /* Prevent display updates */
-       disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
-       disp_db_buf_wr_cntl.f.update_db_buf = 0;
-       disp_db_buf_wr_cntl.f.en_db_buf = 0;
-       writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+       if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
+               w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
 
-       switch(mode) {
-       case LCD_SHARP_QVGA:
-               w100_set_slowsysclk(12);        /* use crystal -- 12.5MHz */
-               /* not use PLL */
-
-               writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
-               writel(0x85FF8000, remapped_regs + mmMC_FB_LOCATION);
-               writel(0x00000003, remapped_regs + mmLCD_FORMAT);
-               writel(0x00CF1C06, remapped_regs + mmGRAPHIC_CTRL);
-               writel(0x01410145, remapped_regs + mmCRTC_TOTAL);
-               writel(0x01170027, remapped_regs + mmACTIVE_H_DISP);
-               writel(0x01410001, remapped_regs + mmACTIVE_V_DISP);
-               writel(0x01170027, remapped_regs + mmGRAPHIC_H_DISP);
-               writel(0x01410001, remapped_regs + mmGRAPHIC_V_DISP);
-               writel(0x81170027, remapped_regs + mmCRTC_SS);
-               writel(0xA0140000, remapped_regs + mmCRTC_LS);
-               writel(0x00400008, remapped_regs + mmCRTC_REV);
-               writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
-               writel(0xC0140014, remapped_regs + mmCRTC_GS);
-               writel(0x00010141, remapped_regs + mmCRTC_VPOS_GS);
-               writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
-               writel(0x80100110, remapped_regs + mmCRTC_GOE);
-               writel(0x00000000, remapped_regs + mmCRTC_FRAME);
-               writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
-               writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
-               writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
-               writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
-               writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
-               writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
-               writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
-               writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
-               writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
-               writel(0x000001e0, remapped_regs + mmGRAPHIC_PITCH);
-               writel(0x000000bf, remapped_regs + mmGPIO_DATA);
-               writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
-               writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
-               writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
-               break;
-       case LCD_SHARP_VGA:
-               w100_set_slowsysclk(12);        /* use crystal -- 12.5MHz */
-               w100_set_fastsysclk(current_par->fastsysclk_mode);      /* use PLL -- 75.0MHz */
-               w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
-               w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x2;
-               writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
-               writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
-               writel(0x9FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
-               writel(0x00000003, remapped_regs + mmLCD_FORMAT);
-               writel(0x00DE1D66, remapped_regs + mmGRAPHIC_CTRL);
-
-               writel(0x0283028B, remapped_regs + mmCRTC_TOTAL);
-               writel(0x02360056, remapped_regs + mmACTIVE_H_DISP);
-               writel(0x02830003, remapped_regs + mmACTIVE_V_DISP);
-               writel(0x02360056, remapped_regs + mmGRAPHIC_H_DISP);
-               writel(0x02830003, remapped_regs + mmGRAPHIC_V_DISP);
-               writel(0x82360056, remapped_regs + mmCRTC_SS);
-               writel(0xA0280000, remapped_regs + mmCRTC_LS);
-               writel(0x00400008, remapped_regs + mmCRTC_REV);
-               writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
-               writel(0x80280028, remapped_regs + mmCRTC_GS);
-               writel(0x02830002, remapped_regs + mmCRTC_VPOS_GS);
-               writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
-               writel(0x80100110, remapped_regs + mmCRTC_GOE);
-               writel(0x00000000, remapped_regs + mmCRTC_FRAME);
-               writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
-               writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
-               writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
-               writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
-               writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
-               writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
-               writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
-               writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
-               writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
-               writel(0x000003C0, remapped_regs + mmGRAPHIC_PITCH);
-               writel(0x000000bf, remapped_regs + mmGPIO_DATA);
-               writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
-               writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
-               writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
-               break;
-       default:
-               break;
-       }
+       w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
+       w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
+       w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
+       writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+}
+
+static void w100_init_lcd(struct w100fb_par *par)
+{
+       u32 temp32;
+       struct w100_mode *mode = par->mode;
+       struct w100_gen_regs *regs = par->mach->regs;
+       union active_h_disp_u active_h_disp;
+       union active_v_disp_u active_v_disp;
+       union graphic_h_disp_u graphic_h_disp;
+       union graphic_v_disp_u graphic_v_disp;
+       union crtc_total_u crtc_total;
+
+       /* w3200 doesnt like undefined bits being set so zero register values first */
+
+       active_h_disp.val = 0;
+       active_h_disp.f.active_h_start=mode->left_margin;
+       active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
+       writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
+
+       active_v_disp.val = 0;
+       active_v_disp.f.active_v_start=mode->upper_margin;
+       active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
+       writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
+
+       graphic_h_disp.val = 0;
+       graphic_h_disp.f.graphic_h_start=mode->left_margin;
+       graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
+       writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
+
+       graphic_v_disp.val = 0;
+       graphic_v_disp.f.graphic_v_start=mode->upper_margin;
+       graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
+       writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
+
+       crtc_total.val = 0;
+       crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
+       crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
+       writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
+
+       writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
+       writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
+       writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
+       writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
+       writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
+       writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
+       writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
+       writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
+       writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
+
+       writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
+       writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
+       writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
+       writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
+       writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
+       writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
+
+       writel(0x00000000, remapped_regs + mmCRTC_FRAME);
+       writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
+       writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
+       writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
 
        /* Hack for overlay in ext memory */
        temp32 = readl(remapped_regs + mmDISP_DEBUG2);
        temp32 |= 0xc0000000;
        writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
-       /* Re-enable display updates */
-       disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
-       disp_db_buf_wr_cntl.f.update_db_buf = 1;
-       disp_db_buf_wr_cntl.f.en_db_buf = 1;
-       writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
 }
 
 
-static void w100_set_vga_rotation_regs(u16 divider, unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_setup_memory(struct w100fb_par *par)
 {
-       w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
-       w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
-       writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+       union mc_ext_mem_location_u extmem_location;
+       union mc_fb_location_u intmem_location;
+       struct w100_mem_info *mem = par->mach->mem;
+       struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
 
-       writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
-       writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
-       writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+       if (!par->extmem_active) {
+               w100_suspend(W100_SUSPEND_EXTMEM);
 
-       /* Re-enable display updates */
-       writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
-}
+               /* Map Internal Memory at FB Base */
+               intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
+               intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
+               writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
 
+               /* Unmap External Memory - value is *probably* irrelevant but may have meaning
+                  to acceleration libraries */
+               extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
+               extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
+               writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+       } else {
+               /* Map Internal Memory to its default location */
+               intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
+               intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
+               writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
 
-static void w100_init_vga_rotation(u16 deg)
-{
-       switch(deg) {
-       case 0:
-               w100_set_vga_rotation_regs(0x02, 0x00DE1D66, 0x00800000, 0x000003c0);
-               break;
-       case 90:
-               w100_set_vga_rotation_regs(0x06, 0x00DE1D0e, 0x00895b00, 0x00000500);
-               break;
-       case 180:
-               w100_set_vga_rotation_regs(0x02, 0x00DE1D7e, 0x00895ffc, 0x000003c0);
-               break;
-       case 270:
-               w100_set_vga_rotation_regs(0x06, 0x00DE1D16, 0x008004fc, 0x00000500);
-               break;
-       default:
-               /* not-support */
-               break;
+               /* Map External Memory at FB Base */
+               extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
+               extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
+               writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+
+               writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
+               writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
+               writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+               udelay(100);
+               writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+               udelay(100);
+               writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
+               udelay(100);
+               writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
+               writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
+               if (bm_mem) {
+                       writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
+                       writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
+                       writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
+                       writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
+                       writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
+                       writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
+                       writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
+               }
        }
 }
 
-
-static void w100_set_qvga_rotation_regs(unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_set_dispregs(struct w100fb_par *par)
 {
-       writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
-       writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
-       writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+       unsigned long rot=0, divider, offset=0;
+       union graphic_ctrl_u graphic_ctrl;
+
+       /* See if the mode has been rotated */
+       if (par->xres == par->mode->xres) {
+               if (par->flip) {
+                       rot=3; /* 180 degree */
+                       offset=(par->xres * par->yres) - 1;
+               } /* else 0 degree */
+               divider = par->mode->pixclk_divider;
+       } else {
+               if (par->flip) {
+                       rot=2; /* 270 degree */
+                       offset=par->xres - 1;
+               } else {
+                       rot=1; /* 90 degree */
+                       offset=par->xres * (par->yres - 1);
+               }
+               divider = par->mode->pixclk_divider_rotated;
+       }
 
-       /* Re-enable display updates */
-       writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
+       graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
+       switch (par->chip_id) {
+               case CHIP_ID_W100:
+                       graphic_ctrl.f_w100.color_depth=6;
+                       graphic_ctrl.f_w100.en_crtc=1;
+                       graphic_ctrl.f_w100.en_graphic_req=1;
+                       graphic_ctrl.f_w100.en_graphic_crtc=1;
+                       graphic_ctrl.f_w100.lcd_pclk_on=1;
+                       graphic_ctrl.f_w100.lcd_sclk_on=1;
+                       graphic_ctrl.f_w100.low_power_on=0;
+                       graphic_ctrl.f_w100.req_freq=0;
+                       graphic_ctrl.f_w100.portrait_mode=rot;
+
+                       /* Zaurus needs this */
+                       switch(par->xres) {
+                               case 240:
+                               case 320:
+                               default:
+                                       graphic_ctrl.f_w100.total_req_graphic=0xa0;
+                                       break;
+                               case 480:
+                               case 640:
+                                       switch(rot) {
+                                               case 0:  /* 0 */
+                                               case 3:  /* 180 */
+                                                       graphic_ctrl.f_w100.low_power_on=1;
+                                                       graphic_ctrl.f_w100.req_freq=5;
+                                               break;
+                                               case 1:  /* 90 */
+                                               case 2:  /* 270 */
+                                                       graphic_ctrl.f_w100.req_freq=4;
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+                                       graphic_ctrl.f_w100.total_req_graphic=0xf0;
+                                       break;
+                       }
+                       break;
+               case CHIP_ID_W3200:
+               case CHIP_ID_W3220:
+                       graphic_ctrl.f_w32xx.color_depth=6;
+                       graphic_ctrl.f_w32xx.en_crtc=1;
+                       graphic_ctrl.f_w32xx.en_graphic_req=1;
+                       graphic_ctrl.f_w32xx.en_graphic_crtc=1;
+                       graphic_ctrl.f_w32xx.lcd_pclk_on=1;
+                       graphic_ctrl.f_w32xx.lcd_sclk_on=1;
+                       graphic_ctrl.f_w32xx.low_power_on=0;
+                       graphic_ctrl.f_w32xx.req_freq=0;
+                       graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
+                       graphic_ctrl.f_w32xx.portrait_mode=rot;
+                       break;
+       }
+
+       /* Set the pixel clock source and divider */
+       w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
+       w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
+       writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+
+       writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
+       writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
+       writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
 }
 
 
-static void w100_init_qvga_rotation(u16 deg)
+/*
+ * Work out how long the sync pulse lasts
+ * Value is 1/(time in seconds)
+ */
+static void calc_hsync(struct w100fb_par *par)
 {
-       switch(deg) {
-       case 0:
-               w100_set_qvga_rotation_regs(0x00d41c06, 0x00800000, 0x000001e0);
-               break;
-       case 90:
-               w100_set_qvga_rotation_regs(0x00d41c0E, 0x00825580, 0x00000280);
-               break;
-       case 180:
-               w100_set_qvga_rotation_regs(0x00d41c1e, 0x008257fc, 0x000001e0);
-               break;
-       case 270:
-               w100_set_qvga_rotation_regs(0x00d41c16, 0x0080027c, 0x00000280);
-               break;
-       default:
-               /* not-support */
-               break;
-       }
-}
+       unsigned long hsync;
+       struct w100_mode *mode = par->mode;
+       union crtc_ss_u crtc_ss;
+
+       if (mode->pixclk_src == CLK_SRC_XTAL)
+               hsync=par->mach->xtal_freq;
+       else
+               hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
 
+       hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
+
+       crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
+       if (crtc_ss.val)
+               par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
+       else
+               par->hsync_len = 0;
+}
 
 static void w100_suspend(u32 mode)
 {
@@ -1387,30 +1377,28 @@ static void w100_suspend(u32 mode)
        writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
 
        val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
-       val &= ~(0x00100000);   /* bit20=0 */
-       val |= 0xFF000000;      /* bit31:24=0xff */
+       val &= ~(0x00100000);  /* bit20=0 */
+       val |= 0xFF000000;     /* bit31:24=0xff */
        writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
 
        val = readl(remapped_regs + mmMEM_EXT_CNTL);
-       val &= ~(0x00040000);   /* bit18=0 */
-       val |= 0x00080000;      /* bit19=1 */
+       val &= ~(0x00040000);  /* bit18=0 */
+       val |= 0x00080000;     /* bit19=1 */
        writel(val, remapped_regs + mmMEM_EXT_CNTL);
 
-       udelay(1);              /* wait 1us */
+       udelay(1);  /* wait 1us */
 
        if (mode == W100_SUSPEND_EXTMEM) {
-
                /* CKE: Tri-State */
                val = readl(remapped_regs + mmMEM_EXT_CNTL);
-               val |= 0x40000000;      /* bit30=1 */
+               val |= 0x40000000;  /* bit30=1 */
                writel(val, remapped_regs + mmMEM_EXT_CNTL);
 
                /* CLK: Stop */
                val = readl(remapped_regs + mmMEM_EXT_CNTL);
-               val &= ~(0x00000001);   /* bit0=0 */
+               val &= ~(0x00000001);  /* bit0=0 */
                writel(val, remapped_regs + mmMEM_EXT_CNTL);
        } else {
-
                writel(0x00000000, remapped_regs + mmSCLK_CNTL);
                writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
                writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
@@ -1418,43 +1406,16 @@ static void w100_suspend(u32 mode)
                udelay(5);
 
                val = readl(remapped_regs + mmPLL_CNTL);
-               val |= 0x00000004;      /* bit2=1 */
+               val |= 0x00000004;  /* bit2=1 */
                writel(val, remapped_regs + mmPLL_CNTL);
                writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
        }
 }
 
-
-static void w100_resume(void)
-{
-       u32 temp32;
-
-       w100_hw_init();
-       w100_pwm_setup();
-
-       temp32 = readl(remapped_regs + mmDISP_DEBUG2);
-       temp32 &= 0xff7fffff;
-       temp32 |= 0x00800000;
-       writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
-       if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
-               w100_init_sharp_lcd(LCD_SHARP_VGA);
-               if (current_par->lcdMode == LCD_MODE_640) {
-                       w100_init_vga_rotation(current_par->rotation_flag ? 270 : 90);
-               }
-       } else {
-               w100_init_sharp_lcd(LCD_SHARP_QVGA);
-               if (current_par->lcdMode == LCD_MODE_320) {
-                       w100_init_qvga_rotation(current_par->rotation_flag ? 270 : 90);
-               }
-       }
-}
-
-
 static void w100_vsync(void)
 {
        u32 tmp;
-       int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
+       int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
 
        tmp = readl(remapped_regs + mmACTIVE_V_DISP);
 
@@ -1490,363 +1451,6 @@ static void w100_vsync(void)
        writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
 }
 
-
-static void w100_InitExtMem(u32 mode)
-{
-       switch(mode) {
-       case LCD_SHARP_QVGA:
-               /* QVGA doesn't use external memory
-                  nothing to do, really. */
-               break;
-       case LCD_SHARP_VGA:
-               writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
-               writel(0x00040003, remapped_regs + mmMEM_EXT_CNTL);
-               writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
-               udelay(100);
-               writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
-               udelay(100);
-               writel(0x00650021, remapped_regs + mmMEM_SDRAM_MODE_REG);
-               udelay(100);
-               writel(0x10002a4a, remapped_regs + mmMEM_EXT_TIMING_CNTL);
-               writel(0x7ff87012, remapped_regs + mmMEM_IO_CNTL);
-               break;
-       default:
-               break;
-       }
-}
-
-
-#define RESCTL_ADRS     0x00
-#define PHACTRL_ADRS   0x01
-#define DUTYCTRL_ADRS  0x02
-#define POWERREG0_ADRS 0x03
-#define POWERREG1_ADRS 0x04
-#define GPOR3_ADRS             0x05
-#define PICTRL_ADRS     0x06
-#define POLCTRL_ADRS    0x07
-
-#define RESCTL_QVGA     0x01
-#define RESCTL_VGA      0x00
-
-#define POWER1_VW_ON   0x01    /* VW Supply FET ON */
-#define POWER1_GVSS_ON 0x02    /* GVSS(-8V) Power Supply ON */
-#define POWER1_VDD_ON  0x04    /* VDD(8V),SVSS(-4V) Power Supply ON */
-
-#define POWER1_VW_OFF  0x00    /* VW Supply FET OFF */
-#define POWER1_GVSS_OFF        0x00    /* GVSS(-8V) Power Supply OFF */
-#define POWER1_VDD_OFF 0x00    /* VDD(8V),SVSS(-4V) Power Supply OFF */
-
-#define POWER0_COM_DCLK        0x01    /* COM Voltage DC Bias DAC Serial Data Clock */
-#define POWER0_COM_DOUT        0x02    /* COM Voltage DC Bias DAC Serial Data Out */
-#define POWER0_DAC_ON  0x04    /* DAC Power Supply ON */
-#define POWER0_COM_ON  0x08    /* COM Powewr Supply ON */
-#define POWER0_VCC5_ON 0x10    /* VCC5 Power Supply ON */
-
-#define POWER0_DAC_OFF 0x00    /* DAC Power Supply OFF */
-#define POWER0_COM_OFF 0x00    /* COM Powewr Supply OFF */
-#define POWER0_VCC5_OFF        0x00    /* VCC5 Power Supply OFF */
-
-#define PICTRL_INIT_STATE      0x01
-#define PICTRL_INIOFF          0x02
-#define PICTRL_POWER_DOWN      0x04
-#define PICTRL_COM_SIGNAL_OFF  0x08
-#define PICTRL_DAC_SIGNAL_OFF  0x10
-
-#define PICTRL_POWER_ACTIVE    (0)
-
-#define POLCTRL_SYNC_POL_FALL  0x01
-#define POLCTRL_EN_POL_FALL    0x02
-#define POLCTRL_DATA_POL_FALL  0x04
-#define POLCTRL_SYNC_ACT_H     0x08
-#define POLCTRL_EN_ACT_L       0x10
-
-#define POLCTRL_SYNC_POL_RISE  0x00
-#define POLCTRL_EN_POL_RISE    0x00
-#define POLCTRL_DATA_POL_RISE  0x00
-#define POLCTRL_SYNC_ACT_L     0x00
-#define POLCTRL_EN_ACT_H       0x00
-
-#define PHACTRL_PHASE_MANUAL   0x01
-
-#define PHAD_QVGA_DEFAULT_VAL (9)
-#define COMADJ_DEFAULT        (125)
-
-static void lcdtg_ssp_send(u8 adrs, u8 data)
-{
-       w100fb_ssp_send(adrs,data);
-}
-
-/*
- * This is only a psuedo I2C interface. We can't use the standard kernel
- * routines as the interface is write only. We just assume the data is acked...
- */
-static void lcdtg_ssp_i2c_send(u8 data)
-{
-       lcdtg_ssp_send(POWERREG0_ADRS, data);
-       udelay(10);
-}
-
-static void lcdtg_i2c_send_bit(u8 data)
-{
-       lcdtg_ssp_i2c_send(data);
-       lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
-       lcdtg_ssp_i2c_send(data);
-}
-
-static void lcdtg_i2c_send_start(u8 base)
-{
-       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
-       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
-       lcdtg_ssp_i2c_send(base);
-}
-
-static void lcdtg_i2c_send_stop(u8 base)
-{
-       lcdtg_ssp_i2c_send(base);
-       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
-       lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
-}
-
-static void lcdtg_i2c_send_byte(u8 base, u8 data)
-{
-       int i;
-       for (i = 0; i < 8; i++) {
-               if (data & 0x80)
-                       lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
-               else
-                       lcdtg_i2c_send_bit(base);
-               data <<= 1;
-       }
-}
-
-static void lcdtg_i2c_wait_ack(u8 base)
-{
-       lcdtg_i2c_send_bit(base);
-}
-
-static void lcdtg_set_common_voltage(u8 base_data, u8 data)
-{
-       /* Set Common Voltage to M62332FP via I2C */
-       lcdtg_i2c_send_start(base_data);
-       lcdtg_i2c_send_byte(base_data, 0x9c);
-       lcdtg_i2c_wait_ack(base_data);
-       lcdtg_i2c_send_byte(base_data, 0x00);
-       lcdtg_i2c_wait_ack(base_data);
-       lcdtg_i2c_send_byte(base_data, data);
-       lcdtg_i2c_wait_ack(base_data);
-       lcdtg_i2c_send_stop(base_data);
-}
-
-static struct lcdtg_register_setting {
-       u8 adrs;
-       u8 data;
-       u32 wait;
-} lcdtg_power_on_table[] = {
-
-    /* Initialize Internal Logic & Port */
-    { PICTRL_ADRS,
-      PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE |
-      PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF,
-      0 },
-
-    { POWERREG0_ADRS,
-      POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | POWER0_COM_OFF |
-      POWER0_VCC5_OFF,
-      0 },
-
-    { POWERREG1_ADRS,
-      POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF,
-      0 },
-
-    /* VDD(+8V),SVSS(-4V) ON */
-    { POWERREG1_ADRS,
-      POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON /* VDD ON */,
-      3000 },
-
-    /* DAC ON */
-    { POWERREG0_ADRS,
-      POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
-      POWER0_COM_OFF | POWER0_VCC5_OFF,
-      0 },
-
-    /* INIB = H, INI = L  */
-    { PICTRL_ADRS,
-      /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
-      PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF,
-      0 },
-
-    /* Set Common Voltage */
-    { 0xfe, 0, 0 },
-
-    /* VCC5 ON */
-    { POWERREG0_ADRS,
-      POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
-      POWER0_COM_OFF | POWER0_VCC5_ON /* VCC5 ON */,
-      0 },
-
-    /* GVSS(-8V) ON */
-    { POWERREG1_ADRS,
-      POWER1_VW_OFF | POWER1_GVSS_ON /* GVSS ON */ |
-      POWER1_VDD_ON /* VDD ON */,
-      2000 },
-
-    /* COM SIGNAL ON (PICTL[3] = L) */
-    { PICTRL_ADRS,
-      PICTRL_INIT_STATE,
-      0 },
-
-    /* COM ON */
-    { POWERREG0_ADRS,
-      POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
-      POWER0_COM_ON /* COM ON */ | POWER0_VCC5_ON /* VCC5_ON */,
-      0 },
-
-    /* VW ON */
-    { POWERREG1_ADRS,
-      POWER1_VW_ON /* VW ON */ | POWER1_GVSS_ON /* GVSS ON */ |
-      POWER1_VDD_ON /* VDD ON */,
-      0 /* Wait 100ms */ },
-
-    /* Signals output enable */
-    { PICTRL_ADRS,
-      0 /* Signals output enable */,
-      0 },
-
-    { PHACTRL_ADRS,
-      PHACTRL_PHASE_MANUAL,
-      0 },
-
-    /* Initialize for Input Signals from ATI */
-    { POLCTRL_ADRS,
-      POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | POLCTRL_DATA_POL_RISE |
-      POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H,
-      1000 /*100000*/ /* Wait 100ms */ },
-
-    /* end mark */
-    { 0xff, 0, 0 }
-};
-
-static void lcdtg_resume(void)
-{
-       if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
-               lcdtg_hw_init(LCD_SHARP_VGA);
-       } else {
-               lcdtg_hw_init(LCD_SHARP_QVGA);
-       }
-}
-
-static void lcdtg_suspend(void)
-{
-       int i;
-
-       for (i = 0; i < (current_par->xres * current_par->yres); i++) {
-               writew(0xffff, remapped_fbuf + (2*i));
-       }
-
-       /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
-       mdelay(34);
-
-       /* (1)VW OFF */
-       lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
-
-       /* (2)COM OFF */
-       lcdtg_ssp_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
-       lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
-
-       /* (3)Set Common Voltage Bias 0V */
-       lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
-
-       /* (4)GVSS OFF */
-       lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
-
-       /* (5)VCC5 OFF */
-       lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
-       /* (6)Set PDWN, INIOFF, DACOFF */
-       lcdtg_ssp_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
-                       PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
-
-       /* (7)DAC OFF */
-       lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
-       /* (8)VDD OFF */
-       lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
-
-}
-
-static void lcdtg_set_phadadj(u32 mode)
-{
-       int adj;
-
-       if (mode == LCD_SHARP_VGA) {
-               /* Setting for VGA */
-               adj = current_par->phadadj;
-               if (adj < 0) {
-                       adj = PHACTRL_PHASE_MANUAL;
-               } else {
-                       adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
-               }
-       } else {
-               /* Setting for QVGA */
-               adj = (PHAD_QVGA_DEFAULT_VAL << 1) | PHACTRL_PHASE_MANUAL;
-       }
-       lcdtg_ssp_send(PHACTRL_ADRS, adj);
-}
-
-static void lcdtg_hw_init(u32 mode)
-{
-       int i;
-       int comadj;
-
-       i = 0;
-       while(lcdtg_power_on_table[i].adrs != 0xff) {
-               if (lcdtg_power_on_table[i].adrs == 0xfe) {
-                       /* Set Common Voltage */
-                       comadj = current_par->comadj;
-                       if (comadj < 0) {
-                               comadj = COMADJ_DEFAULT;
-                       }
-                       lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
-               } else if (lcdtg_power_on_table[i].adrs == PHACTRL_ADRS) {
-                       /* Set Phase Adjuct */
-                       lcdtg_set_phadadj(mode);
-               } else {
-                       /* Other */
-                       lcdtg_ssp_send(lcdtg_power_on_table[i].adrs, lcdtg_power_on_table[i].data);
-               }
-               if (lcdtg_power_on_table[i].wait != 0)
-                       udelay(lcdtg_power_on_table[i].wait);
-               i++;
-       }
-
-       switch(mode) {
-       case LCD_SHARP_QVGA:
-               /* Set Lcd Resolution (QVGA) */
-               lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
-               break;
-       case LCD_SHARP_VGA:
-               /* Set Lcd Resolution (VGA) */
-               lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
-               break;
-       default:
-               break;
-       }
-}
-
-static void lcdtg_lcd_change(u32 mode)
-{
-       /* Set Phase Adjuct */
-       lcdtg_set_phadadj(mode);
-
-       if (mode == LCD_SHARP_VGA)
-               /* Set Lcd Resolution (VGA) */
-               lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
-       else if (mode == LCD_SHARP_QVGA)
-               /* Set Lcd Resolution (QVGA) */
-               lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
-}
-
-
 static struct device_driver w100fb_driver = {
        .name           = "w100fb",
        .bus            = &platform_bus_type,
@@ -1870,4 +1474,4 @@ module_init(w100fb_init);
 module_exit(w100fb_cleanup);
 
 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL");
index 41624f961237cdcee3b34ada2d785085dc0f5d82..7a58a1e3e427c81d7e6c95a7e4164d3296540d29 100644 (file)
@@ -5,9 +5,12 @@
  *
  * Copyright (C) 2002, ATI Corp.
  * Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
  *
  * Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net>
  *
+ * w32xx support by Ian Molton
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -19,7 +22,7 @@
 
 /* Block CIF Start: */
 #define mmCHIP_ID           0x0000
-#define mmREVISION_ID          0x0004
+#define mmREVISION_ID       0x0004
 #define mmWRAP_BUF_A        0x0008
 #define mmWRAP_BUF_B        0x000C
 #define mmWRAP_TOP_DIR      0x0010
@@ -88,7 +91,7 @@
 #define mmDISP_DEBUG        0x04D4
 #define mmDISP_DB_BUF_CNTL  0x04D8
 #define mmDISP_CRC_SIG      0x04DC
-#define mmCRTC_DEFAULT_COUNT   0x04E0
+#define mmCRTC_DEFAULT_COUNT    0x04E0
 #define mmLCD_BACKGROUND_COLOR  0x04E4
 #define mmCRTC_PS2          0x04E8
 #define mmCRTC_PS2_VPOS     0x04EC
 /* Block DISPLAY End: */
 
 /* Block GFX Start: */
-#define mmBRUSH_OFFSET      0x108C
-#define mmBRUSH_Y_X         0x1074
-#define mmDEFAULT_PITCH_OFFSET         0x10A0
-#define mmDEFAULT_SC_BOTTOM_RIGHT      0x10A8
-#define mmDEFAULT2_SC_BOTTOM_RIGHT     0x10AC
-#define mmGLOBAL_ALPHA      0x1210
-#define mmFILTER_COEF       0x1214
-#define mmMVC_CNTL_START    0x11E0
-#define mmE2_ARITHMETIC_CNTL   0x1220
-#define mmENG_CNTL          0x13E8
-#define mmENG_PERF_CNT      0x13F0
+#define mmBRUSH_OFFSET        0x108C
+#define mmBRUSH_Y_X           0x1074
+#define mmDEFAULT_PITCH_OFFSET      0x10A0
+#define mmDEFAULT_SC_BOTTOM_RIGHT   0x10A8
+#define mmDEFAULT2_SC_BOTTOM_RIGHT  0x10AC
+#define mmGLOBAL_ALPHA        0x1210
+#define mmFILTER_COEF         0x1214
+#define mmMVC_CNTL_START      0x11E0
+#define mmE2_ARITHMETIC_CNTL  0x1220
+#define mmENG_CNTL            0x13E8
+#define mmENG_PERF_CNT        0x13F0
 /* Block GFX End: */
 
 /* Block IDCT Start: */
 /* Block IDCT End: */
 
 /* Block MC Start: */
-#define mmMEM_CNTL          0x0180
-#define mmMEM_ARB           0x0184
-#define mmMC_FB_LOCATION    0x0188
-#define mmMEM_EXT_CNTL      0x018C
-#define mmMC_EXT_MEM_LOCATION   0x0190
-#define mmMEM_EXT_TIMING_CNTL   0x0194
-#define mmMEM_SDRAM_MODE_REG   0x0198
-#define mmMEM_IO_CNTL       0x019C
-#define mmMC_DEBUG          0x01A0
-#define mmMC_BIST_CTRL      0x01A4
-#define mmMC_BIST_COLLAR_READ          0x01A8
-#define mmTC_MISMATCH       0x01AC
-#define mmMC_PERF_MON_CNTL  0x01B0
-#define mmMC_PERF_COUNTERS  0x01B4
+#define mmMEM_CNTL             0x0180
+#define mmMEM_ARB              0x0184
+#define mmMC_FB_LOCATION       0x0188
+#define mmMEM_EXT_CNTL         0x018C
+#define mmMC_EXT_MEM_LOCATION  0x0190
+#define mmMEM_EXT_TIMING_CNTL  0x0194
+#define mmMEM_SDRAM_MODE_REG   0x0198
+#define mmMEM_IO_CNTL          0x019C
+#define mmMC_DEBUG             0x01A0
+#define mmMC_BIST_CTRL         0x01A4
+#define mmMC_BIST_COLLAR_READ  0x01A8
+#define mmTC_MISMATCH          0x01AC
+#define mmMC_PERF_MON_CNTL     0x01B0
+#define mmMC_PERF_COUNTERS     0x01B4
 /* Block MC End: */
 
+/* Block BM Start: */
+#define mmBM_EXT_MEM_BANDWIDTH    0x0A00
+#define mmBM_OFFSET               0x0A04
+#define mmBM_MEM_EXT_TIMING_CNTL  0x0A08
+#define mmBM_MEM_EXT_CNTL         0x0A0C
+#define mmBM_MEM_MODE_REG         0x0A10
+#define mmBM_MEM_IO_CNTL          0x0A18
+#define mmBM_CONFIG               0x0A1C
+#define mmBM_STATUS               0x0A20
+#define mmBM_DEBUG                0x0A24
+#define mmBM_PERF_MON_CNTL        0x0A28
+#define mmBM_PERF_COUNTERS        0x0A2C
+#define mmBM_PERF2_MON_CNTL       0x0A30
+#define mmBM_PERF2_COUNTERS       0x0A34
+/* Block BM End: */
+
 /* Block RBBM Start: */
 #define mmWAIT_UNTIL        0x1400
 #define mmISYNC_CNTL        0x1404
 /* Block CG End: */
 
 /* default value definitions */
-#define defWRAP_TOP_DIR     0x00000000
-#define defWRAP_START_DIR      0x00000000
-#define defCFGREG_BASE      0x00000000
-#define defCIF_IO           0x000C0902
-#define defINTF_CNTL        0x00000011
-#define defCPU_DEFAULTS     0x00000006
-#define defHW_INT           0x00000000
-#define defMC_EXT_MEM_LOCATION            0x07ff0000
-#define defTC_MISMATCH      0x00000000
+#define defWRAP_TOP_DIR        0x00000000
+#define defWRAP_START_DIR      0x00000000
+#define defCFGREG_BASE         0x00000000
+#define defCIF_IO              0x000C0902
+#define defINTF_CNTL           0x00000011
+#define defCPU_DEFAULTS        0x00000006
+#define defHW_INT              0x00000000
+#define defMC_EXT_MEM_LOCATION 0x07ff0000
+#define defTC_MISMATCH         0x00000000
 
 #define W100_CFG_BASE          0x0
 #define W100_CFG_LEN           0x10
 #define W100_REG_BASE          0x10000
 #define W100_REG_LEN           0x2000
 #define MEM_INT_BASE_VALUE     0x100000
-#define MEM_INT_TOP_VALUE_W100 0x15ffff
 #define MEM_EXT_BASE_VALUE     0x800000
-#define MEM_EXT_TOP_VALUE      0x9fffff
+#define MEM_INT_SIZE           0x05ffff
+#define MEM_WINDOW_BASE        0x100000
+#define MEM_WINDOW_SIZE        0xf00000
+
 #define WRAP_BUF_BASE_VALUE    0x80000
 #define WRAP_BUF_TOP_VALUE     0xbffff
 
+#define CHIP_ID_W100           0x57411002
+#define CHIP_ID_W3200          0x56441002
+#define CHIP_ID_W3220          0x57441002
 
-/* data structure definitions */
+/* Register structure definitions */
 
 struct wrap_top_dir_t {
-     unsigned long top_addr         : 23;
-     unsigned long                             : 9;
+       unsigned long top_addr  : 23;
+       unsigned long           : 9;
 } __attribute__((packed));
 
 union wrap_top_dir_u {
-     unsigned long val : 32;
-     struct wrap_top_dir_t f;
+       unsigned long val : 32;
+       struct wrap_top_dir_t f;
 } __attribute__((packed));
 
 struct wrap_start_dir_t {
-     unsigned long start_addr       : 23;
-     unsigned long                             : 9;
+       unsigned long start_addr : 23;
+       unsigned long            : 9;
 } __attribute__((packed));
 
 union wrap_start_dir_u {
-     unsigned long val : 32;
-     struct wrap_start_dir_t f;
+       unsigned long val : 32;
+       struct wrap_start_dir_t f;
 } __attribute__((packed));
 
 struct cif_cntl_t {
-     unsigned long swap_reg                    : 2;
-     unsigned long swap_fbuf_1                 : 2;
-     unsigned long swap_fbuf_2                 : 2;
-     unsigned long swap_fbuf_3                 : 2;
-     unsigned long pmi_int_disable             : 1;
-     unsigned long pmi_schmen_disable       : 1;
-     unsigned long intb_oe                     : 1;
-     unsigned long en_wait_to_compensate_dq_prop_dly : 1;
-     unsigned long compensate_wait_rd_size  : 2;
-     unsigned long wait_asserted_timeout_val      : 2;
-     unsigned long wait_masked_val             : 2;
-     unsigned long en_wait_timeout             : 1;
-     unsigned long en_one_clk_setup_before_wait   : 1;
-     unsigned long interrupt_active_high    : 1;
-     unsigned long en_overwrite_straps      : 1;
-     unsigned long strap_wait_active_hi     : 1;
-     unsigned long lat_busy_count              : 2;
-     unsigned long lat_rd_pm4_sclk_busy     : 1;
-     unsigned long dis_system_bits             : 1;
-     unsigned long dis_mr                      : 1;
-     unsigned long cif_spare_1                 : 4;
+       unsigned long swap_reg                 : 2;
+       unsigned long swap_fbuf_1              : 2;
+       unsigned long swap_fbuf_2              : 2;
+       unsigned long swap_fbuf_3              : 2;
+       unsigned long pmi_int_disable          : 1;
+       unsigned long pmi_schmen_disable       : 1;
+       unsigned long intb_oe                  : 1;
+       unsigned long en_wait_to_compensate_dq_prop_dly  : 1;
+       unsigned long compensate_wait_rd_size  : 2;
+       unsigned long wait_asserted_timeout_val  : 2;
+       unsigned long wait_masked_val          : 2;
+       unsigned long en_wait_timeout          : 1;
+       unsigned long en_one_clk_setup_before_wait  : 1;
+       unsigned long interrupt_active_high    : 1;
+       unsigned long en_overwrite_straps      : 1;
+       unsigned long strap_wait_active_hi     : 1;
+       unsigned long lat_busy_count           : 2;
+       unsigned long lat_rd_pm4_sclk_busy     : 1;
+       unsigned long dis_system_bits          : 1;
+       unsigned long dis_mr                   : 1;
+       unsigned long cif_spare_1              : 4;
 } __attribute__((packed));
 
 union cif_cntl_u {
-     unsigned long val : 32;
-     struct cif_cntl_t f;
+       unsigned long val : 32;
+       struct cif_cntl_t f;
 } __attribute__((packed));
 
 struct cfgreg_base_t {
-     unsigned long cfgreg_base      : 24;
-     unsigned long                             : 8;
+       unsigned long cfgreg_base  : 24;
+       unsigned long              : 8;
 } __attribute__((packed));
 
 union cfgreg_base_u {
-     unsigned long val : 32;
-     struct cfgreg_base_t f;
+       unsigned long val : 32;
+       struct cfgreg_base_t f;
 } __attribute__((packed));
 
 struct cif_io_t {
-     unsigned long dq_srp           : 1;
-     unsigned long dq_srn           : 1;
-     unsigned long dq_sp            : 4;
-     unsigned long dq_sn            : 4;
-     unsigned long waitb_srp        : 1;
-     unsigned long waitb_srn        : 1;
-     unsigned long waitb_sp         : 4;
-     unsigned long waitb_sn         : 4;
-     unsigned long intb_srp         : 1;
-     unsigned long intb_srn         : 1;
-     unsigned long intb_sp          : 4;
-     unsigned long intb_sn          : 4;
-     unsigned long                             : 2;
+       unsigned long dq_srp     : 1;
+       unsigned long dq_srn     : 1;
+       unsigned long dq_sp      : 4;
+       unsigned long dq_sn      : 4;
+       unsigned long waitb_srp  : 1;
+       unsigned long waitb_srn  : 1;
+       unsigned long waitb_sp   : 4;
+       unsigned long waitb_sn   : 4;
+       unsigned long intb_srp   : 1;
+       unsigned long intb_srn   : 1;
+       unsigned long intb_sp    : 4;
+       unsigned long intb_sn    : 4;
+       unsigned long            : 2;
 } __attribute__((packed));
 
 union cif_io_u {
-     unsigned long val : 32;
-     struct cif_io_t f;
+       unsigned long val : 32;
+       struct cif_io_t f;
 } __attribute__((packed));
 
 struct cif_read_dbg_t {
-     unsigned long unpacker_pre_fetch_trig_gen  : 2;
-     unsigned long dly_second_rd_fetch_trig     : 1;
-     unsigned long rst_rd_burst_id                     : 1;
-     unsigned long dis_rd_burst_id                     : 1;
-     unsigned long en_block_rd_when_packer_is_not_emp : 1;
-     unsigned long dis_pre_fetch_cntl_sm        : 1;
-     unsigned long rbbm_chrncy_dis                     : 1;
-     unsigned long rbbm_rd_after_wr_lat         : 2;
-     unsigned long dis_be_during_rd                    : 1;
-     unsigned long one_clk_invalidate_pulse     : 1;
-     unsigned long dis_chnl_priority                   : 1;
-     unsigned long rst_read_path_a_pls          : 1;
-     unsigned long rst_read_path_b_pls          : 1;
-     unsigned long dis_reg_rd_fetch_trig        : 1;
-     unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
-     unsigned long dis_rd_same_byte_to_trig_fetch : 1;
-     unsigned long dis_dir_wrap                        : 1;
-     unsigned long dis_ring_buf_to_force_dec    : 1;
-     unsigned long dis_addr_comp_in_16bit       : 1;
-     unsigned long clr_w                               : 1;
-     unsigned long err_rd_tag_is_3                     : 1;
-     unsigned long err_load_when_ful_a          : 1;
-     unsigned long err_load_when_ful_b          : 1;
-     unsigned long                                                     : 7;
+       unsigned long unpacker_pre_fetch_trig_gen  : 2;
+       unsigned long dly_second_rd_fetch_trig     : 1;
+       unsigned long rst_rd_burst_id              : 1;
+       unsigned long dis_rd_burst_id              : 1;
+       unsigned long en_block_rd_when_packer_is_not_emp : 1;
+       unsigned long dis_pre_fetch_cntl_sm        : 1;
+       unsigned long rbbm_chrncy_dis              : 1;
+       unsigned long rbbm_rd_after_wr_lat         : 2;
+       unsigned long dis_be_during_rd             : 1;
+       unsigned long one_clk_invalidate_pulse     : 1;
+       unsigned long dis_chnl_priority            : 1;
+       unsigned long rst_read_path_a_pls          : 1;
+       unsigned long rst_read_path_b_pls          : 1;
+       unsigned long dis_reg_rd_fetch_trig        : 1;
+       unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
+       unsigned long dis_rd_same_byte_to_trig_fetch : 1;
+       unsigned long dis_dir_wrap                 : 1;
+       unsigned long dis_ring_buf_to_force_dec    : 1;
+       unsigned long dis_addr_comp_in_16bit       : 1;
+       unsigned long clr_w                        : 1;
+       unsigned long err_rd_tag_is_3              : 1;
+       unsigned long err_load_when_ful_a          : 1;
+       unsigned long err_load_when_ful_b          : 1;
+       unsigned long                              : 7;
 } __attribute__((packed));
 
 union cif_read_dbg_u {
-     unsigned long val : 32;
-     struct cif_read_dbg_t f;
+       unsigned long val : 32;
+       struct cif_read_dbg_t f;
 } __attribute__((packed));
 
 struct cif_write_dbg_t {
-     unsigned long packer_timeout_count           : 2;
-     unsigned long en_upper_load_cond             : 1;
-     unsigned long en_chnl_change_cond            : 1;
-     unsigned long dis_addr_comp_cond             : 1;
-     unsigned long dis_load_same_byte_addr_cond   : 1;
-     unsigned long dis_timeout_cond                      : 1;
-     unsigned long dis_timeout_during_rbbm        : 1;
-     unsigned long dis_packer_ful_during_rbbm_timeout : 1;
-     unsigned long en_dword_split_to_rbbm         : 1;
-     unsigned long en_dummy_val                          : 1;
-     unsigned long dummy_val_sel                         : 1;
-     unsigned long mask_pm4_wrptr_dec             : 1;
-     unsigned long dis_mc_clean_cond                     : 1;
-     unsigned long err_two_reqi_during_ful        : 1;
-     unsigned long err_reqi_during_idle_clk       : 1;
-     unsigned long err_global                            : 1;
-     unsigned long en_wr_buf_dbg_load             : 1;
-     unsigned long en_wr_buf_dbg_path             : 1;
-     unsigned long sel_wr_buf_byte                       : 3;
-     unsigned long dis_rd_flush_wr                       : 1;
-     unsigned long dis_packer_ful_cond            : 1;
-     unsigned long dis_invalidate_by_ops_chnl     : 1;
-     unsigned long en_halt_when_reqi_err          : 1;
-     unsigned long cif_spare_2                           : 5;
-     unsigned long                                                       : 1;
+       unsigned long packer_timeout_count          : 2;
+       unsigned long en_upper_load_cond            : 1;
+       unsigned long en_chnl_change_cond           : 1;
+       unsigned long dis_addr_comp_cond            : 1;
+       unsigned long dis_load_same_byte_addr_cond  : 1;
+       unsigned long dis_timeout_cond              : 1;
+       unsigned long dis_timeout_during_rbbm       : 1;
+       unsigned long dis_packer_ful_during_rbbm_timeout : 1;
+       unsigned long en_dword_split_to_rbbm        : 1;
+       unsigned long en_dummy_val                  : 1;
+       unsigned long dummy_val_sel                 : 1;
+       unsigned long mask_pm4_wrptr_dec            : 1;
+       unsigned long dis_mc_clean_cond             : 1;
+       unsigned long err_two_reqi_during_ful       : 1;
+       unsigned long err_reqi_during_idle_clk      : 1;
+       unsigned long err_global                    : 1;
+       unsigned long en_wr_buf_dbg_load            : 1;
+       unsigned long en_wr_buf_dbg_path            : 1;
+       unsigned long sel_wr_buf_byte               : 3;
+       unsigned long dis_rd_flush_wr               : 1;
+       unsigned long dis_packer_ful_cond           : 1;
+       unsigned long dis_invalidate_by_ops_chnl    : 1;
+       unsigned long en_halt_when_reqi_err         : 1;
+       unsigned long cif_spare_2                   : 5;
+       unsigned long                               : 1;
 } __attribute__((packed));
 
 union cif_write_dbg_u {
-     unsigned long val : 32;
-     struct cif_write_dbg_t f;
+       unsigned long val : 32;
+       struct cif_write_dbg_t f;
 } __attribute__((packed));
 
 
 struct intf_cntl_t {
-     unsigned char ad_inc_a            : 1;
-     unsigned char ring_buf_a          : 1;
-     unsigned char rd_fetch_trigger_a  : 1;
-     unsigned char rd_data_rdy_a       : 1;
-     unsigned char ad_inc_b            : 1;
-     unsigned char ring_buf_b          : 1;
-     unsigned char rd_fetch_trigger_b  : 1;
-     unsigned char rd_data_rdy_b       : 1;
+       unsigned char ad_inc_a            : 1;
+       unsigned char ring_buf_a          : 1;
+       unsigned char rd_fetch_trigger_a  : 1;
+       unsigned char rd_data_rdy_a       : 1;
+       unsigned char ad_inc_b            : 1;
+       unsigned char ring_buf_b          : 1;
+       unsigned char rd_fetch_trigger_b  : 1;
+       unsigned char rd_data_rdy_b       : 1;
 } __attribute__((packed));
 
 union intf_cntl_u {
-     unsigned char val : 8;
-     struct intf_cntl_t f;
+       unsigned char val : 8;
+       struct intf_cntl_t f;
 } __attribute__((packed));
 
 struct cpu_defaults_t {
-     unsigned char unpack_rd_data   : 1;
-     unsigned char access_ind_addr_a: 1;
-     unsigned char access_ind_addr_b: 1;
-     unsigned char access_scratch_reg             : 1;
-     unsigned char pack_wr_data     : 1;
-     unsigned char transition_size  : 1;
-     unsigned char en_read_buf_mode : 1;
-     unsigned char rd_fetch_scratch : 1;
+       unsigned char unpack_rd_data     : 1;
+       unsigned char access_ind_addr_a  : 1;
+       unsigned char access_ind_addr_b  : 1;
+       unsigned char access_scratch_reg : 1;
+       unsigned char pack_wr_data       : 1;
+       unsigned char transition_size    : 1;
+       unsigned char en_read_buf_mode   : 1;
+       unsigned char rd_fetch_scratch   : 1;
 } __attribute__((packed));
 
 union cpu_defaults_u {
-     unsigned char val : 8;
-     struct cpu_defaults_t f;
+       unsigned char val : 8;
+       struct cpu_defaults_t f;
+} __attribute__((packed));
+
+struct crtc_total_t {
+       unsigned long crtc_h_total : 10;
+       unsigned long              : 6;
+       unsigned long crtc_v_total : 10;
+       unsigned long              : 6;
+} __attribute__((packed));
+
+union crtc_total_u {
+       unsigned long val : 32;
+       struct crtc_total_t f;
+} __attribute__((packed));
+
+struct crtc_ss_t {
+       unsigned long ss_start    : 10;
+       unsigned long             : 6;
+       unsigned long ss_end      : 10;
+       unsigned long             : 2;
+       unsigned long ss_align    : 1;
+       unsigned long ss_pol      : 1;
+       unsigned long ss_run_mode : 1;
+       unsigned long ss_en       : 1;
+} __attribute__((packed));
+
+union crtc_ss_u {
+       unsigned long val : 32;
+       struct crtc_ss_t f;
+} __attribute__((packed));
+
+struct active_h_disp_t {
+       unsigned long active_h_start  : 10;
+       unsigned long                 : 6;
+       unsigned long active_h_end    : 10;
+       unsigned long                 : 6;
+} __attribute__((packed));
+
+union active_h_disp_u {
+       unsigned long val : 32;
+       struct active_h_disp_t f;
+} __attribute__((packed));
+
+struct active_v_disp_t {
+       unsigned long active_v_start  : 10;
+       unsigned long                 : 6;
+       unsigned long active_v_end    : 10;
+       unsigned long                 : 6;
+} __attribute__((packed));
+
+union active_v_disp_u {
+       unsigned long val : 32;
+       struct active_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_h_disp_t {
+       unsigned long graphic_h_start : 10;
+       unsigned long                 : 6;
+       unsigned long graphic_h_end   : 10;
+       unsigned long                 : 6;
+} __attribute__((packed));
+
+union graphic_h_disp_u {
+       unsigned long val : 32;
+       struct graphic_h_disp_t f;
+} __attribute__((packed));
+
+struct graphic_v_disp_t {
+       unsigned long graphic_v_start : 10;
+       unsigned long                 : 6;
+       unsigned long graphic_v_end   : 10;
+       unsigned long                 : 6;
+} __attribute__((packed));
+
+union graphic_v_disp_u{
+       unsigned long val : 32;
+       struct graphic_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w100 {
+       unsigned long color_depth       : 3;
+       unsigned long portrait_mode     : 2;
+       unsigned long low_power_on      : 1;
+       unsigned long req_freq          : 4;
+       unsigned long en_crtc           : 1;
+       unsigned long en_graphic_req    : 1;
+       unsigned long en_graphic_crtc   : 1;
+       unsigned long total_req_graphic : 9;
+       unsigned long lcd_pclk_on       : 1;
+       unsigned long lcd_sclk_on       : 1;
+       unsigned long pclk_running      : 1;
+       unsigned long sclk_running      : 1;
+       unsigned long                   : 6;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w32xx {
+       unsigned long color_depth       : 3;
+       unsigned long portrait_mode     : 2;
+       unsigned long low_power_on      : 1;
+       unsigned long req_freq          : 4;
+       unsigned long en_crtc           : 1;
+       unsigned long en_graphic_req    : 1;
+       unsigned long en_graphic_crtc   : 1;
+       unsigned long total_req_graphic : 10;
+       unsigned long lcd_pclk_on       : 1;
+       unsigned long lcd_sclk_on       : 1;
+       unsigned long pclk_running      : 1;
+       unsigned long sclk_running      : 1;
+       unsigned long                   : 5;
+} __attribute__((packed));
+
+union graphic_ctrl_u {
+       unsigned long val : 32;
+       struct graphic_ctrl_t_w100 f_w100;
+       struct graphic_ctrl_t_w32xx f_w32xx;
 } __attribute__((packed));
 
 struct video_ctrl_t {
-     unsigned long video_mode       : 1;
-     unsigned long keyer_en         : 1;
-     unsigned long en_video_req     : 1;
-     unsigned long en_graphic_req_video           : 1;
-     unsigned long en_video_crtc    : 1;
-     unsigned long video_hor_exp    : 2;
-     unsigned long video_ver_exp    : 2;
-     unsigned long uv_combine       : 1;
-     unsigned long total_req_video  : 9;
-     unsigned long video_ch_sel     : 1;
-     unsigned long video_portrait   : 2;
-     unsigned long yuv2rgb_en       : 1;
-     unsigned long yuv2rgb_option   : 1;
-     unsigned long video_inv_hor    : 1;
-     unsigned long video_inv_ver    : 1;
-     unsigned long gamma_sel        : 2;
-     unsigned long dis_limit        : 1;
-     unsigned long en_uv_hblend     : 1;
-     unsigned long rgb_gamma_sel    : 2;
+       unsigned long video_mode       : 1;
+       unsigned long keyer_en         : 1;
+       unsigned long en_video_req     : 1;
+       unsigned long en_graphic_req_video  : 1;
+       unsigned long en_video_crtc    : 1;
+       unsigned long video_hor_exp    : 2;
+       unsigned long video_ver_exp    : 2;
+       unsigned long uv_combine       : 1;
+       unsigned long total_req_video  : 9;
+       unsigned long video_ch_sel     : 1;
+       unsigned long video_portrait   : 2;
+       unsigned long yuv2rgb_en       : 1;
+       unsigned long yuv2rgb_option   : 1;
+       unsigned long video_inv_hor    : 1;
+       unsigned long video_inv_ver    : 1;
+       unsigned long gamma_sel        : 2;
+       unsigned long dis_limit        : 1;
+       unsigned long en_uv_hblend     : 1;
+       unsigned long rgb_gamma_sel    : 2;
 } __attribute__((packed));
 
 union video_ctrl_u {
-     unsigned long val : 32;
-     struct video_ctrl_t f;
+       unsigned long val : 32;
+       struct video_ctrl_t f;
 } __attribute__((packed));
 
 struct disp_db_buf_cntl_rd_t {
-     unsigned long en_db_buf           : 1;
-     unsigned long update_db_buf_done   : 1;
-     unsigned long db_buf_cntl         : 6;
-     unsigned long                                     : 24;
+       unsigned long en_db_buf           : 1;
+       unsigned long update_db_buf_done  : 1;
+       unsigned long db_buf_cntl         : 6;
+       unsigned long                     : 24;
 } __attribute__((packed));
 
 union disp_db_buf_cntl_rd_u {
-     unsigned long val : 32;
-     struct disp_db_buf_cntl_rd_t f;
+       unsigned long val : 32;
+       struct disp_db_buf_cntl_rd_t f;
 } __attribute__((packed));
 
 struct disp_db_buf_cntl_wr_t {
-     unsigned long en_db_buf        : 1;
-     unsigned long update_db_buf    : 1;
-     unsigned long db_buf_cntl      : 6;
-     unsigned long    : 24;
+       unsigned long en_db_buf      : 1;
+       unsigned long update_db_buf  : 1;
+       unsigned long db_buf_cntl    : 6;
+       unsigned long                : 24;
 } __attribute__((packed));
 
 union disp_db_buf_cntl_wr_u {
-     unsigned long val : 32;
-     struct disp_db_buf_cntl_wr_t f;
+       unsigned long val : 32;
+       struct disp_db_buf_cntl_wr_t f;
 } __attribute__((packed));
 
 struct gamma_value1_t {
-     unsigned long gamma1           : 8;
-     unsigned long gamma2           : 8;
-     unsigned long gamma3           : 8;
-     unsigned long gamma4           : 8;
+       unsigned long gamma1   : 8;
+       unsigned long gamma2   : 8;
+       unsigned long gamma3   : 8;
+       unsigned long gamma4   : 8;
 } __attribute__((packed));
 
 union gamma_value1_u {
-     unsigned long val : 32;
-     struct gamma_value1_t f;
+       unsigned long val : 32;
+       struct gamma_value1_t f;
 } __attribute__((packed));
 
 struct gamma_value2_t {
-     unsigned long gamma5           : 8;
-     unsigned long gamma6           : 8;
-     unsigned long gamma7           : 8;
-     unsigned long gamma8           : 8;
+       unsigned long gamma5   : 8;
+       unsigned long gamma6   : 8;
+       unsigned long gamma7   : 8;
+       unsigned long gamma8   : 8;
 } __attribute__((packed));
 
 union gamma_value2_u {
-     unsigned long val : 32;
-     struct gamma_value2_t f;
+       unsigned long val : 32;
+       struct gamma_value2_t f;
 } __attribute__((packed));
 
 struct gamma_slope_t {
-     unsigned long slope1           : 3;
-     unsigned long slope2           : 3;
-     unsigned long slope3           : 3;
-     unsigned long slope4           : 3;
-     unsigned long slope5           : 3;
-     unsigned long slope6           : 3;
-     unsigned long slope7           : 3;
-     unsigned long slope8           : 3;
-     unsigned long                             : 8;
+       unsigned long slope1   : 3;
+       unsigned long slope2   : 3;
+       unsigned long slope3   : 3;
+       unsigned long slope4   : 3;
+       unsigned long slope5   : 3;
+       unsigned long slope6   : 3;
+       unsigned long slope7   : 3;
+       unsigned long slope8   : 3;
+       unsigned long          : 8;
 } __attribute__((packed));
 
 union gamma_slope_u {
-     unsigned long val : 32;
-     struct gamma_slope_t f;
+       unsigned long val : 32;
+       struct gamma_slope_t f;
 } __attribute__((packed));
 
 struct mc_ext_mem_location_t {
-     unsigned long mc_ext_mem_start : 16;
-     unsigned long mc_ext_mem_top   : 16;
+       unsigned long mc_ext_mem_start : 16;
+       unsigned long mc_ext_mem_top   : 16;
 } __attribute__((packed));
 
 union mc_ext_mem_location_u {
-     unsigned long val : 32;
-     struct mc_ext_mem_location_t f;
+       unsigned long val : 32;
+       struct mc_ext_mem_location_t f;
+} __attribute__((packed));
+
+struct mc_fb_location_t {
+       unsigned long mc_fb_start      : 16;
+       unsigned long mc_fb_top        : 16;
+} __attribute__((packed));
+
+union mc_fb_location_u {
+       unsigned long val : 32;
+       struct mc_fb_location_t f;
 } __attribute__((packed));
 
 struct clk_pin_cntl_t {
-     unsigned long osc_en           : 1;
-     unsigned long osc_gain         : 5;
-     unsigned long dont_use_xtalin  : 1;
-     unsigned long xtalin_pm_en     : 1;
-     unsigned long xtalin_dbl_en    : 1;
-     unsigned long                             : 7;
-     unsigned long cg_debug         : 16;
+       unsigned long osc_en           : 1;
+       unsigned long osc_gain         : 5;
+       unsigned long dont_use_xtalin  : 1;
+       unsigned long xtalin_pm_en     : 1;
+       unsigned long xtalin_dbl_en    : 1;
+       unsigned long                  : 7;
+       unsigned long cg_debug         : 16;
 } __attribute__((packed));
 
 union clk_pin_cntl_u {
-     unsigned long val : 32;
-     struct clk_pin_cntl_t f;
+       unsigned long val : 32;
+       struct clk_pin_cntl_t f;
 } __attribute__((packed));
 
 struct pll_ref_fb_div_t {
-     unsigned long pll_ref_div      : 4;
-     unsigned long                             : 4;
-     unsigned long pll_fb_div_int   : 6;
-     unsigned long                             : 2;
-     unsigned long pll_fb_div_frac  : 3;
-     unsigned long                             : 1;
-     unsigned long pll_reset_time   : 4;
-     unsigned long pll_lock_time    : 8;
+       unsigned long pll_ref_div      : 4;
+       unsigned long                  : 4;
+       unsigned long pll_fb_div_int   : 6;
+       unsigned long                  : 2;
+       unsigned long pll_fb_div_frac  : 3;
+       unsigned long                  : 1;
+       unsigned long pll_reset_time   : 4;
+       unsigned long pll_lock_time    : 8;
 } __attribute__((packed));
 
 union pll_ref_fb_div_u {
-     unsigned long val : 32;
-     struct pll_ref_fb_div_t f;
+       unsigned long val : 32;
+       struct pll_ref_fb_div_t f;
 } __attribute__((packed));
 
 struct pll_cntl_t {
-     unsigned long pll_pwdn         : 1;
-     unsigned long pll_reset        : 1;
-     unsigned long pll_pm_en        : 1;
-     unsigned long pll_mode         : 1;
-     unsigned long pll_refclk_sel   : 1;
-     unsigned long pll_fbclk_sel    : 1;
-     unsigned long pll_tcpoff       : 1;
-     unsigned long pll_pcp          : 3;
-     unsigned long pll_pvg          : 3;
-     unsigned long pll_vcofr        : 1;
-     unsigned long pll_ioffset      : 2;
-     unsigned long pll_pecc_mode    : 2;
-     unsigned long pll_pecc_scon    : 2;
-     unsigned long pll_dactal       : 4;
-     unsigned long pll_cp_clip      : 2;
-     unsigned long pll_conf         : 3;
-     unsigned long pll_mbctrl       : 2;
-     unsigned long pll_ring_off     : 1;
+       unsigned long pll_pwdn        : 1;
+       unsigned long pll_reset       : 1;
+       unsigned long pll_pm_en       : 1;
+       unsigned long pll_mode        : 1;
+       unsigned long pll_refclk_sel  : 1;
+       unsigned long pll_fbclk_sel   : 1;
+       unsigned long pll_tcpoff      : 1;
+       unsigned long pll_pcp         : 3;
+       unsigned long pll_pvg         : 3;
+       unsigned long pll_vcofr       : 1;
+       unsigned long pll_ioffset     : 2;
+       unsigned long pll_pecc_mode   : 2;
+       unsigned long pll_pecc_scon   : 2;
+       unsigned long pll_dactal      : 4;
+       unsigned long pll_cp_clip     : 2;
+       unsigned long pll_conf        : 3;
+       unsigned long pll_mbctrl      : 2;
+       unsigned long pll_ring_off    : 1;
 } __attribute__((packed));
 
 union pll_cntl_u {
-     unsigned long val : 32;
-     struct pll_cntl_t f;
+       unsigned long val : 32;
+       struct pll_cntl_t f;
 } __attribute__((packed));
 
 struct sclk_cntl_t {
-     unsigned long sclk_src_sel        : 2;
-     unsigned long                                     : 2;
-     unsigned long sclk_post_div_fast   : 4;
-     unsigned long sclk_clkon_hys      : 3;
-     unsigned long sclk_post_div_slow   : 4;
-     unsigned long disp_cg_ok2switch_en : 1;
-     unsigned long sclk_force_reg      : 1;
-     unsigned long sclk_force_disp     : 1;
-     unsigned long sclk_force_mc       : 1;
-     unsigned long sclk_force_extmc    : 1;
-     unsigned long sclk_force_cp       : 1;
-     unsigned long sclk_force_e2       : 1;
-     unsigned long sclk_force_e3       : 1;
-     unsigned long sclk_force_idct     : 1;
-     unsigned long sclk_force_bist     : 1;
-     unsigned long busy_extend_cp      : 1;
-     unsigned long busy_extend_e2      : 1;
-     unsigned long busy_extend_e3      : 1;
-     unsigned long busy_extend_idct    : 1;
-     unsigned long                                     : 3;
+       unsigned long sclk_src_sel         : 2;
+       unsigned long                      : 2;
+       unsigned long sclk_post_div_fast   : 4;
+       unsigned long sclk_clkon_hys       : 3;
+       unsigned long sclk_post_div_slow   : 4;
+       unsigned long disp_cg_ok2switch_en : 1;
+       unsigned long sclk_force_reg       : 1;
+       unsigned long sclk_force_disp      : 1;
+       unsigned long sclk_force_mc        : 1;
+       unsigned long sclk_force_extmc     : 1;
+       unsigned long sclk_force_cp        : 1;
+       unsigned long sclk_force_e2        : 1;
+       unsigned long sclk_force_e3        : 1;
+       unsigned long sclk_force_idct      : 1;
+       unsigned long sclk_force_bist      : 1;
+       unsigned long busy_extend_cp       : 1;
+       unsigned long busy_extend_e2       : 1;
+       unsigned long busy_extend_e3       : 1;
+       unsigned long busy_extend_idct     : 1;
+       unsigned long                      : 3;
 } __attribute__((packed));
 
 union sclk_cntl_u {
-     unsigned long val : 32;
-     struct sclk_cntl_t f;
+       unsigned long val : 32;
+       struct sclk_cntl_t f;
 } __attribute__((packed));
 
 struct pclk_cntl_t {
-     unsigned long pclk_src_sel     : 2;
-     unsigned long                             : 2;
-     unsigned long pclk_post_div    : 4;
-     unsigned long                             : 8;
-     unsigned long pclk_force_disp  : 1;
-     unsigned long                             : 15;
+       unsigned long pclk_src_sel     : 2;
+       unsigned long                  : 2;
+       unsigned long pclk_post_div    : 4;
+       unsigned long                  : 8;
+       unsigned long pclk_force_disp  : 1;
+       unsigned long                  : 15;
 } __attribute__((packed));
 
 union pclk_cntl_u {
-     unsigned long val : 32;
-     struct pclk_cntl_t f;
+       unsigned long val : 32;
+       struct pclk_cntl_t f;
 } __attribute__((packed));
 
+
+#define TESTCLK_SRC_PLL   0x01
+#define TESTCLK_SRC_SCLK  0x02
+#define TESTCLK_SRC_PCLK  0x03
+/* 4 and 5 seem to by XTAL/M */
+#define TESTCLK_SRC_XTAL  0x06
+
 struct clk_test_cntl_t {
-     unsigned long testclk_sel      : 4;
-     unsigned long                             : 3;
-     unsigned long start_check_freq : 1;
-     unsigned long tstcount_rst     : 1;
-     unsigned long                             : 15;
-     unsigned long test_count       : 8;
+       unsigned long testclk_sel      : 4;
+       unsigned long                  : 3;
+       unsigned long start_check_freq : 1;
+       unsigned long tstcount_rst     : 1;
+       unsigned long                  : 15;
+       unsigned long test_count       : 8;
 } __attribute__((packed));
 
 union clk_test_cntl_u {
-     unsigned long val : 32;
-     struct clk_test_cntl_t f;
+       unsigned long val : 32;
+       struct clk_test_cntl_t f;
 } __attribute__((packed));
 
 struct pwrmgt_cntl_t {
-     unsigned long pwm_enable          : 1;
-     unsigned long                                     : 1;
-     unsigned long pwm_mode_req         : 2;
-     unsigned long pwm_wakeup_cond      : 2;
-     unsigned long pwm_fast_noml_hw_en  : 1;
-     unsigned long pwm_noml_fast_hw_en  : 1;
-     unsigned long pwm_fast_noml_cond   : 4;
-     unsigned long pwm_noml_fast_cond   : 4;
-     unsigned long pwm_idle_timer      : 8;
-     unsigned long pwm_busy_timer      : 8;
+       unsigned long pwm_enable           : 1;
+       unsigned long                      : 1;
+       unsigned long pwm_mode_req         : 2;
+       unsigned long pwm_wakeup_cond      : 2;
+       unsigned long pwm_fast_noml_hw_en  : 1;
+       unsigned long pwm_noml_fast_hw_en  : 1;
+       unsigned long pwm_fast_noml_cond   : 4;
+       unsigned long pwm_noml_fast_cond   : 4;
+       unsigned long pwm_idle_timer       : 8;
+       unsigned long pwm_busy_timer       : 8;
 } __attribute__((packed));
 
 union pwrmgt_cntl_u {
-     unsigned long val : 32;
-     struct pwrmgt_cntl_t f;
+       unsigned long val : 32;
+       struct pwrmgt_cntl_t f;
 } __attribute__((packed));
 
 #endif
index ed78d24ee4263fcfc2495b7f0efbdd6af561c10d..5e817902cb3b408db8c02467a47b856d64eb8b09 100644 (file)
@@ -382,10 +382,8 @@ config QUOTA
          usage (also called disk quotas). Currently, it works for the
          ext2, ext3, and reiserfs file system. ext3 also supports journalled
          quotas for which you don't need to run quotacheck(8) after an unclean
-         shutdown. You need additional software in order to use quota support
-         (you can download sources from
-         <http://www.sf.net/projects/linuxquota/>). For further details, read
-         the Quota mini-HOWTO, available from
+         shutdown.
+         For further details, read the Quota mini-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>, or the documentation provided
          with the quota tools. Probably the quota support is only useful for
          multi user systems. If unsure, say N.
@@ -403,8 +401,7 @@ config QFMT_V2
        depends on QUOTA
        help
          This quota format allows using quotas with 32-bit UIDs/GIDs. If you
-         need this functionality say Y here. Note that you will need recent
-         quota utilities (>= 3.01) for new quota format with this kernel.
+         need this functionality say Y here.
 
 config QUOTACTL
        bool
@@ -816,6 +813,18 @@ config RAMFS
          To compile this as a module, choose M here: the module will be called
          ramfs.
 
+config RELAYFS_FS
+       tristate "Relayfs file system support"
+       ---help---
+         Relayfs is a high-speed data relay filesystem designed to provide
+         an efficient mechanism for tools and facilities to relay large
+         amounts of data from kernel space to user space.
+
+         To compile this code as a module, choose M here: the module will be
+         called relayfs.
+
+         If unsure, say N.
+
 endmenu
 
 menu "Miscellaneous filesystems"
index cf95eb894fd53776b3429354834aac373f0e8170..15158309dee4ae42d2caf7429c274e20945efcbf 100644 (file)
@@ -90,6 +90,7 @@ obj-$(CONFIG_AUTOFS_FS)               += autofs/
 obj-$(CONFIG_AUTOFS4_FS)       += autofs4/
 obj-$(CONFIG_ADFS_FS)          += adfs/
 obj-$(CONFIG_UDF_FS)           += udf/
+obj-$(CONFIG_RELAYFS_FS)       += relayfs/
 obj-$(CONFIG_SUN_OPENPROMFS)   += openpromfs/
 obj-$(CONFIG_JFS_FS)           += jfs/
 obj-$(CONFIG_XFS_FS)           += xfs/
index 1f2d4649b188015076353340055a4ebdd1e0a6b1..bf3ec9d2b54c6d30468df71e003b000be3539a4e 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -104,18 +104,22 @@ static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int
        return bvl;
 }
 
-/*
- * default destructor for a bio allocated with bio_alloc_bioset()
- */
-static void bio_destructor(struct bio *bio)
+void bio_free(struct bio *bio, struct bio_set *bio_set)
 {
        const int pool_idx = BIO_POOL_IDX(bio);
-       struct bio_set *bs = bio->bi_set;
 
        BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
 
-       mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]);
-       mempool_free(bio, bs->bio_pool);
+       mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
+       mempool_free(bio, bio_set->bio_pool);
+}
+
+/*
+ * default destructor for a bio allocated with bio_alloc_bioset()
+ */
+static void bio_fs_destructor(struct bio *bio)
+{
+       bio_free(bio, fs_bio_set);
 }
 
 inline void bio_init(struct bio *bio)
@@ -171,8 +175,6 @@ struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, stru
                        bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
                }
                bio->bi_io_vec = bvl;
-               bio->bi_destructor = bio_destructor;
-               bio->bi_set = bs;
        }
 out:
        return bio;
@@ -180,7 +182,12 @@ out:
 
 struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs)
 {
-       return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+       struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+
+       if (bio)
+               bio->bi_destructor = bio_fs_destructor;
+
+       return bio;
 }
 
 void zero_fill_bio(struct bio *bio)
@@ -273,8 +280,10 @@ struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask)
 {
        struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
 
-       if (b)
+       if (b) {
+               b->bi_destructor = bio_fs_destructor;
                __bio_clone(b, bio);
+       }
 
        return b;
 }
@@ -1075,6 +1084,7 @@ subsys_initcall(init_bio);
 
 EXPORT_SYMBOL(bio_alloc);
 EXPORT_SYMBOL(bio_put);
+EXPORT_SYMBOL(bio_free);
 EXPORT_SYMBOL(bio_endio);
 EXPORT_SYMBOL(bio_init);
 EXPORT_SYMBOL(__bio_clone);
index 6a25d7df89b176db6bb7163517538476398a9af4..1c62203a4906ec1c7ba2ca9ede00e2a2c498aeda 100644 (file)
@@ -917,8 +917,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
                                 * contents - it is a noop if I/O is still in
                                 * flight on potentially older contents.
                                 */
-                               wait_on_buffer(bh);
-                               ll_rw_block(WRITE, 1, &bh);
+                               ll_rw_block(SWRITE, 1, &bh);
                                brelse(bh);
                                spin_lock(lock);
                        }
@@ -2793,21 +2792,22 @@ int submit_bh(int rw, struct buffer_head * bh)
 
 /**
  * ll_rw_block: low-level access to block devices (DEPRECATED)
- * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
+ * @rw: whether to %READ or %WRITE or %SWRITE or maybe %READA (readahead)
  * @nr: number of &struct buffer_heads in the array
  * @bhs: array of pointers to &struct buffer_head
  *
- * ll_rw_block() takes an array of pointers to &struct buffer_heads,
- * and requests an I/O operation on them, either a %READ or a %WRITE.
- * The third %READA option is described in the documentation for
- * generic_make_request() which ll_rw_block() calls.
+ * ll_rw_block() takes an array of pointers to &struct buffer_heads, and
+ * requests an I/O operation on them, either a %READ or a %WRITE.  The third
+ * %SWRITE is like %WRITE only we make sure that the *current* data in buffers
+ * are sent to disk. The fourth %READA option is described in the documentation
+ * for generic_make_request() which ll_rw_block() calls.
  *
  * This function drops any buffer that it cannot get a lock on (with the
- * BH_Lock state bit), any buffer that appears to be clean when doing a
- * write request, and any buffer that appears to be up-to-date when doing
- * read request.  Further it marks as clean buffers that are processed for
- * writing (the buffer cache won't assume that they are actually clean until
- * the buffer gets unlocked).
+ * BH_Lock state bit) unless SWRITE is required, any buffer that appears to be
+ * clean when doing a write request, and any buffer that appears to be
+ * up-to-date when doing read request.  Further it marks as clean buffers that
+ * are processed for writing (the buffer cache won't assume that they are
+ * actually clean until the buffer gets unlocked).
  *
  * ll_rw_block sets b_end_io to simple completion handler that marks
  * the buffer up-to-date (if approriate), unlocks the buffer and wakes
@@ -2823,11 +2823,13 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
        for (i = 0; i < nr; i++) {
                struct buffer_head *bh = bhs[i];
 
-               if (test_set_buffer_locked(bh))
+               if (rw == SWRITE)
+                       lock_buffer(bh);
+               else if (test_set_buffer_locked(bh))
                        continue;
 
                get_bh(bh);
-               if (rw == WRITE) {
+               if (rw == WRITE || rw == SWRITE) {
                        if (test_clear_buffer_dirty(bh)) {
                                bh->b_end_io = end_buffer_write_sync;
                                submit_bh(WRITE, bh);
@@ -3046,10 +3048,9 @@ struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags)
 {
        struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags);
        if (ret) {
-               preempt_disable();
-               __get_cpu_var(bh_accounting).nr++;
+               get_cpu_var(bh_accounting).nr++;
                recalc_bh_state();
-               preempt_enable();
+               put_cpu_var(bh_accounting);
        }
        return ret;
 }
@@ -3059,10 +3060,9 @@ void free_buffer_head(struct buffer_head *bh)
 {
        BUG_ON(!list_empty(&bh->b_assoc_buffers));
        kmem_cache_free(bh_cachep, bh);
-       preempt_disable();
-       __get_cpu_var(bh_accounting).nr--;
+       get_cpu_var(bh_accounting).nr--;
        recalc_bh_state();
-       preempt_enable();
+       put_cpu_var(bh_accounting);
 }
 EXPORT_SYMBOL(free_buffer_head);
 
index e568cc47a7f93005518d1470696f89ee1444a1ae..3217ac5f6bd7aa03277307aa66a5f64573681c49 100644 (file)
@@ -836,7 +836,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                /* go from value to value + temp_len condensing 
                                double commas to singles. Note that this ends up
                                allocating a few bytes too many, which is ok */
-                               vol->password = kcalloc(1, temp_len, GFP_KERNEL);
+                               vol->password = kzalloc(temp_len, GFP_KERNEL);
                                if(vol->password == NULL) {
                                        printk("CIFS: no memory for pass\n");
                                        return 1;
@@ -851,7 +851,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                }
                                vol->password[j] = 0;
                        } else {
-                               vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
+                               vol->password = kzalloc(temp_len+1, GFP_KERNEL);
                                if(vol->password == NULL) {
                                        printk("CIFS: no memory for pass\n");
                                        return 1;
@@ -1317,7 +1317,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                sessinit is sent but no second negprot */
                struct rfc1002_session_packet * ses_init_buf;
                struct smb_hdr * smb_buf;
-               ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+               ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
                if(ses_init_buf) {
                        ses_init_buf->trailer.session_req.called_len = 32;
                        rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
@@ -1964,7 +1964,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
-                               ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+                               ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
                                if(ses->serverOS == NULL)
                                        goto sesssetup_nomem;
                                cifs_strfromUCS_le(ses->serverOS,
@@ -1976,7 +1976,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                if (remaining_words > 0) {
                                        len = UniStrnlen((wchar_t *)bcc_ptr,
                                                         remaining_words-1);
-                                       ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
+                                       ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
                                        cifs_strfromUCS_le(ses->serverNOS,
@@ -1994,7 +1994,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
                                                ses->serverDomain =
-                                                   kcalloc(1, 2*(len+1),GFP_KERNEL);
+                                                   kzalloc(2*(len+1),GFP_KERNEL);
                                                if(ses->serverDomain == NULL)
                                                        goto sesssetup_nomem;
                                                cifs_strfromUCS_le(ses->serverDomain,
@@ -2005,22 +2005,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        } /* else no more room so create dummy domain string */
                                        else
                                                ses->serverDomain = 
-                                                       kcalloc(1, 2, GFP_KERNEL);
+                                                       kzalloc(2, GFP_KERNEL);
                                } else {        /* no room so create dummy domain and NOS string */
                                        /* if these kcallocs fail not much we
                                           can do, but better to not fail the
                                           sesssetup itself */
                                        ses->serverDomain =
-                                           kcalloc(1, 2, GFP_KERNEL);
+                                           kzalloc(2, GFP_KERNEL);
                                        ses->serverNOS =
-                                           kcalloc(1, 2, GFP_KERNEL);
+                                           kzalloc(2, GFP_KERNEL);
                                }
                        } else {        /* ASCII */
                                len = strnlen(bcc_ptr, 1024);
                                if (((long) bcc_ptr + len) - (long)
                                    pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
-                                       ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+                                       ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverOS == NULL)
                                                goto sesssetup_nomem;
                                        strncpy(ses->serverOS,bcc_ptr, len);
@@ -2030,7 +2030,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
-                                       ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+                                       ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
                                        strncpy(ses->serverNOS, bcc_ptr, len);
@@ -2039,7 +2039,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
-                                       ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
+                                       ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverDomain == NULL)
                                                goto sesssetup_nomem;
                                        strncpy(ses->serverDomain, bcc_ptr, len);
@@ -2240,7 +2240,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
                                        ses->serverOS =
-                                           kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+                                           kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
                                                           (wchar_t *)
                                                           bcc_ptr, len,
@@ -2254,7 +2254,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                 remaining_words
                                                                 - 1);
                                                ses->serverNOS =
-                                                   kcalloc(1, 2 * (len + 1),
+                                                   kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
                                                cifs_strfromUCS_le(ses->serverNOS,
                                                                   (wchar_t *)bcc_ptr,
@@ -2267,7 +2267,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
                             /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-                                                       ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
+                                                       ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
                                                        cifs_strfromUCS_le(ses->serverDomain,
                                                             (wchar_t *)bcc_ptr, 
                                  len,
@@ -2278,10 +2278,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                } /* else no more room so create dummy domain string */
                                                else
                                                        ses->serverDomain =
-                                                           kcalloc(1, 2,GFP_KERNEL);
+                                                           kzalloc(2,GFP_KERNEL);
                                        } else {        /* no room so create dummy domain and NOS string */
-                                               ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
-                                               ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+                                               ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
 
@@ -2289,7 +2289,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (((long) bcc_ptr + len) - (long)
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
-                                               ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
+                                               ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverOS, bcc_ptr, len);
 
                                                bcc_ptr += len;
@@ -2297,14 +2297,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
-                                               ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+                                               ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);
                                                bcc_ptr += len;
                                                bcc_ptr[0] = 0;
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
-                                               ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
+                                               ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
                                                bcc_ptr[0] = 0;
@@ -2554,7 +2554,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
                                        ses->serverOS =
-                                           kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+                                           kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
                                                           (wchar_t *)
                                                           bcc_ptr, len,
@@ -2569,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                                 remaining_words
                                                                 - 1);
                                                ses->serverNOS =
-                                                   kcalloc(1, 2 * (len + 1),
+                                                   kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
                                                cifs_strfromUCS_le(ses->
                                                                   serverNOS,
@@ -2586,7 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
                                                        ses->serverDomain =
-                                                           kcalloc(1, 2 *
+                                                           kzalloc(2 *
                                                                    (len +
                                                                     1),
                                                                    GFP_KERNEL);
@@ -2612,13 +2612,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                } /* else no more room so create dummy domain string */
                                                else
                                                        ses->serverDomain =
-                                                           kcalloc(1, 2,
+                                                           kzalloc(2,
                                                                    GFP_KERNEL);
                                        } else {        /* no room so create dummy domain and NOS string */
                                                ses->serverDomain =
-                                                   kcalloc(1, 2, GFP_KERNEL);
+                                                   kzalloc(2, GFP_KERNEL);
                                                ses->serverNOS =
-                                                   kcalloc(1, 2, GFP_KERNEL);
+                                                   kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
                                        len = strnlen(bcc_ptr, 1024);
@@ -2626,7 +2626,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
                                                ses->serverOS =
-                                                   kcalloc(1, len + 1,
+                                                   kzalloc(len + 1,
                                                            GFP_KERNEL);
                                                strncpy(ses->serverOS,
                                                        bcc_ptr, len);
@@ -2637,7 +2637,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
                                                len = strnlen(bcc_ptr, 1024);
                                                ses->serverNOS =
-                                                   kcalloc(1, len + 1,
+                                                   kzalloc(len + 1,
                                                            GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -2646,7 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
                                                len = strnlen(bcc_ptr, 1024);
                                                ses->serverDomain =
-                                                   kcalloc(1, len + 1,
+                                                   kzalloc(len + 1,
                                                            GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);       
                                                bcc_ptr += len;
@@ -2948,7 +2948,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
                                        ses->serverOS =
-                                           kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+                                           kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
                                                           (wchar_t *)
                                                           bcc_ptr, len,
@@ -2963,7 +2963,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                 remaining_words
                                                                 - 1);
                                                ses->serverNOS =
-                                                   kcalloc(1, 2 * (len + 1),
+                                                   kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
                                                cifs_strfromUCS_le(ses->
                                                                   serverNOS,
@@ -2979,7 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
      /* last string not always null terminated (e.g. for Windows XP & 2000) */
                                                        ses->serverDomain =
-                                                           kcalloc(1, 2 *
+                                                           kzalloc(2 *
                                                                    (len +
                                                                     1),
                                                                    GFP_KERNEL);
@@ -3004,17 +3004,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                            = 0;
                                                } /* else no more room so create dummy domain string */
                                                else
-                                                       ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
+                                                       ses->serverDomain = kzalloc(2,GFP_KERNEL);
                                        } else {  /* no room so create dummy domain and NOS string */
-                                               ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
-                                               ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+                                               ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
                                        len = strnlen(bcc_ptr, 1024);
                                        if (((long) bcc_ptr + len) - 
                         (long) pByteArea(smb_buffer_response) 
                             <= BCC(smb_buffer_response)) {
-                                               ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+                                               ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverOS,bcc_ptr, len);
 
                                                bcc_ptr += len;
@@ -3022,14 +3022,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
-                                               ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
+                                               ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);  
                                                bcc_ptr += len;
                                                bcc_ptr[0] = 0;
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
-                                               ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
+                                               ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
                                                bcc_ptr[0] = 0;
@@ -3141,7 +3141,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                                if(tcon->nativeFileSystem)
                                        kfree(tcon->nativeFileSystem);
                                tcon->nativeFileSystem =
-                                   kcalloc(1, length + 2, GFP_KERNEL);
+                                   kzalloc(length + 2, GFP_KERNEL);
                                cifs_strfromUCS_le(tcon->nativeFileSystem,
                                                   (wchar_t *) bcc_ptr,
                                                   length, nls_codepage);
@@ -3159,7 +3159,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                                if(tcon->nativeFileSystem)
                                        kfree(tcon->nativeFileSystem);
                                tcon->nativeFileSystem =
-                                   kcalloc(1, length + 1, GFP_KERNEL);
+                                   kzalloc(length + 1, GFP_KERNEL);
                                strncpy(tcon->nativeFileSystem, bcc_ptr,
                                        length);
                        }
index 3f3538d4a1fad105c0a776ef5f6d6e18fef0ff6c..d335269bd91cfe5b626aba8a45eae25136b450dc 100644 (file)
@@ -145,24 +145,23 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                return -ENOMEM;
        }
 
-       if(nd) {
-               if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
-                       desiredAccess = GENERIC_READ;
-               else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
-                       desiredAccess = GENERIC_WRITE;
-                       write_only = TRUE;
-               } else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
-                       /* GENERIC_ALL is too much permission to request */
-                       /* can cause unnecessary access denied on create */
-                       /* desiredAccess = GENERIC_ALL; */
-                       desiredAccess = GENERIC_READ | GENERIC_WRITE;
+       if(nd && (nd->flags & LOOKUP_OPEN)) {
+               int oflags = nd->intent.open.flags;
+
+               desiredAccess = 0;
+               if (oflags & FMODE_READ)
+                       desiredAccess |= GENERIC_READ;
+               if (oflags & FMODE_WRITE) {
+                       desiredAccess |= GENERIC_WRITE;
+                       if (!(oflags & FMODE_READ))
+                               write_only = TRUE;
                }
 
-               if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
                        disposition = FILE_CREATE;
-               else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+               else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
                        disposition = FILE_OVERWRITE_IF;
-               else if((nd->intent.open.flags & O_CREAT) == O_CREAT)
+               else if((oflags & O_CREAT) == O_CREAT)
                        disposition = FILE_OPEN_IF;
                else {
                        cFYI(1,("Create flag not set in create function"));
index 6b06b6bae35e52cd078efaaabe19198007a4b36d..8c665705c6a07beea9a4ead55a2184524f7ed41f 100644 (file)
@@ -310,96 +310,6 @@ static int __init init_sys32_ioctl(void)
 
 __initcall(init_sys32_ioctl);
 
-int register_ioctl32_conversion(unsigned int cmd,
-                               ioctl_trans_handler_t handler)
-{
-       struct ioctl_trans *t;
-       struct ioctl_trans *new_t;
-       unsigned long hash = ioctl32_hash(cmd);
-
-       new_t = kmalloc(sizeof(*new_t), GFP_KERNEL);
-       if (!new_t)
-               return -ENOMEM;
-
-       down_write(&ioctl32_sem);
-       for (t = ioctl32_hash_table[hash]; t; t = t->next) {
-               if (t->cmd == cmd) {
-                       printk(KERN_ERR "Trying to register duplicated ioctl32 "
-                                       "handler %x\n", cmd);
-                       up_write(&ioctl32_sem);
-                       kfree(new_t);
-                       return -EINVAL; 
-               }
-       }
-       new_t->next = NULL;
-       new_t->cmd = cmd;
-       new_t->handler = handler;
-       ioctl32_insert_translation(new_t);
-
-       up_write(&ioctl32_sem);
-       return 0;
-}
-EXPORT_SYMBOL(register_ioctl32_conversion);
-
-static inline int builtin_ioctl(struct ioctl_trans *t)
-{ 
-       return t >= ioctl_start && t < (ioctl_start + ioctl_table_size);
-} 
-
-/* Problem: 
-   This function cannot unregister duplicate ioctls, because they are not
-   unique.
-   When they happen we need to extend the prototype to pass the handler too. */
-
-int unregister_ioctl32_conversion(unsigned int cmd)
-{
-       unsigned long hash = ioctl32_hash(cmd);
-       struct ioctl_trans *t, *t1;
-
-       down_write(&ioctl32_sem);
-
-       t = ioctl32_hash_table[hash];
-       if (!t) { 
-               up_write(&ioctl32_sem);
-               return -EINVAL;
-       } 
-
-       if (t->cmd == cmd) { 
-               if (builtin_ioctl(t)) {
-                       printk("%p tried to unregister builtin ioctl %x\n",
-                              __builtin_return_address(0), cmd);
-               } else { 
-                       ioctl32_hash_table[hash] = t->next;
-                       up_write(&ioctl32_sem);
-                       kfree(t);
-                       return 0;
-               }
-       } 
-       while (t->next) {
-               t1 = t->next;
-               if (t1->cmd == cmd) { 
-                       if (builtin_ioctl(t1)) {
-                               printk("%p tried to unregister builtin "
-                                       "ioctl %x\n",
-                                       __builtin_return_address(0), cmd);
-                               goto out;
-                       } else { 
-                               t->next = t1->next;
-                               up_write(&ioctl32_sem);
-                               kfree(t1);
-                               return 0;
-                       }
-               }
-               t = t1;
-       }
-       printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n",
-                               cmd);
-out:
-       up_write(&ioctl32_sem);
-       return -EINVAL;
-}
-EXPORT_SYMBOL(unregister_ioctl32_conversion); 
-
 static void compat_ioctl_error(struct file *filp, unsigned int fd,
                unsigned int cmd, unsigned long arg)
 {
@@ -720,14 +630,14 @@ compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb)
 struct compat_ncp_mount_data {
        compat_int_t version;
        compat_uint_t ncp_fd;
-       compat_uid_t mounted_uid;
+       __compat_uid_t mounted_uid;
        compat_pid_t wdog_pid;
        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
        compat_uint_t time_out;
        compat_uint_t retry_count;
        compat_uint_t flags;
-       compat_uid_t uid;
-       compat_gid_t gid;
+       __compat_uid_t uid;
+       __compat_gid_t gid;
        compat_mode_t file_mode;
        compat_mode_t dir_mode;
 };
@@ -784,9 +694,9 @@ static void *do_ncp_super_data_conv(void *raw_data)
 
 struct compat_smb_mount_data {
        compat_int_t version;
-       compat_uid_t mounted_uid;
-       compat_uid_t uid;
-       compat_gid_t gid;
+       __compat_uid_t mounted_uid;
+       __compat_uid_t uid;
+       __compat_gid_t gid;
        compat_mode_t file_mode;
        compat_mode_t dir_mode;
 };
@@ -1364,6 +1274,16 @@ out:
        return ret;
 }
 
+/*
+ * Exactly like fs/open.c:sys_open(), except that it doesn't set the
+ * O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_open(const char __user *filename, int flags, int mode)
+{
+       return do_sys_open(filename, flags, mode);
+}
+
 /*
  * compat_count() counts the number of arguments/envelopes. It is basically
  * a copy of count() from fs/exec.c, except that it works with 32 bit argv
@@ -1808,8 +1728,8 @@ struct compat_nfsctl_export {
        compat_dev_t    ex32_dev;
        compat_ino_t    ex32_ino;
        compat_int_t    ex32_flags;
-       compat_uid_t    ex32_anon_uid;
-       compat_gid_t    ex32_anon_gid;
+       __compat_uid_t  ex32_anon_uid;
+       __compat_gid_t  ex32_anon_gid;
 };
 
 struct compat_nfsctl_fdparm {
index 6c285efa20043cb8dbb4692d7a53f5ff9455bac0..7fe85415ae7c2d7aa7788bb91f5ccb4d412b0612 100644 (file)
@@ -39,12 +39,47 @@ static DECLARE_MUTEX(read_mutex);
 #define CRAMINO(x)     ((x)->offset?(x)->offset<<2:1)
 #define OFFSET(x)      ((x)->i_ino)
 
-static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
+
+static int cramfs_iget5_test(struct inode *inode, void *opaque)
+{
+       struct cramfs_inode *cramfs_inode = opaque;
+
+       if (inode->i_ino != CRAMINO(cramfs_inode))
+               return 0; /* does not match */
+
+       if (inode->i_ino != 1)
+               return 1;
+
+       /* all empty directories, char, block, pipe, and sock, share inode #1 */
+
+       if ((inode->i_mode != cramfs_inode->mode) ||
+           (inode->i_gid != cramfs_inode->gid) ||
+           (inode->i_uid != cramfs_inode->uid))
+               return 0; /* does not match */
+
+       if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
+           (inode->i_rdev != old_decode_dev(cramfs_inode->size)))
+               return 0; /* does not match */
+
+       return 1; /* matches */
+}
+
+static int cramfs_iget5_set(struct inode *inode, void *opaque)
+{
+       struct cramfs_inode *cramfs_inode = opaque;
+       inode->i_ino = CRAMINO(cramfs_inode);
+       return 0;
+}
+
+static struct inode *get_cramfs_inode(struct super_block *sb,
+                               struct cramfs_inode * cramfs_inode)
 {
-       struct inode * inode = new_inode(sb);
+       struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
+                                           cramfs_iget5_test, cramfs_iget5_set,
+                                           cramfs_inode);
        static struct timespec zerotime;
 
-       if (inode) {
+       if (inode && (inode->i_state & I_NEW)) {
                inode->i_mode = cramfs_inode->mode;
                inode->i_uid = cramfs_inode->uid;
                inode->i_size = cramfs_inode->size;
@@ -58,7 +93,6 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
                   but it's the best we can do without reading the directory
                   contents.  1 yields the right result in GNU find, even
                   without -noleaf option. */
-               insert_inode_hash(inode);
                if (S_ISREG(inode->i_mode)) {
                        inode->i_fop = &generic_ro_fops;
                        inode->i_data.a_ops = &cramfs_aops;
@@ -74,6 +108,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
                        init_special_inode(inode, inode->i_mode,
                                old_decode_dev(cramfs_inode->size));
                }
+               unlock_new_inode(inode);
        }
        return inode;
 }
index dcfe331dc4c4816d8a208ecccf625439c94cc8cc..3c0c7c6a5b44004cd02de7dae02343b6674ed672 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
@@ -27,6 +28,8 @@
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
 #include <linux/vfs.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 #include "ext2.h"
 #include "xattr.h"
@@ -201,6 +204,26 @@ static void ext2_clear_inode(struct inode *inode)
 #endif
 }
 
+static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+       struct ext2_sb_info *sbi = EXT2_SB(vfs->mnt_sb);
+
+       if (sbi->s_mount_opt & EXT2_MOUNT_GRPID)
+               seq_puts(seq, ",grpid");
+       else
+               seq_puts(seq, ",nogrpid");
+
+#if defined(CONFIG_QUOTA)
+       if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)
+               seq_puts(seq, ",usrquota");
+
+       if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA)
+               seq_puts(seq, ",grpquota");
+#endif
+
+       return 0;
+}
+
 #ifdef CONFIG_QUOTA
 static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off);
 static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
@@ -218,6 +241,7 @@ static struct super_operations ext2_sops = {
        .statfs         = ext2_statfs,
        .remount_fs     = ext2_remount,
        .clear_inode    = ext2_clear_inode,
+       .show_options   = ext2_show_options,
 #ifdef CONFIG_QUOTA
        .quota_read     = ext2_quota_read,
        .quota_write    = ext2_quota_write,
@@ -256,10 +280,11 @@ static unsigned long get_sb_block(void **data)
 
 enum {
        Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
-       Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
-       Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
-       Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
-       Opt_ignore, Opt_err,
+       Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
+       Opt_err_ro, Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug,
+       Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
+       Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
+       Opt_usrquota, Opt_grpquota
 };
 
 static match_table_t tokens = {
@@ -288,10 +313,10 @@ static match_table_t tokens = {
        {Opt_acl, "acl"},
        {Opt_noacl, "noacl"},
        {Opt_xip, "xip"},
-       {Opt_ignore, "grpquota"},
+       {Opt_grpquota, "grpquota"},
        {Opt_ignore, "noquota"},
-       {Opt_ignore, "quota"},
-       {Opt_ignore, "usrquota"},
+       {Opt_quota, "quota"},
+       {Opt_usrquota, "usrquota"},
        {Opt_err, NULL}
 };
 
@@ -406,6 +431,26 @@ static int parse_options (char * options,
                        printk("EXT2 xip option not supported\n");
 #endif
                        break;
+
+#if defined(CONFIG_QUOTA)
+               case Opt_quota:
+               case Opt_usrquota:
+                       set_opt(sbi->s_mount_opt, USRQUOTA);
+                       break;
+
+               case Opt_grpquota:
+                       set_opt(sbi->s_mount_opt, GRPQUOTA);
+                       break;
+#else
+               case Opt_quota:
+               case Opt_usrquota:
+               case Opt_grpquota:
+                       printk(KERN_ERR
+                               "EXT2-fs: quota operations not supported.\n");
+
+                       break;
+#endif
+
                case Opt_ignore:
                        break;
                default:
index 3c3c6e399fb3df167e7d45936df8e290227d0262..a93c3609025de91984e1673610c0dcc74adfaad0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include "xattr.h"
 #include "acl.h"
@@ -509,8 +510,41 @@ static void ext3_clear_inode(struct inode *inode)
        kfree(rsv);
 }
 
-#ifdef CONFIG_QUOTA
+static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+       struct ext3_sb_info *sbi = EXT3_SB(vfs->mnt_sb);
+
+       if (sbi->s_mount_opt & EXT3_MOUNT_JOURNAL_DATA)
+               seq_puts(seq, ",data=journal");
+
+       if (sbi->s_mount_opt & EXT3_MOUNT_ORDERED_DATA)
+               seq_puts(seq, ",data=ordered");
+
+       if (sbi->s_mount_opt & EXT3_MOUNT_WRITEBACK_DATA)
+               seq_puts(seq, ",data=writeback");
+
+#if defined(CONFIG_QUOTA)
+       if (sbi->s_jquota_fmt)
+               seq_printf(seq, ",jqfmt=%s",
+               (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
+
+       if (sbi->s_qf_names[USRQUOTA])
+               seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+
+       if (sbi->s_qf_names[GRPQUOTA])
+               seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
 
+       if (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA)
+               seq_puts(seq, ",usrquota");
+
+       if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
+               seq_puts(seq, ",grpquota");
+#endif
+
+       return 0;
+}
+
+#ifdef CONFIG_QUOTA
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
 
@@ -569,6 +603,7 @@ static struct super_operations ext3_sops = {
        .statfs         = ext3_statfs,
        .remount_fs     = ext3_remount,
        .clear_inode    = ext3_clear_inode,
+       .show_options   = ext3_show_options,
 #ifdef CONFIG_QUOTA
        .quota_read     = ext3_quota_read,
        .quota_write    = ext3_quota_write,
@@ -590,7 +625,8 @@ enum {
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
-       Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_grpquota
 };
 
 static match_table_t tokens = {
@@ -634,10 +670,10 @@ static match_table_t tokens = {
        {Opt_grpjquota, "grpjquota=%s"},
        {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
        {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
-       {Opt_quota, "grpquota"},
+       {Opt_grpquota, "grpquota"},
        {Opt_noquota, "noquota"},
        {Opt_quota, "quota"},
-       {Opt_quota, "usrquota"},
+       {Opt_usrquota, "usrquota"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
@@ -903,7 +939,13 @@ clear_qf_name:
                        sbi->s_jquota_fmt = QFMT_VFS_V0;
                        break;
                case Opt_quota:
+               case Opt_usrquota:
                        set_opt(sbi->s_mount_opt, QUOTA);
+                       set_opt(sbi->s_mount_opt, USRQUOTA);
+                       break;
+               case Opt_grpquota:
+                       set_opt(sbi->s_mount_opt, QUOTA);
+                       set_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
                case Opt_noquota:
                        if (sb_any_quota_enabled(sb)) {
@@ -912,8 +954,13 @@ clear_qf_name:
                                return 0;
                        }
                        clear_opt(sbi->s_mount_opt, QUOTA);
+                       clear_opt(sbi->s_mount_opt, USRQUOTA);
+                       clear_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
 #else
+               case Opt_quota:
+               case Opt_usrquota:
+               case Opt_grpquota:
                case Opt_usrjquota:
                case Opt_grpjquota:
                case Opt_offusrjquota:
@@ -924,7 +971,6 @@ clear_qf_name:
                                "EXT3-fs: journalled quota options not "
                                "supported.\n");
                        break;
-               case Opt_quota:
                case Opt_noquota:
                        break;
 #endif
@@ -962,14 +1008,38 @@ clear_qf_name:
                }
        }
 #ifdef CONFIG_QUOTA
-       if (!sbi->s_jquota_fmt && (sbi->s_qf_names[USRQUOTA] ||
-           sbi->s_qf_names[GRPQUOTA])) {
-               printk(KERN_ERR
-                       "EXT3-fs: journalled quota format not specified.\n");
-               return 0;
+       if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+               if ((sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA) &&
+                    sbi->s_qf_names[USRQUOTA])
+                       clear_opt(sbi->s_mount_opt, USRQUOTA);
+
+               if ((sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA) &&
+                    sbi->s_qf_names[GRPQUOTA])
+                       clear_opt(sbi->s_mount_opt, GRPQUOTA);
+
+               if ((sbi->s_qf_names[USRQUOTA] &&
+                               (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)) ||
+                   (sbi->s_qf_names[GRPQUOTA] &&
+                               (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA))) {
+                       printk(KERN_ERR "EXT3-fs: old and new quota "
+                                       "format mixing.\n");
+                       return 0;
+               }
+
+               if (!sbi->s_jquota_fmt) {
+                       printk(KERN_ERR "EXT3-fs: journalled quota format "
+                                       "not specified.\n");
+                       return 0;
+               }
+       } else {
+               if (sbi->s_jquota_fmt) {
+                       printk(KERN_ERR "EXT3-fs: journalled quota format "
+                                       "specified with no journalling "
+                                       "enabled.\n");
+                       return 0;
+               }
        }
 #endif
-
        return 1;
 }
 
index e5ae1b720dde8b42321235bbb2b3369e017e9d27..895049b2ac9cb65fd58af857e719bc7d8d03115e 100644 (file)
@@ -30,6 +30,29 @@ static inline loff_t fat_make_i_pos(struct super_block *sb,
                | (de - (struct msdos_dir_entry *)bh->b_data);
 }
 
+static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
+                                    sector_t phys)
+{
+       struct super_block *sb = dir->i_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       struct buffer_head *bh;
+       int sec;
+
+       /* This is not a first sector of cluster, or sec_per_clus == 1 */
+       if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1)
+               return;
+       /* root dir of FAT12/FAT16 */
+       if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
+               return;
+
+       bh = sb_getblk(sb, phys);
+       if (bh && !buffer_uptodate(bh)) {
+               for (sec = 0; sec < sbi->sec_per_clus; sec++)
+                       sb_breadahead(sb, phys + sec);
+       }
+       brelse(bh);
+}
+
 /* Returns the inode number of the directory entry at offset pos. If bh is
    non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
    returned in bh.
@@ -58,6 +81,8 @@ next:
        if (err || !phys)
                return -1;      /* beyond EOF or error */
 
+       fat_dir_readahead(dir, iblock, phys);
+
        *bh = sb_bread(sb, phys);
        if (*bh == NULL) {
                printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
@@ -635,8 +660,7 @@ RecEnd:
 EODir:
        filp->f_pos = cpos;
 FillFailed:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
        if (unicode)
                free_page((unsigned long)unicode);
 out:
index 1d3de78e6bc960ddeb2b4b42eed7815c64aca298..43e9e1737de2cb365c954afeddfb64ae0433779b 100644 (file)
@@ -89,7 +89,6 @@ struct file *get_empty_filp(void)
        rwlock_init(&f->f_owner.lock);
        /* f->f_version: 0 */
        INIT_LIST_HEAD(&f->f_list);
-       f->f_maxcount = INT_MAX;
        return f;
 
 over:
index 27f66d3e8a0413091ab58b3f0b85fae788a224fe..6aa6fbe4f8ee9a5397408d59938140e38fa4c084 100644 (file)
@@ -155,7 +155,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 
        sbp->s_flags |= MS_RDONLY;
 
-       infp = kcalloc(1, sizeof(*infp), GFP_KERNEL);
+       infp = kzalloc(sizeof(*infp), GFP_KERNEL);
        if (!infp) {
                printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
                return -ENOMEM;
index a096c5a5666442530eeb208baa4069122511c11d..3d5cdc6847c06f4200b93804710804541a909f67 100644 (file)
@@ -13,8 +13,6 @@
 
 #include "btree.h"
 
-#define REF_PAGES      0
-
 void hfs_bnode_read(struct hfs_bnode *node, void *buf,
                int off, int len)
 {
@@ -289,9 +287,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
                        page_cache_release(page);
                        goto fail;
                }
-#if !REF_PAGES
                page_cache_release(page);
-#endif
                node->page[i] = page;
        }
 
@@ -449,13 +445,6 @@ void hfs_bnode_get(struct hfs_bnode *node)
 {
        if (node) {
                atomic_inc(&node->refcnt);
-#if REF_PAGES
-               {
-               int i;
-               for (i = 0; i < node->tree->pages_per_bnode; i++)
-                       get_page(node->page[i]);
-               }
-#endif
                dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
                       node->tree->cnid, node->this, atomic_read(&node->refcnt));
        }
@@ -472,20 +461,12 @@ void hfs_bnode_put(struct hfs_bnode *node)
                       node->tree->cnid, node->this, atomic_read(&node->refcnt));
                if (!atomic_read(&node->refcnt))
                        BUG();
-               if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
-#if REF_PAGES
-                       for (i = 0; i < tree->pages_per_bnode; i++)
-                               put_page(node->page[i]);
-#endif
+               if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
                        return;
-               }
                for (i = 0; i < tree->pages_per_bnode; i++) {
                        if (!node->page[i])
                                continue;
                        mark_page_accessed(node->page[i]);
-#if REF_PAGES
-                       put_page(node->page[i]);
-#endif
                }
 
                if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
index 65dedefcabfc5fd5fb00d129f7569ec40fe1a819..2fcd679f02383366b7f8774ef2ed00d9fe924727 100644 (file)
  *
  * Given the ID of the parent and the name build a search key.
  */
-void hfs_cat_build_key(btree_key *key, u32 parent, struct qstr *name)
+void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, struct qstr *name)
 {
        key->cat.reserved = 0;
        key->cat.ParID = cpu_to_be32(parent);
        if (name) {
-               hfs_triv2mac(&key->cat.CName, name);
+               hfs_asc2mac(sb, &key->cat.CName, name);
                key->key_len = 6 + key->cat.CName.len;
        } else {
                memset(&key->cat.CName, 0, sizeof(struct hfs_name));
@@ -62,13 +62,14 @@ static int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
        }
 }
 
-static int hfs_cat_build_thread(hfs_cat_rec *rec, int type,
+static int hfs_cat_build_thread(struct super_block *sb,
+                               hfs_cat_rec *rec, int type,
                                u32 parentid, struct qstr *name)
 {
        rec->type = type;
        memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved));
        rec->thread.ParID = cpu_to_be32(parentid);
-       hfs_triv2mac(&rec->thread.CName, name);
+       hfs_asc2mac(sb, &rec->thread.CName, name);
        return sizeof(struct hfs_cat_thread);
 }
 
@@ -93,8 +94,8 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
        sb = dir->i_sb;
        hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
 
-       hfs_cat_build_key(fd.search_key, cnid, NULL);
-       entry_size = hfs_cat_build_thread(&entry, S_ISDIR(inode->i_mode) ?
+       hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
+       entry_size = hfs_cat_build_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
                        HFS_CDR_THD : HFS_CDR_FTH,
                        dir->i_ino, str);
        err = hfs_brec_find(&fd);
@@ -107,7 +108,7 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
        if (err)
                goto err2;
 
-       hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+       hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
        entry_size = hfs_cat_build_record(&entry, cnid, inode);
        err = hfs_brec_find(&fd);
        if (err != -ENOENT) {
@@ -127,7 +128,7 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
        return 0;
 
 err1:
-       hfs_cat_build_key(fd.search_key, cnid, NULL);
+       hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
        if (!hfs_brec_find(&fd))
                hfs_brec_remove(&fd);
 err2:
@@ -176,7 +177,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
        hfs_cat_rec rec;
        int res, len, type;
 
-       hfs_cat_build_key(fd->search_key, cnid, NULL);
+       hfs_cat_build_key(sb, fd->search_key, cnid, NULL);
        res = hfs_brec_read(fd, &rec, sizeof(rec));
        if (res)
                return res;
@@ -211,7 +212,7 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
        sb = dir->i_sb;
        hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
 
-       hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+       hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
        res = hfs_brec_find(&fd);
        if (res)
                goto out;
@@ -239,7 +240,7 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
        if (res)
                goto out;
 
-       hfs_cat_build_key(fd.search_key, cnid, NULL);
+       hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
        res = hfs_brec_find(&fd);
        if (!res) {
                res = hfs_brec_remove(&fd);
@@ -280,7 +281,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
        dst_fd = src_fd;
 
        /* find the old dir entry and read the data */
-       hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+       hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
        err = hfs_brec_find(&src_fd);
        if (err)
                goto out;
@@ -289,7 +290,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
                            src_fd.entrylength);
 
        /* create new dir entry with the data from the old entry */
-       hfs_cat_build_key(dst_fd.search_key, dst_dir->i_ino, dst_name);
+       hfs_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
        err = hfs_brec_find(&dst_fd);
        if (err != -ENOENT) {
                if (!err)
@@ -305,7 +306,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
        mark_inode_dirty(dst_dir);
 
        /* finally remove the old entry */
-       hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+       hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
        err = hfs_brec_find(&src_fd);
        if (err)
                goto out;
@@ -321,7 +322,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
                goto out;
 
        /* remove old thread entry */
-       hfs_cat_build_key(src_fd.search_key, cnid, NULL);
+       hfs_cat_build_key(sb, src_fd.search_key, cnid, NULL);
        err = hfs_brec_find(&src_fd);
        if (err)
                goto out;
@@ -330,8 +331,8 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
                goto out;
 
        /* create new thread entry */
-       hfs_cat_build_key(dst_fd.search_key, cnid, NULL);
-       entry_size = hfs_cat_build_thread(&entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
+       hfs_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
+       entry_size = hfs_cat_build_thread(sb, &entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
                                        dst_dir->i_ino, dst_name);
        err = hfs_brec_find(&dst_fd);
        if (err != -ENOENT) {
index c55998262aed51632eefa6b6a347a5bd511fdd70..e1f24befba58b282b9f2aa7af6a5b4628cf6533d 100644 (file)
@@ -28,7 +28,7 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
        dentry->d_op = &hfs_dentry_operations;
 
        hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
-       hfs_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+       hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
        res = hfs_brec_read(&fd, &rec, sizeof(rec));
        if (res) {
                hfs_find_exit(&fd);
@@ -56,7 +56,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode *inode = filp->f_dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        int len, err;
-       char strbuf[HFS_NAMELEN + 1];
+       char strbuf[HFS_MAX_NAMELEN];
        union hfs_cat_rec entry;
        struct hfs_find_data fd;
        struct hfs_readdir_data *rd;
@@ -66,7 +66,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                return 0;
 
        hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
-       hfs_cat_build_key(fd.search_key, inode->i_ino, NULL);
+       hfs_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
        err = hfs_brec_find(&fd);
        if (err)
                goto out;
@@ -111,7 +111,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
                type = entry.type;
-               len = hfs_mac2triv(strbuf, &fd.key->cat.CName);
+               len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName);
                if (type == HFS_CDR_DIR) {
                        if (fd.entrylength < sizeof(struct hfs_cat_dir)) {
                                printk("HFS: small dir entry\n");
@@ -307,7 +307,8 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                           old_dir, &old_dentry->d_name,
                           new_dir, &new_dentry->d_name);
        if (!res)
-               hfs_cat_build_key((btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
+               hfs_cat_build_key(old_dir->i_sb,
+                                 (btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
                                  new_dir->i_ino, &new_dentry->d_name);
        return res;
 }
index df6b33adee3bbd143d0a2873d9e378d44a7419d1..88099ab1a180121449cfc04d7ca3a0d26b9366ef 100644 (file)
@@ -25,6 +25,7 @@
 #define HFS_SECTOR_SIZE                512    /* size of an HFS sector */
 #define HFS_SECTOR_SIZE_BITS   9      /* log_2(HFS_SECTOR_SIZE) */
 #define HFS_NAMELEN            31     /* maximum length of an HFS filename */
+#define HFS_MAX_NAMELEN                128
 #define HFS_MAX_VALENCE                32767U
 
 /* Meanings of the drAtrb field of the MDB,
index 0dc8ef8e14de67e0fc2cd4dd9bf379ceaf26f8ea..aae019aadf8865728c2039deb5b2aba09b4a3517 100644 (file)
@@ -141,6 +141,8 @@ struct hfs_sb_info {
 
        int session, part;
 
+       struct nls_table *nls_io, *nls_disk;
+
        struct semaphore bitmap_lock;
 
        unsigned long flags;
@@ -168,7 +170,7 @@ extern int hfs_cat_create(u32, struct inode *, struct qstr *, struct inode *);
 extern int hfs_cat_delete(u32, struct inode *, struct qstr *);
 extern int hfs_cat_move(u32, struct inode *, struct qstr *,
                        struct inode *, struct qstr *);
-extern void hfs_cat_build_key(btree_key *, u32, struct qstr *);
+extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *);
 
 /* dir.c */
 extern struct file_operations hfs_dir_operations;
@@ -222,8 +224,8 @@ extern int hfs_strcmp(const unsigned char *, unsigned int,
 extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 
 /* trans.c */
-extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
-extern int hfs_mac2triv(char *, const struct hfs_name *);
+extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
+extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
 
 extern struct timezone sys_tz;
 
index 75191232609454d67e0e126314c15ef782bdd398..f1570b9f9de30427f133670f02893a67726ed6ed 100644 (file)
@@ -160,7 +160,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 
        init_MUTEX(&HFS_I(inode)->extents_lock);
        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
-       hfs_cat_build_key((btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
+       hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
        inode->i_ino = HFS_SB(sb)->next_id++;
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
index 217e32f37e0be7bce323a9962c0cf95adb394b9e..0a473f79c89feb192b71dba3f66a7951536c86f8 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/cdrom.h>
 #include <linux/genhd.h>
+#include <linux/nls.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
@@ -343,6 +344,11 @@ void hfs_mdb_put(struct super_block *sb)
        brelse(HFS_SB(sb)->mdb_bh);
        brelse(HFS_SB(sb)->alt_mdb_bh);
 
+       if (HFS_SB(sb)->nls_io)
+               unload_nls(HFS_SB(sb)->nls_io);
+       if (HFS_SB(sb)->nls_disk)
+               unload_nls(HFS_SB(sb)->nls_disk);
+
        kfree(HFS_SB(sb));
        sb->s_fs_info = NULL;
 }
index ab783f6afa3b08d00c18c564b598f353af07084f..c5074aeafcae7e8bebaf55780e1548692cdad78b 100644 (file)
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/mount.h>
 #include <linux/init.h>
+#include <linux/nls.h>
 #include <linux/parser.h>
+#include <linux/seq_file.h>
 #include <linux/vfs.h>
 
 #include "hfs_fs.h"
@@ -111,6 +114,32 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data)
        return 0;
 }
 
+static int hfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+       struct hfs_sb_info *sbi = HFS_SB(mnt->mnt_sb);
+
+       if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f))
+               seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator);
+       if (sbi->s_type != cpu_to_be32(0x3f3f3f3f))
+               seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type);
+       seq_printf(seq, ",uid=%u,gid=%u", sbi->s_uid, sbi->s_gid);
+       if (sbi->s_file_umask != 0133)
+               seq_printf(seq, ",file_umask=%o", sbi->s_file_umask);
+       if (sbi->s_dir_umask != 0022)
+               seq_printf(seq, ",dir_umask=%o", sbi->s_dir_umask);
+       if (sbi->part >= 0)
+               seq_printf(seq, ",part=%u", sbi->part);
+       if (sbi->session >= 0)
+               seq_printf(seq, ",session=%u", sbi->session);
+       if (sbi->nls_disk)
+               seq_printf(seq, ",codepage=%s", sbi->nls_disk->charset);
+       if (sbi->nls_io)
+               seq_printf(seq, ",iocharset=%s", sbi->nls_io->charset);
+       if (sbi->s_quiet)
+               seq_printf(seq, ",quiet");
+       return 0;
+}
+
 static struct inode *hfs_alloc_inode(struct super_block *sb)
 {
        struct hfs_inode_info *i;
@@ -133,11 +162,13 @@ static struct super_operations hfs_super_operations = {
        .write_super    = hfs_write_super,
        .statfs         = hfs_statfs,
        .remount_fs     = hfs_remount,
+       .show_options   = hfs_show_options,
 };
 
 enum {
        opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask,
        opt_part, opt_session, opt_type, opt_creator, opt_quiet,
+       opt_codepage, opt_iocharset,
        opt_err
 };
 
@@ -152,6 +183,8 @@ static match_table_t tokens = {
        { opt_type, "type=%s" },
        { opt_creator, "creator=%s" },
        { opt_quiet, "quiet" },
+       { opt_codepage, "codepage=%s" },
+       { opt_iocharset, "iocharset=%s" },
        { opt_err, NULL }
 };
 
@@ -257,11 +290,46 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
                case opt_quiet:
                        hsb->s_quiet = 1;
                        break;
+               case opt_codepage:
+                       if (hsb->nls_disk) {
+                               printk("HFS+-fs: unable to change codepage\n");
+                               return 0;
+                       }
+                       p = match_strdup(&args[0]);
+                       hsb->nls_disk = load_nls(p);
+                       if (!hsb->nls_disk) {
+                               printk("HFS+-fs: unable to load codepage \"%s\"\n", p);
+                               kfree(p);
+                               return 0;
+                       }
+                       kfree(p);
+                       break;
+               case opt_iocharset:
+                       if (hsb->nls_io) {
+                               printk("HFS: unable to change iocharset\n");
+                               return 0;
+                       }
+                       p = match_strdup(&args[0]);
+                       hsb->nls_io = load_nls(p);
+                       if (!hsb->nls_io) {
+                               printk("HFS: unable to load iocharset \"%s\"\n", p);
+                               kfree(p);
+                               return 0;
+                       }
+                       kfree(p);
+                       break;
                default:
                        return 0;
                }
        }
 
+       if (hsb->nls_disk && !hsb->nls_io) {
+               hsb->nls_io = load_nls_default();
+               if (!hsb->nls_io) {
+                       printk("HFS: unable to load default iocharset\n");
+                       return 0;
+               }
+       }
        hsb->s_dir_umask &= 0777;
        hsb->s_file_umask &= 0577;
 
index fb9720abbadd64ff572f58b4533302247347e50c..e673a88b8ae7560b14796b611aa57b267193411f 100644 (file)
@@ -9,12 +9,15 @@
  * with ':' vs. '/' as the path-element separator.
  */
 
+#include <linux/types.h>
+#include <linux/nls.h>
+
 #include "hfs_fs.h"
 
 /*================ Global functions ================*/
 
 /*
- * hfs_mac2triv()
+ * hfs_mac2asc()
  *
  * Given a 'Pascal String' (a string preceded by a length byte) in
  * the Macintosh character set produce the corresponding filename using
  * by ':' which never appears in HFS filenames.         All other characters
  * are passed unchanged from input to output.
  */
-int hfs_mac2triv(char *out, const struct hfs_name *in)
+int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
 {
-       const char *p;
-       char c;
-       int i, len;
+       struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
+       struct nls_table *nls_io = HFS_SB(sb)->nls_io;
+       const char *src;
+       char *dst;
+       int srclen, dstlen, size;
+
+       src = in->name;
+       srclen = in->len;
+       dst = out;
+       dstlen = HFS_MAX_NAMELEN;
+       if (nls_io) {
+               wchar_t ch;
 
-       len = in->len;
-       p = in->name;
-       for (i = 0; i < len; i++) {
-               c = *p++;
-               *out++ = c == '/' ? ':' : c;
+               while (srclen > 0) {
+                       if (nls_disk) {
+                               size = nls_disk->char2uni(src, srclen, &ch);
+                               if (size <= 0) {
+                                       ch = '?';
+                                       size = 1;
+                               }
+                               src += size;
+                               srclen -= size;
+                       } else {
+                               ch = *src++;
+                               srclen--;
+                       }
+                       if (ch == '/')
+                               ch = ':';
+                       size = nls_io->uni2char(ch, dst, dstlen);
+                       if (size < 0) {
+                               if (size == -ENAMETOOLONG)
+                                       goto out;
+                               *dst = '?';
+                               size = 1;
+                       }
+                       dst += size;
+                       dstlen -= size;
+               }
+       } else {
+               char ch;
+
+               while (--srclen >= 0)
+                       *dst++ = (ch = *src++) == '/' ? ':' : ch;
        }
-       return i;
+out:
+       return dst - out;
 }
 
 /*
- * hfs_triv2mac()
+ * hfs_asc2mac()
  *
  * Given an ASCII string (not null-terminated) and its length,
  * generate the corresponding filename in the Macintosh character set
@@ -54,19 +92,57 @@ int hfs_mac2triv(char *out, const struct hfs_name *in)
  * This routine is a inverse to hfs_mac2triv().
  * A ':' is replaced by a '/'.
  */
-void hfs_triv2mac(struct hfs_name *out, struct qstr *in)
+void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, struct qstr *in)
 {
+       struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
+       struct nls_table *nls_io = HFS_SB(sb)->nls_io;
        const char *src;
-       char *dst, c;
-       int i, len;
+       char *dst;
+       int srclen, dstlen, size;
 
-       out->len = len = min((unsigned int)HFS_NAMELEN, in->len);
        src = in->name;
+       srclen = in->len;
        dst = out->name;
-       for (i = 0; i < len; i++) {
-               c = *src++;
-               *dst++ = c == ':' ? '/' : c;
+       dstlen = HFS_NAMELEN;
+       if (nls_io) {
+               wchar_t ch;
+
+               while (srclen > 0) {
+                       size = nls_io->char2uni(src, srclen, &ch);
+                       if (size < 0) {
+                               ch = '?';
+                               size = 1;
+                       }
+                       src += size;
+                       srclen -= size;
+                       if (ch == ':')
+                               ch = '/';
+                       if (nls_disk) {
+                               size = nls_disk->uni2char(ch, dst, dstlen);
+                               if (size < 0) {
+                                       if (size == -ENAMETOOLONG)
+                                               goto out;
+                                       *dst = '?';
+                                       size = 1;
+                               }
+                               dst += size;
+                               dstlen -= size;
+                       } else {
+                               *dst++ = ch > 0xff ? '?' : ch;
+                               dstlen--;
+                       }
+               }
+       } else {
+               char ch;
+
+               if (dstlen > srclen)
+                       dstlen = srclen;
+               while (--dstlen >= 0)
+                       *dst++ = (ch = *src++) == ':' ? '/' : ch;
        }
-       for (; i < HFS_NAMELEN; i++)
+out:
+       out->len = dst - (char *)out->name;
+       dstlen = HFS_NAMELEN - out->len;
+       while (--dstlen >= 0)
                *dst++ = 0;
 }
index 8868d3b766fd46e1c263dfdde6d1688cc1f5cd09..b85abc6e6f83b3c3344ac102521521f7655d5134 100644 (file)
@@ -18,8 +18,6 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 
-#define REF_PAGES      0
-
 /* Copy a specified range of bytes from the raw data of a node */
 void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
 {
@@ -450,9 +448,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
                        page_cache_release(page);
                        goto fail;
                }
-#if !REF_PAGES
                page_cache_release(page);
-#endif
                node->page[i] = page;
        }
 
@@ -612,13 +608,6 @@ void hfs_bnode_get(struct hfs_bnode *node)
 {
        if (node) {
                atomic_inc(&node->refcnt);
-#if REF_PAGES
-               {
-               int i;
-               for (i = 0; i < node->tree->pages_per_bnode; i++)
-                       get_page(node->page[i]);
-               }
-#endif
                dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
                       node->tree->cnid, node->this, atomic_read(&node->refcnt));
        }
@@ -635,20 +624,12 @@ void hfs_bnode_put(struct hfs_bnode *node)
                       node->tree->cnid, node->this, atomic_read(&node->refcnt));
                if (!atomic_read(&node->refcnt))
                        BUG();
-               if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
-#if REF_PAGES
-                       for (i = 0; i < tree->pages_per_bnode; i++)
-                               put_page(node->page[i]);
-#endif
+               if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
                        return;
-               }
                for (i = 0; i < tree->pages_per_bnode; i++) {
                        if (!node->page[i])
                                continue;
                        mark_page_accessed(node->page[i]);
-#if REF_PAGES
-                       put_page(node->page[i]);
-#endif
                }
 
                if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
index 533094a570df3011f032822974669195fd19cd16..2bc0cdd30e5656f3325be27d84b6369f345e6a40 100644 (file)
@@ -343,8 +343,9 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
 ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 /* options.c */
-int parse_options(char *, struct hfsplus_sb_info *);
-void fill_defaults(struct hfsplus_sb_info *);
+int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
+void hfsplus_fill_defaults(struct hfsplus_sb_info *);
+int hfsplus_show_options(struct seq_file *, struct vfsmount *);
 
 /* tables.c */
 extern u16 hfsplus_case_fold_table[];
index 1cca0102c98d30e4c57a3f8097669959e64c9d45..cca0818aa4ca3dbd18fe842e802e38b558fa4d90 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/sched.h>
 #include <linux/parser.h>
 #include <linux/nls.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
 #include "hfsplus_fs.h"
 
 enum {
@@ -38,7 +40,7 @@ static match_table_t tokens = {
 };
 
 /* Initialize an options object to reasonable defaults */
-void fill_defaults(struct hfsplus_sb_info *opts)
+void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
 {
        if (!opts)
                return;
@@ -63,7 +65,7 @@ static inline int match_fourchar(substring_t *arg, u32 *result)
 
 /* Parse options from mount. Returns 0 on failure */
 /* input is the options passed to mount() as a string */
-int parse_options(char *input, struct hfsplus_sb_info *sbi)
+int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
 {
        char *p;
        substring_t args[MAX_OPT_ARGS];
@@ -160,3 +162,23 @@ done:
 
        return 1;
 }
+
+int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+       struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb);
+
+       if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
+               seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
+       if (sbi->type != HFSPLUS_DEF_CR_TYPE)
+               seq_printf(seq, ",type=%.4s", (char *)&sbi->type);
+       seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask, sbi->uid, sbi->gid);
+       if (sbi->part >= 0)
+               seq_printf(seq, ",part=%u", sbi->part);
+       if (sbi->session >= 0)
+               seq_printf(seq, ",session=%u", sbi->session);
+       if (sbi->nls)
+               seq_printf(seq, ",nls=%s", sbi->nls->charset);
+       if (sbi->flags & HFSPLUS_SB_NODECOMPOSE)
+               seq_printf(seq, ",nodecompose");
+       return 0;
+}
index d55ad67b8e4238e3625f2139b78b353858337657..fd0f0f050e1d5f3643f7b6e7273af4d7ade0448e 100644 (file)
@@ -217,8 +217,7 @@ static void hfsplus_put_super(struct super_block *sb)
                vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
                vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
                mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-               ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
-               wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+               sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
        }
 
        hfs_btree_close(HFSPLUS_SB(sb).cat_tree);
@@ -277,6 +276,7 @@ static struct super_operations hfsplus_sops = {
        .write_super    = hfsplus_write_super,
        .statfs         = hfsplus_statfs,
        .remount_fs     = hfsplus_remount,
+       .show_options   = hfsplus_show_options,
 };
 
 static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
@@ -297,8 +297,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
        sb->s_fs_info = sbi;
        INIT_HLIST_HEAD(&sbi->rsrc_inodes);
-       fill_defaults(sbi);
-       if (!parse_options(data, sbi)) {
+       hfsplus_fill_defaults(sbi);
+       if (!hfsplus_parse_options(data, sbi)) {
                if (!silent)
                        printk("HFS+-fs: unable to parse mount options\n");
                err = -EINVAL;
@@ -415,8 +415,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
        vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
        mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-       ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
-       wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+       sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
 
        if (!HFSPLUS_SB(sb).hidden_dir) {
                printk("HFS+: create hidden dir...\n");
index 67bca0d4a33ba5977a94c6a3d71b636010ac67a7..cca3fb693f9905e52ab1e6f486091d89ee2650e5 100644 (file)
@@ -49,7 +49,6 @@ struct hostfs_iattr {
        struct timespec ia_atime;
        struct timespec ia_mtime;
        struct timespec ia_ctime;
-       unsigned int    ia_attr_flags;
 };
 
 extern int stat_file(const char *path, unsigned long long *inode_out,
index e57f1724db3e89242afb362dfcda99178a2c4015..71df1b1e8f75a87910357025048b38ba7d382df6 100644 (file)
@@ -1195,9 +1195,6 @@ void update_atime(struct inode *inode)
        if (!timespec_equal(&inode->i_atime, &now)) {
                inode->i_atime = now;
                mark_inode_dirty_sync(inode);
-       } else {
-               if (!timespec_equal(&inode->i_atime, &now))
-                       inode->i_atime = now;
        }
 }
 
index 2e4e2a57708cf95dcdf348235376ef901f4dc295..a37e9fb1da589fa1457929e2079e176220ad34c0 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/ioctls.h>
 
 static atomic_t inotify_cookie;
+static atomic_t inotify_watches;
 
 static kmem_cache_t *watch_cachep;
 static kmem_cache_t *event_cachep;
@@ -422,6 +423,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev,
        get_inotify_watch(watch);
 
        atomic_inc(&dev->user->inotify_watches);
+       atomic_inc(&inotify_watches);
 
        return watch;
 }
@@ -454,6 +456,7 @@ static void remove_watch_no_event(struct inotify_watch *watch,
        list_del(&watch->d_list);
 
        atomic_dec(&dev->user->inotify_watches);
+       atomic_dec(&inotify_watches);
        idr_remove(&dev->idr, watch->wd);
        put_inotify_watch(watch);
 }
@@ -532,6 +535,9 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
        struct dentry *parent;
        struct inode *inode;
 
+       if (!atomic_read (&inotify_watches))
+               return;
+
        spin_lock(&dentry->d_lock);
        parent = dentry->d_parent;
        inode = parent->d_inode;
@@ -925,6 +931,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
        struct nameidata nd;
        struct file *filp;
        int ret, fput_needed;
+       int mask_add = 0;
 
        filp = fget_light(fd, &fput_needed);
        if (unlikely(!filp))
@@ -947,6 +954,9 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
        down(&inode->inotify_sem);
        down(&dev->sem);
 
+       if (mask & IN_MASK_ADD)
+               mask_add = 1;
+
        /* don't let user-space set invalid bits: we don't want flags set */
        mask &= IN_ALL_EVENTS;
        if (unlikely(!mask)) {
@@ -960,7 +970,10 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
         */
        old = inode_find_dev(inode, dev);
        if (unlikely(old)) {
-               old->mask = mask;
+               if (mask_add)
+                       old->mask |= mask;
+               else
+                       old->mask = mask;
                ret = old->wd;
                goto out;
        }
@@ -1043,6 +1056,7 @@ static int __init inotify_setup(void)
        inotify_max_user_watches = 8192;
 
        atomic_set(&inotify_cookie, 0);
+       atomic_set(&inotify_watches, 0);
 
        watch_cachep = kmem_cache_create("inotify_watch_cache",
                                         sizeof(struct inotify_watch),
index 5a97e346bd95a247c12f0edcc5b33d1b065d6419..014a51fd00d776d0ded21d1e3eaf6b7cf22ca1ec 100644 (file)
@@ -204,7 +204,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
        int i;
 
        spin_unlock(&journal->j_list_lock);
-       ll_rw_block(WRITE, *batch_count, bhs);
+       ll_rw_block(SWRITE, *batch_count, bhs);
        spin_lock(&journal->j_list_lock);
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = bhs[i];
index dac720c837abf0475ee41fa56708c5748daf480d..2a3e310f79efa7c3665dd037dd572ca35780677f 100644 (file)
@@ -358,7 +358,7 @@ write_out_data:
                                        jbd_debug(2, "submit %d writes\n",
                                                        bufs);
                                        spin_unlock(&journal->j_list_lock);
-                                       ll_rw_block(WRITE, bufs, wbuf);
+                                       ll_rw_block(SWRITE, bufs, wbuf);
                                        journal_brelse_array(wbuf, bufs);
                                        bufs = 0;
                                        goto write_out_data;
@@ -381,7 +381,7 @@ write_out_data:
 
        if (bufs) {
                spin_unlock(&journal->j_list_lock);
-               ll_rw_block(WRITE, bufs, wbuf);
+               ll_rw_block(SWRITE, bufs, wbuf);
                journal_brelse_array(wbuf, bufs);
                spin_lock(&journal->j_list_lock);
        }
@@ -720,11 +720,17 @@ wait_for_iobuf:
        J_ASSERT(commit_transaction->t_log_list == NULL);
 
 restart_loop:
+       /*
+        * As there are other places (journal_unmap_buffer()) adding buffers
+        * to this list we have to be careful and hold the j_list_lock.
+        */
+       spin_lock(&journal->j_list_lock);
        while (commit_transaction->t_forget) {
                transaction_t *cp_transaction;
                struct buffer_head *bh;
 
                jh = commit_transaction->t_forget;
+               spin_unlock(&journal->j_list_lock);
                bh = jh2bh(jh);
                jbd_lock_bh_state(bh);
                J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
@@ -792,9 +798,25 @@ restart_loop:
                        journal_remove_journal_head(bh);  /* needs a brelse */
                        release_buffer_page(bh);
                }
+               cond_resched_lock(&journal->j_list_lock);
+       }
+       spin_unlock(&journal->j_list_lock);
+       /*
+        * This is a bit sleazy.  We borrow j_list_lock to protect
+        * journal->j_committing_transaction in __journal_remove_checkpoint.
+        * Really, __journal_remove_checkpoint should be using j_state_lock but
+        * it's a bit hassle to hold that across __journal_remove_checkpoint
+        */
+       spin_lock(&journal->j_state_lock);
+       spin_lock(&journal->j_list_lock);
+       /*
+        * Now recheck if some buffers did not get attached to the transaction
+        * while the lock was dropped...
+        */
+       if (commit_transaction->t_forget) {
                spin_unlock(&journal->j_list_lock);
-               if (cond_resched())
-                       goto restart_loop;
+               spin_unlock(&journal->j_state_lock);
+               goto restart_loop;
        }
 
        /* Done with this transaction! */
@@ -803,14 +825,6 @@ restart_loop:
 
        J_ASSERT(commit_transaction->t_state == T_COMMIT);
 
-       /*
-        * This is a bit sleazy.  We borrow j_list_lock to protect
-        * journal->j_committing_transaction in __journal_remove_checkpoint.
-        * Really, __jornal_remove_checkpoint should be using j_state_lock but
-        * it's a bit hassle to hold that across __journal_remove_checkpoint
-        */
-       spin_lock(&journal->j_state_lock);
-       spin_lock(&journal->j_list_lock);
        commit_transaction->t_state = T_FINISHED;
        J_ASSERT(commit_transaction == journal->j_committing_transaction);
        journal->j_commit_sequence = commit_transaction->t_tid;
index 5e7b439495171c9d0fcfa7f28b2fa51aab489823..7ae2c4fe506bb5bd7b2ac21c6bbf80795741361d 100644 (file)
@@ -65,7 +65,6 @@ EXPORT_SYMBOL(journal_set_features);
 EXPORT_SYMBOL(journal_create);
 EXPORT_SYMBOL(journal_load);
 EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_recover);
 EXPORT_SYMBOL(journal_update_superblock);
 EXPORT_SYMBOL(journal_abort);
 EXPORT_SYMBOL(journal_errno);
@@ -81,6 +80,7 @@ EXPORT_SYMBOL(journal_try_to_free_buffers);
 EXPORT_SYMBOL(journal_force_commit);
 
 static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+static void __journal_abort_soft (journal_t *journal, int errno);
 
 /*
  * Helper function used to manage commit timeouts
@@ -93,16 +93,6 @@ static void commit_timeout(unsigned long __data)
        wake_up_process(p);
 }
 
-/* Static check for data structure consistency.  There's no code
- * invoked --- we'll just get a linker failure if things aren't right.
- */
-void __journal_internal_check(void)
-{
-       extern void journal_bad_superblock_size(void);
-       if (sizeof(struct journal_superblock_s) != 1024)
-               journal_bad_superblock_size();
-}
-
 /*
  * kjournald: The main thread function used to manage a logging device
  * journal.
@@ -119,16 +109,12 @@ void __journal_internal_check(void)
  *    known as checkpointing, and this thread is responsible for that job.
  */
 
-journal_t *current_journal;            // AKPM: debug
-
-int kjournald(void *arg)
+static int kjournald(void *arg)
 {
        journal_t *journal = (journal_t *) arg;
        transaction_t *transaction;
        struct timer_list timer;
 
-       current_journal = journal;
-
        daemonize("kjournald");
 
        /* Set up an interval timer which can be used to trigger a
@@ -193,6 +179,8 @@ loop:
                if (transaction && time_after_eq(jiffies,
                                                transaction->t_expires))
                        should_sleep = 0;
+               if (journal->j_flags & JFS_UNMOUNT)
+                       should_sleep = 0;
                if (should_sleep) {
                        spin_unlock(&journal->j_state_lock);
                        schedule();
@@ -969,7 +957,7 @@ void journal_update_superblock(journal_t *journal, int wait)
        if (wait)
                sync_dirty_buffer(bh);
        else
-               ll_rw_block(WRITE, 1, &bh);
+               ll_rw_block(SWRITE, 1, &bh);
 
 out:
        /* If we have just flushed the log (by marking s_start==0), then
@@ -1439,7 +1427,7 @@ int journal_wipe(journal_t *journal, int write)
  * device this journal is present.
  */
 
-const char *journal_dev_name(journal_t *journal, char *buffer)
+static const char *journal_dev_name(journal_t *journal, char *buffer)
 {
        struct block_device *bdev;
 
@@ -1485,7 +1473,7 @@ void __journal_abort_hard(journal_t *journal)
 
 /* Soft abort: record the abort error status in the journal superblock,
  * but don't do any other IO. */
-void __journal_abort_soft (journal_t *journal, int errno)
+static void __journal_abort_soft (journal_t *journal, int errno)
 {
        if (journal->j_flags & JFS_ABORT)
                return;
@@ -1880,7 +1868,7 @@ EXPORT_SYMBOL(journal_enable_debug);
 
 static struct proc_dir_entry *proc_jbd_debug;
 
-int read_jbd_debug(char *page, char **start, off_t off,
+static int read_jbd_debug(char *page, char **start, off_t off,
                          int count, int *eof, void *data)
 {
        int ret;
@@ -1890,7 +1878,7 @@ int read_jbd_debug(char *page, char **start, off_t off,
        return ret;
 }
 
-int write_jbd_debug(struct file *file, const char __user *buffer,
+static int write_jbd_debug(struct file *file, const char __user *buffer,
                           unsigned long count, void *data)
 {
        char buf[32];
@@ -1979,6 +1967,14 @@ static int __init journal_init(void)
 {
        int ret;
 
+/* Static check for data structure consistency.  There's no code
+ * invoked --- we'll just get a linker failure if things aren't right.
+ */
+       extern void journal_bad_superblock_size(void);
+       if (sizeof(struct journal_superblock_s) != 1024)
+               journal_bad_superblock_size();
+
+
        ret = journal_init_caches();
        if (ret != 0)
                journal_destroy_caches();
index d327a598f8612843fddcf91be7df805e23acbc70..a56144183462e20d06ad756a5b6d062c44333838 100644 (file)
@@ -116,7 +116,8 @@ static inline int hash(journal_t *journal, unsigned long block)
                (block << (hash_shift - 12))) & (table->hash_size - 1);
 }
 
-int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
+static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
+                             tid_t seq)
 {
        struct list_head *hash_list;
        struct jbd_revoke_record_s *record;
@@ -613,7 +614,7 @@ static void flush_descriptor(journal_t *journal,
        set_buffer_jwrite(bh);
        BUFFER_TRACE(bh, "write");
        set_buffer_dirty(bh);
-       ll_rw_block(WRITE, 1, &bh);
+       ll_rw_block(SWRITE, 1, &bh);
 }
 #endif
 
index 77b7662b840b480f681c8cc889c5689d2b60f253..c6ec66fd876682f4846f0638c2b3682a66b49f94 100644 (file)
@@ -490,23 +490,21 @@ void journal_unlock_updates (journal_t *journal)
  */
 static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
 {
-       struct buffer_head *bh = jh2bh(jh);
        int jlist;
 
-       if (buffer_dirty(bh)) {
-               /* If this buffer is one which might reasonably be dirty
-                * --- ie. data, or not part of this journal --- then
-                * we're OK to leave it alone, but otherwise we need to
-                * move the dirty bit to the journal's own internal
-                * JBDDirty bit. */
-               jlist = jh->b_jlist;
-
-               if (jlist == BJ_Metadata || jlist == BJ_Reserved || 
-                   jlist == BJ_Shadow || jlist == BJ_Forget) {
-                       if (test_clear_buffer_dirty(jh2bh(jh))) {
-                               set_bit(BH_JBDDirty, &jh2bh(jh)->b_state);
-                       }
-               }
+       /* If this buffer is one which might reasonably be dirty
+        * --- ie. data, or not part of this journal --- then
+        * we're OK to leave it alone, but otherwise we need to
+        * move the dirty bit to the journal's own internal
+        * JBDDirty bit. */
+       jlist = jh->b_jlist;
+
+       if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+           jlist == BJ_Shadow || jlist == BJ_Forget) {
+               struct buffer_head *bh = jh2bh(jh);
+
+               if (test_clear_buffer_dirty(bh))
+                       set_buffer_jbddirty(bh);
        }
 }
 
@@ -574,9 +572,14 @@ repeat:
                        if (jh->b_next_transaction)
                                J_ASSERT_JH(jh, jh->b_next_transaction ==
                                                        transaction);
-                       JBUFFER_TRACE(jh, "Unexpected dirty buffer");
-                       jbd_unexpected_dirty_buffer(jh);
-               }
+               }
+               /*
+                * In any case we need to clean the dirty flag and we must
+                * do it under the buffer lock to be sure we don't race
+                * with running write-out.
+                */
+               JBUFFER_TRACE(jh, "Unexpected dirty buffer");
+               jbd_unexpected_dirty_buffer(jh);
        }
 
        unlock_buffer(bh);
index bfbeb4c86e03af70713b00b55e846b7dde0fc8cf..777b90057b893968a2718fb3163407811947c146 100644 (file)
@@ -1629,9 +1629,6 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
 }
 
 
-extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
-extern loff_t generic_file_llseek(struct file *, loff_t, int) __attribute__((weak));
-
 static struct file_operations jffs_file_operations =
 {
        .open           = generic_file_open,
index bd9ed9b0247b1d48de85680c7bed66e04b1787a2..8279bf0133ff573549c0570b707a447042fa4cf9 100644 (file)
@@ -21,9 +21,6 @@
 #include <linux/jffs2.h>
 #include "nodelist.h"
 
-extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
-extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak));
-
 static int jffs2_commit_write (struct file *filp, struct page *pg,
                               unsigned start, unsigned end);
 static int jffs2_prepare_write (struct file *filp, struct page *pg,
index 86ccac80f0abc1cea8a4c42641dac38925f734ad..72a5588faecac5040a241448796d0cfb1e7a5b3f 100644 (file)
@@ -37,6 +37,9 @@
 #define JFS_ERR_CONTINUE   0x00000004   /* continue */
 #define JFS_ERR_PANIC      0x00000008   /* panic */
 
+#define        JFS_USRQUOTA    0x00000010
+#define        JFS_GRPQUOTA    0x00000020
+
 /* platform option (conditional compilation) */
 #define JFS_AIX                0x80000000      /* AIX support */
 /*     POSIX name/directory  support */
index 9ff89720f93bab8bfeaee75ac656e04f6a0de3ee..71bc34b96b2b89d81a0086265aacba9be8b509d6 100644 (file)
 #include <linux/parser.h>
 #include <linux/completion.h>
 #include <linux/vfs.h>
+#include <linux/mount.h>
 #include <linux/moduleparam.h>
 #include <linux/posix_acl.h>
 #include <asm/uaccess.h>
+#include <linux/seq_file.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -192,7 +194,8 @@ static void jfs_put_super(struct super_block *sb)
 
 enum {
        Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
-       Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err,
+       Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
+       Opt_usrquota, Opt_grpquota
 };
 
 static match_table_t tokens = {
@@ -204,8 +207,8 @@ static match_table_t tokens = {
        {Opt_errors, "errors=%s"},
        {Opt_ignore, "noquota"},
        {Opt_ignore, "quota"},
-       {Opt_ignore, "usrquota"},
-       {Opt_ignore, "grpquota"},
+       {Opt_usrquota, "usrquota"},
+       {Opt_grpquota, "grpquota"},
        {Opt_err, NULL}
 };
 
@@ -293,6 +296,24 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
                        }
                        break;
                }
+
+#if defined(CONFIG_QUOTA)
+               case Opt_quota:
+               case Opt_usrquota:
+                       *flag |= JFS_USRQUOTA;
+                       break;
+               case Opt_grpquota:
+                       *flag |= JFS_GRPQUOTA;
+                       break;
+#else
+               case Opt_usrquota:
+               case Opt_grpquota:
+               case Opt_quota:
+                       printk(KERN_ERR
+                              "JFS: quota operations not supported\n");
+                       break;
+#endif
+
                default:
                        printk("jfs: Unrecognized mount option \"%s\" "
                                        " or missing value\n", p);
@@ -539,6 +560,26 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
+static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+       struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
+
+       if (sbi->flag & JFS_NOINTEGRITY)
+               seq_puts(seq, ",nointegrity");
+       else
+               seq_puts(seq, ",integrity");
+
+#if defined(CONFIG_QUOTA)
+       if (sbi->flag & JFS_USRQUOTA)
+               seq_puts(seq, ",usrquota");
+
+       if (sbi->flag & JFS_GRPQUOTA)
+               seq_puts(seq, ",grpquota");
+#endif
+
+       return 0;
+}
+
 static struct super_operations jfs_super_operations = {
        .alloc_inode    = jfs_alloc_inode,
        .destroy_inode  = jfs_destroy_inode,
@@ -552,6 +593,7 @@ static struct super_operations jfs_super_operations = {
        .unlockfs       = jfs_unlockfs,
        .statfs         = jfs_statfs,
        .remount_fs     = jfs_remount,
+       .show_options   = jfs_show_options
 };
 
 static struct export_operations jfs_export_operations = {
index 6ec1f0fefc5b017aa321738f7d3581370a91fad3..145e852c4bd02d717c3dd9e3b63caa6804870f25 100644 (file)
@@ -525,6 +525,22 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd)
        return error;
 }
 
+static inline void dput_path(struct path *path, struct nameidata *nd)
+{
+       dput(path->dentry);
+       if (path->mnt != nd->mnt)
+               mntput(path->mnt);
+}
+
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
+{
+       dput(nd->dentry);
+       if (nd->mnt != path->mnt)
+               mntput(nd->mnt);
+       nd->mnt = path->mnt;
+       nd->dentry = path->dentry;
+}
+
 /*
  * This limits recursive symlink follows to 8, while
  * limiting consecutive symlinks to 40.
@@ -552,9 +568,7 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
        nd->depth--;
        return err;
 loop:
-       dput(path->dentry);
-       if (path->mnt != nd->mnt)
-               mntput(path->mnt);
+       dput_path(path, nd);
        path_release(nd);
        return err;
 }
@@ -813,13 +827,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
                        err = -ENOTDIR; 
                        if (!inode->i_op)
                                break;
-               } else {
-                       dput(nd->dentry);
-                       if (nd->mnt != next.mnt)
-                               mntput(nd->mnt);
-                       nd->mnt = next.mnt;
-                       nd->dentry = next.dentry;
-               }
+               } else
+                       path_to_nameidata(&next, nd);
                err = -ENOTDIR; 
                if (!inode->i_op->lookup)
                        break;
@@ -859,13 +868,8 @@ last_component:
                        if (err)
                                goto return_err;
                        inode = nd->dentry->d_inode;
-               } else {
-                       dput(nd->dentry);
-                       if (nd->mnt != next.mnt)
-                               mntput(nd->mnt);
-                       nd->mnt = next.mnt;
-                       nd->dentry = next.dentry;
-               }
+               } else
+                       path_to_nameidata(&next, nd);
                err = -ENOENT;
                if (!inode)
                        break;
@@ -901,9 +905,7 @@ return_reval:
 return_base:
                return 0;
 out_dput:
-               dput(next.dentry);
-               if (nd->mnt != next.mnt)
-                       mntput(next.mnt);
+               dput_path(&next, nd);
                break;
        }
        path_release(nd);
@@ -1507,11 +1509,7 @@ do_last:
        if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
                goto do_link;
 
-       dput(nd->dentry);
-       nd->dentry = path.dentry;
-       if (nd->mnt != path.mnt)
-               mntput(nd->mnt);
-       nd->mnt = path.mnt;
+       path_to_nameidata(&path, nd);
        error = -EISDIR;
        if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
                goto exit;
@@ -1522,9 +1520,7 @@ ok:
        return 0;
 
 exit_dput:
-       dput(path.dentry);
-       if (nd->mnt != path.mnt)
-               mntput(path.mnt);
+       dput_path(&path, nd);
 exit:
        path_release(nd);
        return error;
index 79bd8a46e1e7298859a85f9ed9efd20e1dfdb19c..34156260c9b6586939e932e3856cc0211e98cd97 100644 (file)
@@ -40,7 +40,7 @@ static inline int sysfs_init(void)
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
 static struct list_head *mount_hashtable;
-static int hash_mask, hash_bits;
+static int hash_mask __read_mostly, hash_bits __read_mostly;
 static kmem_cache_t *mnt_cache; 
 
 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
@@ -1334,8 +1334,12 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p
        error = -EINVAL;
        if (user_nd.mnt->mnt_root != user_nd.dentry)
                goto out2; /* not a mountpoint */
+       if (user_nd.mnt->mnt_parent == user_nd.mnt)
+               goto out2; /* not attached */
        if (new_nd.mnt->mnt_root != new_nd.dentry)
                goto out2; /* not a mountpoint */
+       if (new_nd.mnt->mnt_parent == new_nd.mnt)
+               goto out2; /* not attached */
        tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
        spin_lock(&vfsmount_lock);
        if (tmp != new_nd.mnt) {
index 9a11aa39e2e4e887d549f9e0f942797bc902ada1..057aff745506da64d5ca6b61d00f0eb41c597029 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/hash.h>
+#include <linux/module.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -221,6 +222,7 @@ static int expkey_show(struct seq_file *m,
 }
        
 struct cache_detail svc_expkey_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = EXPKEY_HASHMAX,
        .hash_table     = expkey_table,
        .name           = "nfsd.fh",
@@ -456,6 +458,7 @@ static int svc_export_show(struct seq_file *m,
        return 0;
 }
 struct cache_detail svc_export_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = EXPORT_HASHMAX,
        .hash_table     = export_table,
        .name           = "nfsd.export",
index 5605a26efc57d9db3ca93471f437996dae91056e..13369650cdf9b8db38f2af1a456db8e7cff5a645 100644 (file)
@@ -187,6 +187,7 @@ static int         idtoname_parse(struct cache_detail *, char *, int);
 static struct ent *idtoname_lookup(struct ent *, int);
 
 static struct cache_detail idtoname_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = ENT_HASHMAX,
        .hash_table     = idtoname_table,
        .name           = "nfs4.idtoname",
@@ -320,6 +321,7 @@ static struct ent *nametoid_lookup(struct ent *, int);
 static int         nametoid_parse(struct cache_detail *, char *, int);
 
 static struct cache_detail nametoid_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = ENT_HASHMAX,
        .hash_table     = nametoid_table,
        .name           = "nfs4.nametoid",
@@ -404,8 +406,10 @@ nfsd_idmap_init(void)
 void
 nfsd_idmap_shutdown(void)
 {
-       cache_unregister(&idtoname_cache);
-       cache_unregister(&nametoid_cache);
+       if (cache_unregister(&idtoname_cache))
+               printk(KERN_ERR "nfsd: failed to unregister idtoname cache\n");
+       if (cache_unregister(&nametoid_cache))
+               printk(KERN_ERR "nfsd: failed to unregister nametoid cache\n");
 }
 
 /*
index 32bf05e2996d8054b8ced182c41471d7c3e133e6..4ee2dcc31c285dc57c6922b21e1bad80e740b6c3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -933,16 +933,11 @@ void fastcall fd_install(unsigned int fd, struct file * file)
 
 EXPORT_SYMBOL(fd_install);
 
-asmlinkage long sys_open(const char __user * filename, int flags, int mode)
+long do_sys_open(const char __user *filename, int flags, int mode)
 {
-       char * tmp;
-       int fd;
+       char *tmp = getname(filename);
+       int fd = PTR_ERR(tmp);
 
-       if (force_o_largefile())
-               flags |= O_LARGEFILE;
-
-       tmp = getname(filename);
-       fd = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
                fd = get_unused_fd();
                if (fd >= 0) {
@@ -959,6 +954,14 @@ asmlinkage long sys_open(const char __user * filename, int flags, int mode)
        }
        return fd;
 }
+
+asmlinkage long sys_open(const char __user *filename, int flags, int mode)
+{
+       if (force_o_largefile())
+               flags |= O_LARGEFILE;
+
+       return do_sys_open(filename, flags, mode);
+}
 EXPORT_SYMBOL_GPL(sys_open);
 
 #ifndef __alpha__
index 25aa09f9d09d08ce5c29738406bae6d5e27d8843..2c7a23dde2d83f1ae18190e5723c0eb8d8ae0548 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -415,6 +415,10 @@ pipe_poll(struct file *filp, poll_table *wait)
 
        if (filp->f_mode & FMODE_WRITE) {
                mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0;
+               /*
+                * Most Unices do not set POLLERR for FIFOs but on Linux they
+                * behave exactly like pipes for poll().
+                */
                if (!PIPE_READERS(*inode))
                        mask |= POLLERR;
        }
@@ -422,9 +426,6 @@ pipe_poll(struct file *filp, poll_table *wait)
        return mask;
 }
 
-/* FIXME: most Unices do not set POLLERR for fifos */
-#define fifo_poll pipe_poll
-
 static int
 pipe_release(struct inode *inode, int decr, int decw)
 {
@@ -568,7 +569,7 @@ struct file_operations read_fifo_fops = {
        .read           = pipe_read,
        .readv          = pipe_readv,
        .write          = bad_pipe_w,
-       .poll           = fifo_poll,
+       .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_read_open,
        .release        = pipe_read_release,
@@ -580,7 +581,7 @@ struct file_operations write_fifo_fops = {
        .read           = bad_pipe_r,
        .write          = pipe_write,
        .writev         = pipe_writev,
-       .poll           = fifo_poll,
+       .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_write_open,
        .release        = pipe_write_release,
@@ -593,7 +594,7 @@ struct file_operations rdwr_fifo_fops = {
        .readv          = pipe_readv,
        .write          = pipe_write,
        .writev         = pipe_writev,
-       .poll           = fifo_poll,
+       .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_rdwr_open,
        .release        = pipe_rdwr_release,
index 520978e49e92474f428054785c6c68a1978138a5..84751f3f52d530e86518247e3cace7d20646ed80 100644 (file)
@@ -119,7 +119,6 @@ enum pid_directory_inos {
 #ifdef CONFIG_AUDITSYSCALL
        PROC_TGID_LOGINUID,
 #endif
-       PROC_TGID_FD_DIR,
        PROC_TGID_OOM_SCORE,
        PROC_TGID_OOM_ADJUST,
        PROC_TID_INO,
@@ -158,9 +157,11 @@ enum pid_directory_inos {
 #ifdef CONFIG_AUDITSYSCALL
        PROC_TID_LOGINUID,
 #endif
-       PROC_TID_FD_DIR = 0x8000,       /* 0x8000-0xffff */
        PROC_TID_OOM_SCORE,
        PROC_TID_OOM_ADJUST,
+
+       /* Add new entries before this */
+       PROC_TID_FD_DIR = 0x8000,       /* 0x8000-0xffff */
 };
 
 struct pid_entry {
@@ -297,15 +298,21 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
        return -ENOENT;
 }
 
-static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+static struct fs_struct *get_fs_struct(struct task_struct *task)
 {
        struct fs_struct *fs;
-       int result = -ENOENT;
-       task_lock(proc_task(inode));
-       fs = proc_task(inode)->fs;
+       task_lock(task);
+       fs = task->fs;
        if(fs)
                atomic_inc(&fs->count);
-       task_unlock(proc_task(inode));
+       task_unlock(task);
+       return fs;
+}
+
+static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+{
+       struct fs_struct *fs = get_fs_struct(proc_task(inode));
+       int result = -ENOENT;
        if (fs) {
                read_lock(&fs->lock);
                *mnt = mntget(fs->pwdmnt);
@@ -319,13 +326,8 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs
 
 static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-       struct fs_struct *fs;
+       struct fs_struct *fs = get_fs_struct(proc_task(inode));
        int result = -ENOENT;
-       task_lock(proc_task(inode));
-       fs = proc_task(inode)->fs;
-       if(fs)
-               atomic_inc(&fs->count);
-       task_unlock(proc_task(inode));
        if (fs) {
                read_lock(&fs->lock);
                *mnt = mntget(fs->rootmnt);
@@ -344,33 +346,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
         (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
         security_ptrace(current,task) == 0))
 
-static int may_ptrace_attach(struct task_struct *task)
-{
-       int retval = 0;
-
-       task_lock(task);
-
-       if (!task->mm)
-               goto out;
-       if (((current->uid != task->euid) ||
-            (current->uid != task->suid) ||
-            (current->uid != task->uid) ||
-            (current->gid != task->egid) ||
-            (current->gid != task->sgid) ||
-            (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-               goto out;
-       rmb();
-       if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
-               goto out;
-       if (security_ptrace(current, task))
-               goto out;
-
-       retval = 1;
-out:
-       task_unlock(task);
-       return retval;
-}
-
 static int proc_pid_environ(struct task_struct *task, char * buffer)
 {
        int res = 0;
@@ -380,7 +355,7 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
                if (len > PAGE_SIZE)
                        len = PAGE_SIZE;
                res = access_process_vm(task, mm->env_start, buffer, len, 0);
-               if (!may_ptrace_attach(task))
+               if (!ptrace_may_attach(task))
                        res = -ESRCH;
                mmput(mm);
        }
@@ -683,7 +658,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
        int ret = -ESRCH;
        struct mm_struct *mm;
 
-       if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
+       if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
                goto out;
 
        ret = -ENOMEM;
@@ -709,7 +684,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
 
                this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
                retval = access_process_vm(task, src, page, this_len, 0);
-               if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) {
+               if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {
                        if (!ret)
                                ret = -EIO;
                        break;
@@ -747,7 +722,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
        struct task_struct *task = proc_task(file->f_dentry->d_inode);
        unsigned long dst = *ppos;
 
-       if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
+       if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
                return -ESRCH;
 
        page = (char *)__get_free_page(GFP_USER);
index abe8920313fb32b84ad65b78861325727ae5ce45..8a8c34461d481c115a31d628d8e598bb68c20b26 100644 (file)
@@ -249,6 +249,18 @@ out:
        return error;
 }
 
+static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                       struct kstat *stat)
+{
+       struct inode *inode = dentry->d_inode;
+       struct proc_dir_entry *de = PROC_I(inode)->pde;
+       if (de && de->nlink)
+               inode->i_nlink = de->nlink;
+
+       generic_fillattr(inode, stat);
+       return 0;
+}
+
 static struct inode_operations proc_file_inode_operations = {
        .setattr        = proc_notify_change,
 };
@@ -475,6 +487,7 @@ static struct file_operations proc_dir_operations = {
  */
 static struct inode_operations proc_dir_inode_operations = {
        .lookup         = proc_lookup,
+       .getattr        = proc_getattr,
        .setattr        = proc_notify_change,
 };
 
index 563abd09b5c84b882cbe6f47e56d05e80e5db4b6..b60324aaa2b6731d9ddedd67badaa7b5c9790a60 100644 (file)
@@ -188,7 +188,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
        struct inode *inode;
        loff_t pos;
 
-       if (unlikely(count > file->f_maxcount))
+       if (unlikely(count > INT_MAX))
                goto Einval;
        pos = *ppos;
        if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
index ca7989b04be3490f1e430cae7af2c1b242e521c8..a8e29e9bbbd08e336fc13a3fd9b1e81d7ec4eda0 100644 (file)
@@ -1034,7 +1034,7 @@ static int flush_commit_list(struct super_block *s,
                    SB_ONDISK_JOURNAL_SIZE(s);
                tbh = journal_find_get_block(s, bn);
                if (buffer_dirty(tbh))  /* redundant, ll_rw_block() checks */
-                       ll_rw_block(WRITE, 1, &tbh);
+                       ll_rw_block(SWRITE, 1, &tbh);
                put_bh(tbh);
        }
        atomic_dec(&journal->j_async_throttle);
@@ -2172,7 +2172,7 @@ static int journal_read_transaction(struct super_block *p_s_sb,
        /* flush out the real blocks */
        for (i = 0; i < get_desc_trans_len(desc); i++) {
                set_buffer_dirty(real_blocks[i]);
-               ll_rw_block(WRITE, 1, real_blocks + i);
+               ll_rw_block(SWRITE, 1, real_blocks + i);
        }
        for (i = 0; i < get_desc_trans_len(desc); i++) {
                wait_on_buffer(real_blocks[i]);
diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile
new file mode 100644 (file)
index 0000000..e76e182
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RELAYFS_FS) += relayfs.o
+
+relayfs-y := relay.o inode.o buffers.o
+
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
new file mode 100644 (file)
index 0000000..2aa8e27
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * RelayFS buffer management code.
+ *
+ * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
+ * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+/*
+ * close() vm_op implementation for relayfs file mapping.
+ */
+static void relay_file_mmap_close(struct vm_area_struct *vma)
+{
+       struct rchan_buf *buf = vma->vm_private_data;
+       buf->chan->cb->buf_unmapped(buf, vma->vm_file);
+}
+
+/*
+ * nopage() vm_op implementation for relayfs file mapping.
+ */
+static struct page *relay_buf_nopage(struct vm_area_struct *vma,
+                                    unsigned long address,
+                                    int *type)
+{
+       struct page *page;
+       struct rchan_buf *buf = vma->vm_private_data;
+       unsigned long offset = address - vma->vm_start;
+
+       if (address > vma->vm_end)
+               return NOPAGE_SIGBUS; /* Disallow mremap */
+       if (!buf)
+               return NOPAGE_OOM;
+
+       page = vmalloc_to_page(buf->start + offset);
+       if (!page)
+               return NOPAGE_OOM;
+       get_page(page);
+
+       if (type)
+               *type = VM_FAULT_MINOR;
+
+       return page;
+}
+
+/*
+ * vm_ops for relay file mappings.
+ */
+static struct vm_operations_struct relay_file_mmap_ops = {
+       .nopage = relay_buf_nopage,
+       .close = relay_file_mmap_close,
+};
+
+/**
+ *     relay_mmap_buf: - mmap channel buffer to process address space
+ *     @buf: relay channel buffer
+ *     @vma: vm_area_struct describing memory to be mapped
+ *
+ *     Returns 0 if ok, negative on error
+ *
+ *     Caller should already have grabbed mmap_sem.
+ */
+int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
+{
+       unsigned long length = vma->vm_end - vma->vm_start;
+       struct file *filp = vma->vm_file;
+
+       if (!buf)
+               return -EBADF;
+
+       if (length != (unsigned long)buf->chan->alloc_size)
+               return -EINVAL;
+
+       vma->vm_ops = &relay_file_mmap_ops;
+       vma->vm_private_data = buf;
+       buf->chan->cb->buf_mapped(buf, filp);
+
+       return 0;
+}
+
+/**
+ *     relay_alloc_buf - allocate a channel buffer
+ *     @buf: the buffer struct
+ *     @size: total size of the buffer
+ *
+ *     Returns a pointer to the resulting buffer, NULL if unsuccessful
+ */
+static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
+{
+       void *mem;
+       unsigned int i, j, n_pages;
+
+       size = PAGE_ALIGN(size);
+       n_pages = size >> PAGE_SHIFT;
+
+       buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
+       if (!buf->page_array)
+               return NULL;
+
+       for (i = 0; i < n_pages; i++) {
+               buf->page_array[i] = alloc_page(GFP_KERNEL);
+               if (unlikely(!buf->page_array[i]))
+                       goto depopulate;
+       }
+       mem = vmap(buf->page_array, n_pages, GFP_KERNEL, PAGE_KERNEL);
+       if (!mem)
+               goto depopulate;
+
+       memset(mem, 0, size);
+       buf->page_count = n_pages;
+       return mem;
+
+depopulate:
+       for (j = 0; j < i; j++)
+               __free_page(buf->page_array[j]);
+       kfree(buf->page_array);
+       return NULL;
+}
+
+/**
+ *     relay_create_buf - allocate and initialize a channel buffer
+ *     @alloc_size: size of the buffer to allocate
+ *     @n_subbufs: number of sub-buffers in the channel
+ *
+ *     Returns channel buffer if successful, NULL otherwise
+ */
+struct rchan_buf *relay_create_buf(struct rchan *chan)
+{
+       struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
+       if (!buf->padding)
+               goto free_buf;
+
+       buf->start = relay_alloc_buf(buf, chan->alloc_size);
+       if (!buf->start)
+               goto free_buf;
+
+       buf->chan = chan;
+       kref_get(&buf->chan->kref);
+       return buf;
+
+free_buf:
+       kfree(buf->padding);
+       kfree(buf);
+       return NULL;
+}
+
+/**
+ *     relay_destroy_buf - destroy an rchan_buf struct and associated buffer
+ *     @buf: the buffer struct
+ */
+void relay_destroy_buf(struct rchan_buf *buf)
+{
+       struct rchan *chan = buf->chan;
+       unsigned int i;
+
+       if (likely(buf->start)) {
+               vunmap(buf->start);
+               for (i = 0; i < buf->page_count; i++)
+                       __free_page(buf->page_array[i]);
+               kfree(buf->page_array);
+       }
+       kfree(buf->padding);
+       kfree(buf);
+       kref_put(&chan->kref, relay_destroy_channel);
+}
+
+/**
+ *     relay_remove_buf - remove a channel buffer
+ *
+ *     Removes the file from the relayfs fileystem, which also frees the
+ *     rchan_buf_struct and the channel buffer.  Should only be called from
+ *     kref_put().
+ */
+void relay_remove_buf(struct kref *kref)
+{
+       struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
+       relayfs_remove(buf->dentry);
+}
diff --git a/fs/relayfs/buffers.h b/fs/relayfs/buffers.h
new file mode 100644 (file)
index 0000000..37a1249
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _BUFFERS_H
+#define _BUFFERS_H
+
+/* This inspired by rtai/shmem */
+#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE
+
+extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma);
+extern struct rchan_buf *relay_create_buf(struct rchan *chan);
+extern void relay_destroy_buf(struct rchan_buf *buf);
+extern void relay_remove_buf(struct kref *kref);
+
+#endif/* _BUFFERS_H */
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
new file mode 100644 (file)
index 0000000..0f7f88d
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * VFS-related code for RelayFS, a high-speed data relay filesystem.
+ *
+ * Copyright (C) 2003-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
+ * Copyright (C) 2003-2005 - Karim Yaghmour <karim@opersys.com>
+ *
+ * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/backing-dev.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+#define RELAYFS_MAGIC                  0xF0B4A981
+
+static struct vfsmount *               relayfs_mount;
+static int                             relayfs_mount_count;
+static kmem_cache_t *                  relayfs_inode_cachep;
+
+static struct backing_dev_info         relayfs_backing_dev_info = {
+       .ra_pages       = 0,    /* No readahead */
+       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
+                                      struct rchan *chan)
+{
+       struct rchan_buf *buf = NULL;
+       struct inode *inode;
+
+       if (S_ISREG(mode)) {
+               BUG_ON(!chan);
+               buf = relay_create_buf(chan);
+               if (!buf)
+                       return NULL;
+       }
+
+       inode = new_inode(sb);
+       if (!inode) {
+               relay_destroy_buf(buf);
+               return NULL;
+       }
+
+       inode->i_mode = mode;
+       inode->i_uid = 0;
+       inode->i_gid = 0;
+       inode->i_blksize = PAGE_CACHE_SIZE;
+       inode->i_blocks = 0;
+       inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       switch (mode & S_IFMT) {
+       case S_IFREG:
+               inode->i_fop = &relayfs_file_operations;
+               RELAYFS_I(inode)->buf = buf;
+               break;
+       case S_IFDIR:
+               inode->i_op = &simple_dir_inode_operations;
+               inode->i_fop = &simple_dir_operations;
+
+               /* directory inodes start off with i_nlink == 2 (for "." entry) */
+               inode->i_nlink++;
+               break;
+       default:
+               break;
+       }
+
+       return inode;
+}
+
+/**
+ *     relayfs_create_entry - create a relayfs directory or file
+ *     @name: the name of the file to create
+ *     @parent: parent directory
+ *     @mode: mode
+ *     @chan: relay channel associated with the file
+ *
+ *     Returns the new dentry, NULL on failure
+ *
+ *     Creates a file or directory with the specifed permissions.
+ */
+static struct dentry *relayfs_create_entry(const char *name,
+                                          struct dentry *parent,
+                                          int mode,
+                                          struct rchan *chan)
+{
+       struct dentry *d;
+       struct inode *inode;
+       int error = 0;
+
+       BUG_ON(!name || !(S_ISREG(mode) || S_ISDIR(mode)));
+
+       error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count);
+       if (error) {
+               printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error);
+               return NULL;
+       }
+
+       if (!parent && relayfs_mount && relayfs_mount->mnt_sb)
+               parent = relayfs_mount->mnt_sb->s_root;
+
+       if (!parent) {
+               simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+               return NULL;
+       }
+
+       parent = dget(parent);
+       down(&parent->d_inode->i_sem);
+       d = lookup_one_len(name, parent, strlen(name));
+       if (IS_ERR(d)) {
+               d = NULL;
+               goto release_mount;
+       }
+
+       if (d->d_inode) {
+               d = NULL;
+               goto release_mount;
+       }
+
+       inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan);
+       if (!inode) {
+               d = NULL;
+               goto release_mount;
+       }
+
+       d_instantiate(d, inode);
+       dget(d);        /* Extra count - pin the dentry in core */
+
+       if (S_ISDIR(mode))
+               parent->d_inode->i_nlink++;
+
+       goto exit;
+
+release_mount:
+       simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+
+exit:
+       up(&parent->d_inode->i_sem);
+       dput(parent);
+       return d;
+}
+
+/**
+ *     relayfs_create_file - create a file in the relay filesystem
+ *     @name: the name of the file to create
+ *     @parent: parent directory
+ *     @mode: mode, if not specied the default perms are used
+ *     @chan: channel associated with the file
+ *
+ *     Returns file dentry if successful, NULL otherwise.
+ *
+ *     The file will be created user r on behalf of current user.
+ */
+struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
+                                  int mode, struct rchan *chan)
+{
+       if (!mode)
+               mode = S_IRUSR;
+       mode = (mode & S_IALLUGO) | S_IFREG;
+
+       return relayfs_create_entry(name, parent, mode, chan);
+}
+
+/**
+ *     relayfs_create_dir - create a directory in the relay filesystem
+ *     @name: the name of the directory to create
+ *     @parent: parent directory, NULL if parent should be fs root
+ *
+ *     Returns directory dentry if successful, NULL otherwise.
+ *
+ *     The directory will be created world rwx on behalf of current user.
+ */
+struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
+{
+       int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+       return relayfs_create_entry(name, parent, mode, NULL);
+}
+
+/**
+ *     relayfs_remove - remove a file or directory in the relay filesystem
+ *     @dentry: file or directory dentry
+ *
+ *     Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove(struct dentry *dentry)
+{
+       struct dentry *parent;
+       int error = 0;
+
+       if (!dentry)
+               return -EINVAL;
+       parent = dentry->d_parent;
+       if (!parent)
+               return -EINVAL;
+
+       parent = dget(parent);
+       down(&parent->d_inode->i_sem);
+       if (dentry->d_inode) {
+               if (S_ISDIR(dentry->d_inode->i_mode))
+                       error = simple_rmdir(parent->d_inode, dentry);
+               else
+                       error = simple_unlink(parent->d_inode, dentry);
+               if (!error)
+                       d_delete(dentry);
+       }
+       if (!error)
+               dput(dentry);
+       up(&parent->d_inode->i_sem);
+       dput(parent);
+
+       if (!error)
+               simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+
+       return error;
+}
+
+/**
+ *     relayfs_remove_dir - remove a directory in the relay filesystem
+ *     @dentry: directory dentry
+ *
+ *     Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove_dir(struct dentry *dentry)
+{
+       return relayfs_remove(dentry);
+}
+
+/**
+ *     relayfs_open - open file op for relayfs files
+ *     @inode: the inode
+ *     @filp: the file
+ *
+ *     Increments the channel buffer refcount.
+ */
+static int relayfs_open(struct inode *inode, struct file *filp)
+{
+       struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+       kref_get(&buf->kref);
+
+       return 0;
+}
+
+/**
+ *     relayfs_mmap - mmap file op for relayfs files
+ *     @filp: the file
+ *     @vma: the vma describing what to map
+ *
+ *     Calls upon relay_mmap_buf to map the file into user space.
+ */
+static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       return relay_mmap_buf(RELAYFS_I(inode)->buf, vma);
+}
+
+/**
+ *     relayfs_poll - poll file op for relayfs files
+ *     @filp: the file
+ *     @wait: poll table
+ *
+ *     Poll implemention.
+ */
+static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
+{
+       unsigned int mask = 0;
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+
+       if (buf->finalized)
+               return POLLERR;
+
+       if (filp->f_mode & FMODE_READ) {
+               poll_wait(filp, &buf->read_wait, wait);
+               if (!relay_buf_empty(buf))
+                       mask |= POLLIN | POLLRDNORM;
+       }
+
+       return mask;
+}
+
+/**
+ *     relayfs_release - release file op for relayfs files
+ *     @inode: the inode
+ *     @filp: the file
+ *
+ *     Decrements the channel refcount, as the filesystem is
+ *     no longer using it.
+ */
+static int relayfs_release(struct inode *inode, struct file *filp)
+{
+       struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+       kref_put(&buf->kref, relay_remove_buf);
+
+       return 0;
+}
+
+/**
+ *     relayfs_read_consume - update the consumed count for the buffer
+ */
+static void relayfs_read_consume(struct rchan_buf *buf,
+                                size_t read_pos,
+                                size_t bytes_consumed)
+{
+       size_t subbuf_size = buf->chan->subbuf_size;
+       size_t n_subbufs = buf->chan->n_subbufs;
+       size_t read_subbuf;
+
+       if (buf->bytes_consumed + bytes_consumed > subbuf_size) {
+               relay_subbufs_consumed(buf->chan, buf->cpu, 1);
+               buf->bytes_consumed = 0;
+       }
+
+       buf->bytes_consumed += bytes_consumed;
+       read_subbuf = read_pos / buf->chan->subbuf_size;
+       if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
+               if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
+                   (buf->offset == subbuf_size))
+                       return;
+               relay_subbufs_consumed(buf->chan, buf->cpu, 1);
+               buf->bytes_consumed = 0;
+       }
+}
+
+/**
+ *     relayfs_read_avail - boolean, are there unconsumed bytes available?
+ */
+static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
+{
+       size_t bytes_produced, bytes_consumed, write_offset;
+       size_t subbuf_size = buf->chan->subbuf_size;
+       size_t n_subbufs = buf->chan->n_subbufs;
+       size_t produced = buf->subbufs_produced % n_subbufs;
+       size_t consumed = buf->subbufs_consumed % n_subbufs;
+
+       write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
+
+       if (consumed > produced) {
+               if ((produced > n_subbufs) &&
+                   (produced + n_subbufs - consumed <= n_subbufs))
+                       produced += n_subbufs;
+       } else if (consumed == produced) {
+               if (buf->offset > subbuf_size) {
+                       produced += n_subbufs;
+                       if (buf->subbufs_produced == buf->subbufs_consumed)
+                               consumed += n_subbufs;
+               }
+       }
+
+       if (buf->offset > subbuf_size)
+               bytes_produced = (produced - 1) * subbuf_size + write_offset;
+       else
+               bytes_produced = produced * subbuf_size + write_offset;
+       bytes_consumed = consumed * subbuf_size + buf->bytes_consumed;
+
+       if (bytes_produced == bytes_consumed)
+               return 0;
+
+       relayfs_read_consume(buf, read_pos, 0);
+
+       return 1;
+}
+
+/**
+ *     relayfs_read_subbuf_avail - return bytes available in sub-buffer
+ */
+static size_t relayfs_read_subbuf_avail(size_t read_pos,
+                                       struct rchan_buf *buf)
+{
+       size_t padding, avail = 0;
+       size_t read_subbuf, read_offset, write_subbuf, write_offset;
+       size_t subbuf_size = buf->chan->subbuf_size;
+
+       write_subbuf = (buf->data - buf->start) / subbuf_size;
+       write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
+       read_subbuf = read_pos / subbuf_size;
+       read_offset = read_pos % subbuf_size;
+       padding = buf->padding[read_subbuf];
+
+       if (read_subbuf == write_subbuf) {
+               if (read_offset + padding < write_offset)
+                       avail = write_offset - (read_offset + padding);
+       } else
+               avail = (subbuf_size - padding) - read_offset;
+
+       return avail;
+}
+
+/**
+ *     relayfs_read_start_pos - find the first available byte to read
+ *
+ *     If the read_pos is in the middle of padding, return the
+ *     position of the first actually available byte, otherwise
+ *     return the original value.
+ */
+static size_t relayfs_read_start_pos(size_t read_pos,
+                                    struct rchan_buf *buf)
+{
+       size_t read_subbuf, padding, padding_start, padding_end;
+       size_t subbuf_size = buf->chan->subbuf_size;
+       size_t n_subbufs = buf->chan->n_subbufs;
+
+       read_subbuf = read_pos / subbuf_size;
+       padding = buf->padding[read_subbuf];
+       padding_start = (read_subbuf + 1) * subbuf_size - padding;
+       padding_end = (read_subbuf + 1) * subbuf_size;
+       if (read_pos >= padding_start && read_pos < padding_end) {
+               read_subbuf = (read_subbuf + 1) % n_subbufs;
+               read_pos = read_subbuf * subbuf_size;
+       }
+
+       return read_pos;
+}
+
+/**
+ *     relayfs_read_end_pos - return the new read position
+ */
+static size_t relayfs_read_end_pos(struct rchan_buf *buf,
+                                  size_t read_pos,
+                                  size_t count)
+{
+       size_t read_subbuf, padding, end_pos;
+       size_t subbuf_size = buf->chan->subbuf_size;
+       size_t n_subbufs = buf->chan->n_subbufs;
+
+       read_subbuf = read_pos / subbuf_size;
+       padding = buf->padding[read_subbuf];
+       if (read_pos % subbuf_size + count + padding == subbuf_size)
+               end_pos = (read_subbuf + 1) * subbuf_size;
+       else
+               end_pos = read_pos + count;
+       if (end_pos >= subbuf_size * n_subbufs)
+               end_pos = 0;
+
+       return end_pos;
+}
+
+/**
+ *     relayfs_read - read file op for relayfs files
+ *     @filp: the file
+ *     @buffer: the userspace buffer
+ *     @count: number of bytes to read
+ *     @ppos: position to read from
+ *
+ *     Reads count bytes or the number of bytes available in the
+ *     current sub-buffer being read, whichever is smaller.
+ */
+static ssize_t relayfs_read(struct file *filp,
+                           char __user *buffer,
+                           size_t count,
+                           loff_t *ppos)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+       size_t read_start, avail;
+       ssize_t ret = 0;
+       void *from;
+
+       down(&inode->i_sem);
+       if(!relayfs_read_avail(buf, *ppos))
+               goto out;
+
+       read_start = relayfs_read_start_pos(*ppos, buf);
+       avail = relayfs_read_subbuf_avail(read_start, buf);
+       if (!avail)
+               goto out;
+
+       from = buf->start + read_start;
+       ret = count = min(count, avail);
+       if (copy_to_user(buffer, from, count)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       relayfs_read_consume(buf, read_start, count);
+       *ppos = relayfs_read_end_pos(buf, read_start, count);
+out:
+       up(&inode->i_sem);
+       return ret;
+}
+
+/**
+ *     relayfs alloc_inode() implementation
+ */
+static struct inode *relayfs_alloc_inode(struct super_block *sb)
+{
+       struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
+       if (!p)
+               return NULL;
+       p->buf = NULL;
+
+       return &p->vfs_inode;
+}
+
+/**
+ *     relayfs destroy_inode() implementation
+ */
+static void relayfs_destroy_inode(struct inode *inode)
+{
+       if (RELAYFS_I(inode)->buf)
+               relay_destroy_buf(RELAYFS_I(inode)->buf);
+
+       kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
+}
+
+static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+{
+       struct relayfs_inode_info *i = p;
+       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+               inode_init_once(&i->vfs_inode);
+}
+
+struct file_operations relayfs_file_operations = {
+       .open           = relayfs_open,
+       .poll           = relayfs_poll,
+       .mmap           = relayfs_mmap,
+       .read           = relayfs_read,
+       .llseek         = no_llseek,
+       .release        = relayfs_release,
+};
+
+static struct super_operations relayfs_ops = {
+       .statfs         = simple_statfs,
+       .drop_inode     = generic_delete_inode,
+       .alloc_inode    = relayfs_alloc_inode,
+       .destroy_inode  = relayfs_destroy_inode,
+};
+
+static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
+{
+       struct inode *inode;
+       struct dentry *root;
+       int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+
+       sb->s_blocksize = PAGE_CACHE_SIZE;
+       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       sb->s_magic = RELAYFS_MAGIC;
+       sb->s_op = &relayfs_ops;
+       inode = relayfs_get_inode(sb, mode, NULL);
+
+       if (!inode)
+               return -ENOMEM;
+
+       root = d_alloc_root(inode);
+       if (!root) {
+               iput(inode);
+               return -ENOMEM;
+       }
+       sb->s_root = root;
+
+       return 0;
+}
+
+static struct super_block * relayfs_get_sb(struct file_system_type *fs_type,
+                                          int flags, const char *dev_name,
+                                          void *data)
+{
+       return get_sb_single(fs_type, flags, data, relayfs_fill_super);
+}
+
+static struct file_system_type relayfs_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "relayfs",
+       .get_sb         = relayfs_get_sb,
+       .kill_sb        = kill_litter_super,
+};
+
+static int __init init_relayfs_fs(void)
+{
+       int err;
+
+       relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache",
+                               sizeof(struct relayfs_inode_info), 0,
+                               0, init_once, NULL);
+       if (!relayfs_inode_cachep)
+               return -ENOMEM;
+
+       err = register_filesystem(&relayfs_fs_type);
+       if (err)
+               kmem_cache_destroy(relayfs_inode_cachep);
+
+       return err;
+}
+
+static void __exit exit_relayfs_fs(void)
+{
+       unregister_filesystem(&relayfs_fs_type);
+       kmem_cache_destroy(relayfs_inode_cachep);
+}
+
+module_init(init_relayfs_fs)
+module_exit(exit_relayfs_fs)
+
+EXPORT_SYMBOL_GPL(relayfs_file_operations);
+EXPORT_SYMBOL_GPL(relayfs_create_dir);
+EXPORT_SYMBOL_GPL(relayfs_remove_dir);
+
+MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
+MODULE_DESCRIPTION("Relay Filesystem");
+MODULE_LICENSE("GPL");
+
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
new file mode 100644 (file)
index 0000000..16446a1
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Public API and common code for RelayFS.
+ *
+ * See Documentation/filesystems/relayfs.txt for an overview of relayfs.
+ *
+ * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
+ * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/errno.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+/**
+ *     relay_buf_empty - boolean, is the channel buffer empty?
+ *     @buf: channel buffer
+ *
+ *     Returns 1 if the buffer is empty, 0 otherwise.
+ */
+int relay_buf_empty(struct rchan_buf *buf)
+{
+       return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1;
+}
+
+/**
+ *     relay_buf_full - boolean, is the channel buffer full?
+ *     @buf: channel buffer
+ *
+ *     Returns 1 if the buffer is full, 0 otherwise.
+ */
+int relay_buf_full(struct rchan_buf *buf)
+{
+       size_t ready = buf->subbufs_produced - buf->subbufs_consumed;
+       return (ready >= buf->chan->n_subbufs) ? 1 : 0;
+}
+
+/*
+ * High-level relayfs kernel API and associated functions.
+ */
+
+/*
+ * rchan_callback implementations defining default channel behavior.  Used
+ * in place of corresponding NULL values in client callback struct.
+ */
+
+/*
+ * subbuf_start() default callback.  Does nothing.
+ */
+static int subbuf_start_default_callback (struct rchan_buf *buf,
+                                         void *subbuf,
+                                         void *prev_subbuf,
+                                         size_t prev_padding)
+{
+       if (relay_buf_full(buf))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * buf_mapped() default callback.  Does nothing.
+ */
+static void buf_mapped_default_callback(struct rchan_buf *buf,
+                                       struct file *filp)
+{
+}
+
+/*
+ * buf_unmapped() default callback.  Does nothing.
+ */
+static void buf_unmapped_default_callback(struct rchan_buf *buf,
+                                         struct file *filp)
+{
+}
+
+/* relay channel default callbacks */
+static struct rchan_callbacks default_channel_callbacks = {
+       .subbuf_start = subbuf_start_default_callback,
+       .buf_mapped = buf_mapped_default_callback,
+       .buf_unmapped = buf_unmapped_default_callback,
+};
+
+/**
+ *     wakeup_readers - wake up readers waiting on a channel
+ *     @private: the channel buffer
+ *
+ *     This is the work function used to defer reader waking.  The
+ *     reason waking is deferred is that calling directly from write
+ *     causes problems if you're writing from say the scheduler.
+ */
+static void wakeup_readers(void *private)
+{
+       struct rchan_buf *buf = private;
+       wake_up_interruptible(&buf->read_wait);
+}
+
+/**
+ *     __relay_reset - reset a channel buffer
+ *     @buf: the channel buffer
+ *     @init: 1 if this is a first-time initialization
+ *
+ *     See relay_reset for description of effect.
+ */
+static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
+{
+       size_t i;
+
+       if (init) {
+               init_waitqueue_head(&buf->read_wait);
+               kref_init(&buf->kref);
+               INIT_WORK(&buf->wake_readers, NULL, NULL);
+       } else {
+               cancel_delayed_work(&buf->wake_readers);
+               flush_scheduled_work();
+       }
+
+       buf->subbufs_produced = 0;
+       buf->subbufs_consumed = 0;
+       buf->bytes_consumed = 0;
+       buf->finalized = 0;
+       buf->data = buf->start;
+       buf->offset = 0;
+
+       for (i = 0; i < buf->chan->n_subbufs; i++)
+               buf->padding[i] = 0;
+
+       buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0);
+}
+
+/**
+ *     relay_reset - reset the channel
+ *     @chan: the channel
+ *
+ *     This has the effect of erasing all data from all channel buffers
+ *     and restarting the channel in its initial state.  The buffers
+ *     are not freed, so any mappings are still in effect.
+ *
+ *     NOTE: Care should be taken that the channel isn't actually
+ *     being used by anything when this call is made.
+ */
+void relay_reset(struct rchan *chan)
+{
+       unsigned int i;
+
+       if (!chan)
+               return;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!chan->buf[i])
+                       continue;
+               __relay_reset(chan->buf[i], 0);
+       }
+}
+
+/**
+ *     relay_open_buf - create a new channel buffer in relayfs
+ *
+ *     Internal - used by relay_open().
+ */
+static struct rchan_buf *relay_open_buf(struct rchan *chan,
+                                       const char *filename,
+                                       struct dentry *parent)
+{
+       struct rchan_buf *buf;
+       struct dentry *dentry;
+
+       /* Create file in fs */
+       dentry = relayfs_create_file(filename, parent, S_IRUSR, chan);
+       if (!dentry)
+               return NULL;
+
+       buf = RELAYFS_I(dentry->d_inode)->buf;
+       buf->dentry = dentry;
+       __relay_reset(buf, 1);
+
+       return buf;
+}
+
+/**
+ *     relay_close_buf - close a channel buffer
+ *     @buf: channel buffer
+ *
+ *     Marks the buffer finalized and restores the default callbacks.
+ *     The channel buffer and channel buffer data structure are then freed
+ *     automatically when the last reference is given up.
+ */
+static inline void relay_close_buf(struct rchan_buf *buf)
+{
+       buf->finalized = 1;
+       buf->chan->cb = &default_channel_callbacks;
+       cancel_delayed_work(&buf->wake_readers);
+       flush_scheduled_work();
+       kref_put(&buf->kref, relay_remove_buf);
+}
+
+static inline void setup_callbacks(struct rchan *chan,
+                                  struct rchan_callbacks *cb)
+{
+       if (!cb) {
+               chan->cb = &default_channel_callbacks;
+               return;
+       }
+
+       if (!cb->subbuf_start)
+               cb->subbuf_start = subbuf_start_default_callback;
+       if (!cb->buf_mapped)
+               cb->buf_mapped = buf_mapped_default_callback;
+       if (!cb->buf_unmapped)
+               cb->buf_unmapped = buf_unmapped_default_callback;
+       chan->cb = cb;
+}
+
+/**
+ *     relay_open - create a new relayfs channel
+ *     @base_filename: base name of files to create
+ *     @parent: dentry of parent directory, NULL for root directory
+ *     @subbuf_size: size of sub-buffers
+ *     @n_subbufs: number of sub-buffers
+ *     @cb: client callback functions
+ *
+ *     Returns channel pointer if successful, NULL otherwise.
+ *
+ *     Creates a channel buffer for each cpu using the sizes and
+ *     attributes specified.  The created channel buffer files
+ *     will be named base_filename0...base_filenameN-1.  File
+ *     permissions will be S_IRUSR.
+ */
+struct rchan *relay_open(const char *base_filename,
+                        struct dentry *parent,
+                        size_t subbuf_size,
+                        size_t n_subbufs,
+                        struct rchan_callbacks *cb)
+{
+       unsigned int i;
+       struct rchan *chan;
+       char *tmpname;
+
+       if (!base_filename)
+               return NULL;
+
+       if (!(subbuf_size && n_subbufs))
+               return NULL;
+
+       chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
+       if (!chan)
+               return NULL;
+
+       chan->version = RELAYFS_CHANNEL_VERSION;
+       chan->n_subbufs = n_subbufs;
+       chan->subbuf_size = subbuf_size;
+       chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
+       setup_callbacks(chan, cb);
+       kref_init(&chan->kref);
+
+       tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+       if (!tmpname)
+               goto free_chan;
+
+       for_each_online_cpu(i) {
+               sprintf(tmpname, "%s%d", base_filename, i);
+               chan->buf[i] = relay_open_buf(chan, tmpname, parent);
+               chan->buf[i]->cpu = i;
+               if (!chan->buf[i])
+                       goto free_bufs;
+       }
+
+       kfree(tmpname);
+       return chan;
+
+free_bufs:
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!chan->buf[i])
+                       break;
+               relay_close_buf(chan->buf[i]);
+       }
+       kfree(tmpname);
+
+free_chan:
+       kref_put(&chan->kref, relay_destroy_channel);
+       return NULL;
+}
+
+/**
+ *     relay_switch_subbuf - switch to a new sub-buffer
+ *     @buf: channel buffer
+ *     @length: size of current event
+ *
+ *     Returns either the length passed in or 0 if full.
+
+ *     Performs sub-buffer-switch tasks such as invoking callbacks,
+ *     updating padding counts, waking up readers, etc.
+ */
+size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
+{
+       void *old, *new;
+       size_t old_subbuf, new_subbuf;
+
+       if (unlikely(length > buf->chan->subbuf_size))
+               goto toobig;
+
+       if (buf->offset != buf->chan->subbuf_size + 1) {
+               buf->prev_padding = buf->chan->subbuf_size - buf->offset;
+               old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
+               buf->padding[old_subbuf] = buf->prev_padding;
+               buf->subbufs_produced++;
+               if (waitqueue_active(&buf->read_wait)) {
+                       PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
+                       schedule_delayed_work(&buf->wake_readers, 1);
+               }
+       }
+
+       old = buf->data;
+       new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
+       new = buf->start + new_subbuf * buf->chan->subbuf_size;
+       buf->offset = 0;
+       if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
+               buf->offset = buf->chan->subbuf_size + 1;
+               return 0;
+       }
+       buf->data = new;
+       buf->padding[new_subbuf] = 0;
+
+       if (unlikely(length + buf->offset > buf->chan->subbuf_size))
+               goto toobig;
+
+       return length;
+
+toobig:
+       printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length);
+       WARN_ON(1);
+       return 0;
+}
+
+/**
+ *     relay_subbufs_consumed - update the buffer's sub-buffers-consumed count
+ *     @chan: the channel
+ *     @cpu: the cpu associated with the channel buffer to update
+ *     @subbufs_consumed: number of sub-buffers to add to current buf's count
+ *
+ *     Adds to the channel buffer's consumed sub-buffer count.
+ *     subbufs_consumed should be the number of sub-buffers newly consumed,
+ *     not the total consumed.
+ *
+ *     NOTE: kernel clients don't need to call this function if the channel
+ *     mode is 'overwrite'.
+ */
+void relay_subbufs_consumed(struct rchan *chan,
+                           unsigned int cpu,
+                           size_t subbufs_consumed)
+{
+       struct rchan_buf *buf;
+
+       if (!chan)
+               return;
+
+       if (cpu >= NR_CPUS || !chan->buf[cpu])
+               return;
+
+       buf = chan->buf[cpu];
+       buf->subbufs_consumed += subbufs_consumed;
+       if (buf->subbufs_consumed > buf->subbufs_produced)
+               buf->subbufs_consumed = buf->subbufs_produced;
+}
+
+/**
+ *     relay_destroy_channel - free the channel struct
+ *
+ *     Should only be called from kref_put().
+ */
+void relay_destroy_channel(struct kref *kref)
+{
+       struct rchan *chan = container_of(kref, struct rchan, kref);
+       kfree(chan);
+}
+
+/**
+ *     relay_close - close the channel
+ *     @chan: the channel
+ *
+ *     Closes all channel buffers and frees the channel.
+ */
+void relay_close(struct rchan *chan)
+{
+       unsigned int i;
+
+       if (!chan)
+               return;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!chan->buf[i])
+                       continue;
+               relay_close_buf(chan->buf[i]);
+       }
+
+       kref_put(&chan->kref, relay_destroy_channel);
+}
+
+/**
+ *     relay_flush - close the channel
+ *     @chan: the channel
+ *
+ *     Flushes all channel buffers i.e. forces buffer switch.
+ */
+void relay_flush(struct rchan *chan)
+{
+       unsigned int i;
+
+       if (!chan)
+               return;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!chan->buf[i])
+                       continue;
+               relay_switch_subbuf(chan->buf[i], 0);
+       }
+}
+
+EXPORT_SYMBOL_GPL(relay_open);
+EXPORT_SYMBOL_GPL(relay_close);
+EXPORT_SYMBOL_GPL(relay_flush);
+EXPORT_SYMBOL_GPL(relay_reset);
+EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
+EXPORT_SYMBOL_GPL(relay_switch_subbuf);
+EXPORT_SYMBOL_GPL(relay_buf_full);
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
new file mode 100644 (file)
index 0000000..703503f
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _RELAY_H
+#define _RELAY_H
+
+struct dentry *relayfs_create_file(const char *name,
+                                  struct dentry *parent,
+                                  int mode,
+                                  struct rchan *chan);
+extern int relayfs_remove(struct dentry *dentry);
+extern int relay_buf_empty(struct rchan_buf *buf);
+extern void relay_destroy_channel(struct kref *kref);
+
+#endif /* _RELAY_H */
index 997640c99c7d88030d2de6e980deee138a18db0e..faf1512173eb23d36cf861b651b3572ded618999 100644 (file)
@@ -114,8 +114,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
        sb->s_dirt = 1;
@@ -200,8 +199,7 @@ do_more:
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
 
@@ -459,8 +457,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
        sb->s_dirt = 1;
@@ -585,8 +582,7 @@ succed:
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
        sb->s_dirt = 1;
index 61a6b1542fc5f01eb239cca652aaf7c2bd6d2b35..0938945b9cbc2c628750061a05f772ebeee670e5 100644 (file)
@@ -124,8 +124,7 @@ void ufs_free_inode (struct inode * inode)
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
        
@@ -249,8 +248,7 @@ cg_found:
        ubh_mark_buffer_dirty (USPI_UBH);
        ubh_mark_buffer_dirty (UCPI_UBH);
        if (sb->s_flags & MS_SYNCHRONOUS) {
-               ubh_wait_on_buffer (UCPI_UBH);
-               ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi);
+               ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
                ubh_wait_on_buffer (UCPI_UBH);
        }
        sb->s_dirt = 1;
index e312bf8bad9fd5432e44df7c9c36d31e1a63e545..61d2e35012a462e2cb6be0f9fc27bd10e20db0b1 100644 (file)
@@ -285,8 +285,7 @@ next:;
                }
        }
        if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
-               ubh_wait_on_buffer (ind_ubh);
-               ubh_ll_rw_block (WRITE, 1, &ind_ubh);
+               ubh_ll_rw_block (SWRITE, 1, &ind_ubh);
                ubh_wait_on_buffer (ind_ubh);
        }
        ubh_brelse (ind_ubh);
@@ -353,8 +352,7 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
                }
        }
        if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
-               ubh_wait_on_buffer (dind_bh);
-               ubh_ll_rw_block (WRITE, 1, &dind_bh);
+               ubh_ll_rw_block (SWRITE, 1, &dind_bh);
                ubh_wait_on_buffer (dind_bh);
        }
        ubh_brelse (dind_bh);
@@ -418,8 +416,7 @@ static int ufs_trunc_tindirect (struct inode * inode)
                }
        }
        if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
-               ubh_wait_on_buffer (tind_bh);
-               ubh_ll_rw_block (WRITE, 1, &tind_bh);
+               ubh_ll_rw_block (SWRITE, 1, &tind_bh);
                ubh_wait_on_buffer (tind_bh);
        }
        ubh_brelse (tind_bh);
diff --git a/fs/umsdos/notes b/fs/umsdos/notes
deleted file mode 100644 (file)
index 3c47d1f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-This file contain idea and things I don't want to forget
-
-Possible bug in fs/read_write.c
-Function sys_readdir()
-
-       There is a call the verify_area that does not take in account
-       the count parameter. I guess it should read
-
-       error = verify_area(VERIFY_WRITE, dirent, count*sizeof (*dirent));
-
-       instead of
-
-       error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
-
-       Of course, now , count is always 1
-
-
index dc8bc7624f26be341900d900340cb0e7bcb6ce60..3f9c64bea151fd7c6df4297e8bfa01b626a02bd5 100644 (file)
@@ -325,6 +325,8 @@ removexattr(struct dentry *d, char __user *name)
                down(&d->d_inode->i_sem);
                error = d->d_inode->i_op->removexattr(d, kname);
                up(&d->d_inode->i_sem);
+               if (!error)
+                       fsnotify_xattr(d);
        }
 out:
        return error;
diff --git a/include/asm-alpha/auxvec.h b/include/asm-alpha/auxvec.h
new file mode 100644 (file)
index 0000000..e96fe88
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ASM_ALPHA_AUXVEC_H
+#define __ASM_ALPHA_AUXVEC_H
+
+/* Reserve these numbers for any future use of a VDSO.  */
+#if 0
+#define AT_SYSINFO             32
+#define AT_SYSINFO_EHDR                33
+#endif
+
+/* More complete cache descriptions than AT_[DIU]CACHEBSIZE.  If the
+   value is -1, then the cache doesn't exist.  Otherwise:
+
+      bit 0-3:   Cache set-associativity; 0 means fully associative.
+      bit 4-7:   Log2 of cacheline size.
+      bit 8-31:          Size of the entire cache >> 8.
+      bit 32-63:  Reserved.
+*/
+
+#define AT_L1I_CACHESHAPE      34
+#define AT_L1D_CACHESHAPE      35
+#define AT_L2_CACHESHAPE       36
+#define AT_L3_CACHESHAPE       37
+
+#endif /* __ASM_ALPHA_AUXVEC_H */
index e94a945a231429fe357451f0bacf7e84feabd0f5..6c2d78fba264ac21ce616fcf9622bf1ea9b89fc7 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_ALPHA_ELF_H
 #define __ASM_ALPHA_ELF_H
 
+#include <asm/auxvec.h>
+
 /* Special values for the st_other field in the symbol table.  */
 
 #define STO_ALPHA_NOPV         0x80
@@ -142,26 +144,6 @@ extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task);
        : amask (AMASK_CIX) ? "ev6" : "ev67");  \
 })
 
-/* Reserve these numbers for any future use of a VDSO.  */
-#if 0
-#define AT_SYSINFO             32
-#define AT_SYSINFO_EHDR                33
-#endif
-
-/* More complete cache descriptions than AT_[DIU]CACHEBSIZE.  If the
-   value is -1, then the cache doesn't exist.  Otherwise:
-
-      bit 0-3:   Cache set-associativity; 0 means fully associative.
-      bit 4-7:   Log2 of cacheline size.
-      bit 8-31:          Size of the entire cache >> 8.
-      bit 32-63:  Reserved.
-*/
-
-#define AT_L1I_CACHESHAPE      34
-#define AT_L1D_CACHESHAPE      35
-#define AT_L2_CACHESHAPE       36
-#define AT_L3_CACHESHAPE       37
-
 #ifdef __KERNEL__
 
 #define SET_PERSONALITY(EX, IBCS2)                             \
index 6b7d6c1649ce9c8d30aef7586ee8abad5bfabe59..87f2cf459e266367be6f16f10c545f85d41e9bbc 100644 (file)
@@ -3,10 +3,6 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE        0003
-#define O_RDONLY           00
-#define O_WRONLY           01
-#define O_RDWR             02
 #define O_CREAT                 01000  /* not fcntl */
 #define O_TRUNC                 02000  /* not fcntl */
 #define O_EXCL          04000  /* not fcntl */
 
 #define O_NONBLOCK      00004
 #define O_APPEND        00010
-#define O_NDELAY       O_NONBLOCK
 #define O_SYNC         040000
-#define FASYNC         020000  /* fcntl, for BSD compatibility */
 #define O_DIRECTORY    0100000 /* must be a directory */
 #define O_NOFOLLOW     0200000 /* don't follow links */
 #define O_LARGEFILE    0400000 /* will be set by the kernel on every open */
 #define O_DIRECT       02000000 /* direct disk access - should check with OSF/1 */
 #define O_NOATIME      04000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
 #define F_GETLK                7
 #define F_SETLK                8
 #define F_SETLKW       9
@@ -37,9 +26,6 @@
 #define F_SETSIG       10      /*  for sockets. */
 #define F_GETSIG       11      /*  for sockets. */
 
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
 /* for posix fcntl() and lockf() */
 #define F_RDLCK                1
 #define F_WRLCK                2
 
 #define F_INPROGRESS   64
 
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW        192     /* ... Which allows concurrent read & write ops */
-struct flock {
-       short l_type;
-       short l_whence;
-       __kernel_off_t l_start;
-       __kernel_off_t l_len;
-       __kernel_pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
+#include <asm-generic/fcntl.h>
 
 #endif
diff --git a/include/asm-alpha/futex.h b/include/asm-alpha/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-alpha/hdreg.h b/include/asm-alpha/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index 4c39ee750f388f71cff6ac5dd0de7b866f1c7066..22de3b434a22a59d7f16bce6520787efab1fc8f9 100644 (file)
        __access_ok(((unsigned long)(addr)),(size),get_fs());   \
 })
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
index 79138dcfb4accafa92a10910cdc0a70a93d42e8c..d64ee9211eeddc63fbb888421f01157f72f382a1 100644 (file)
@@ -30,6 +30,9 @@
 #define __ASM_ARCH_OMAP_H4_H
 
 /* Placeholder for H4 specific defines */
+/* GPMC CS1 */
+#define OMAP24XX_ETHR_START             0x08000300
+#define OMAP24XX_ETHR_GPIO_IRQ         92
 
 #endif /*  __ASM_ARCH_OMAP_H4_H */
 
index 0f1abaefe4decf6c81f7c5d8feefb3b8ee24c9bc..79574e0ed13d3c82d03c13cd4fbcc7df69d5f4c2 100644 (file)
 #define OMAP1510P1_EMIFS_PRI_VALUE             0x00
 #define OMAP1510P1_EMIFF_PRI_VALUE             0x00
 
-/*
- * These definitions define an area of FLASH set aside
- * for the use of MTD/JFFS2. This is the area of flash
- * that a JFFS2 filesystem will reside which is mounted
- * at boot with the "root=/dev/mtdblock/0 rw"
- * command line option. The flash address used here must
- * fall within the legal range defined by rrload for storing
- * the filesystem component. This address will be sufficiently
- * deep into the overall flash range to avoid the other
- * components also stored in flash such as the bootloader,
- * the bootloader params, and the kernel.
- * The SW2 settings for the map below are:
- * 1 off, 2 off, 3 on, 4 off.
- */
-
-/* Intel flash_0, partitioned as expected by rrload */
-#define OMAP_FLASH_0_BASE      0xD8000000
-#define OMAP_FLASH_0_START     0x00000000
-#define OMAP_FLASH_0_SIZE      SZ_16M
-
-/* Intel flash_1, used for cramfs or other flash file systems */
-#define OMAP_FLASH_1_BASE      0xD9000000
-#define OMAP_FLASH_1_START     0x01000000
-#define OMAP_FLASH_1_SIZE      SZ_16M
-
 #define NR_FPGA_IRQS           24
 #define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
 
index 0c224cc74fe4289678408a1095758723c9a18af1..691e52a52b433f4fe5cf43e9feeabefdd03e04ee 100644 (file)
 #define OMAP_SDRAM_DEVICE              D256M_1X16_4B
 #endif
 
-/*
- * These definitions define an area of FLASH set aside
- * for the use of MTD/JFFS2. This is the area of flash
- * that a JFFS2 filesystem will reside which is mounted
- * at boot with the "root=/dev/mtdblock/0 rw"
- * command line option.
- */
-
-/* Intel flash_0, partitioned as expected by rrload */
-#define OMAP_FLASH_0_BASE      0xD8000000      /* VA */
-#define OMAP_FLASH_0_START     0x00000000      /* PA */
-#define OMAP_FLASH_0_SIZE      SZ_32M
-
 #define MAXIRQNUM              IH_BOARD_BASE
 #define MAXFIQNUM              MAXIRQNUM
 #define MAXSWINUM              MAXIRQNUM
 
 #define NR_IRQS                        (MAXIRQNUM + 1)
 
+/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
+#define OMAP_NAND_FLASH_START1    0x0A000000 /* CS2B */
+#define OMAP_NAND_FLASH_START2    0x0C000000 /* CS3 */
+
 #endif
index 33977b8956fbb1abcaec714b839e39be6a148305..ed6d346ee12344da8fa651956b3742360b433f09 100644 (file)
 #ifndef __ASM_ARCH_VOICEBLUE_H
 #define __ASM_ARCH_VOICEBLUE_H
 
-#if (EXTERNAL_MAX_NR_PORTS < 4)
-#undef EXTERNAL_MAX_NR_PORTS
-#define EXTERNAL_MAX_NR_PORTS  4
-#endif
-
 extern void voiceblue_wdt_enable(void);
 extern void voiceblue_wdt_disable(void);
 extern void voiceblue_wdt_ping(void);
index 95bd625480c13afd715fe45a70e0a40bb9c57cf0..a0040cd86639452426f7a715e5f9043237fdc5ed 100644 (file)
@@ -30,10 +30,23 @@ struct omap_clock_config {
        u8 system_clock_type;
 };
 
+struct omap_mmc_conf {
+       unsigned enabled:1;
+       /* nomux means "standard" muxing is wrong on this board, and that
+        * board-specific code handled it before common init logic.
+        */
+       unsigned nomux:1;
+       /* switch pin can be for card detect (default) or card cover */
+       unsigned cover:1;
+       /* 4 wire signaling is optional, and is only used for SD/SDIO */
+       unsigned wire4:1;
+       s16 power_pin;
+       s16 switch_pin;
+       s16 wp_pin;
+};
+
 struct omap_mmc_config {
-       u8 mmc_blocks;
-       s16 mmc1_power_pin, mmc2_power_pin;
-       s16 mmc1_switch_pin, mmc2_switch_pin;
+       struct omap_mmc_conf mmc[2];
 };
 
 struct omap_serial_console_config {
index e8786713ee5cc561cda61b7360c15e42008b4d60..1119e2b53e724fb9773c35dcaf793cc7b7df62e0 100644 (file)
@@ -38,146 +38,179 @@ extern unsigned int system_rev;
 /*
  * Test if multicore OMAP support is needed
  */
-#undef MULTI_OMAP
+#undef MULTI_OMAP1
+#undef MULTI_OMAP2
 #undef OMAP_NAME
 
 #ifdef CONFIG_ARCH_OMAP730
 # ifdef OMAP_NAME
-#  undef  MULTI_OMAP
-#  define MULTI_OMAP
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
 # else
 #  define OMAP_NAME omap730
 # endif
 #endif
 #ifdef CONFIG_ARCH_OMAP1510
 # ifdef OMAP_NAME
-#  undef  MULTI_OMAP
-#  define MULTI_OMAP
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
 # else
 #  define OMAP_NAME omap1510
 # endif
 #endif
 #ifdef CONFIG_ARCH_OMAP16XX
 # ifdef OMAP_NAME
-#  undef  MULTI_OMAP
-#  define MULTI_OMAP
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
 # else
-#  define OMAP_NAME omap1610
+#  define OMAP_NAME omap16xx
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP16XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP
-#  define MULTI_OMAP
+#ifdef CONFIG_ARCH_OMAP24XX
+# if (defined(OMAP_NAME) || defined(MULTI_OMAP1))
+#  error "OMAP1 and OMAP2 can't be selected at the same time"
 # else
-#  define OMAP_NAME omap1710
+#  undef  MULTI_OMAP2
+#  define OMAP_NAME omap24xx
 # endif
 #endif
 
 /*
- * Generate various OMAP cpu specific macros, and cpu class
- * specific macros
+ * Macros to group OMAP into cpu classes.
+ * These can be used in most places.
+ * cpu_is_omap7xx():   True for OMAP730
+ * cpu_is_omap15xx():  True for OMAP1510 and OMAP5910
+ * cpu_is_omap16xx():  True for OMAP1610, OMAP5912 and OMAP1710
+ * cpu_is_omap24xx():  True for OMAP2420
  */
-#define GET_OMAP_TYPE  ((system_rev >> 24) & 0xff)
 #define GET_OMAP_CLASS (system_rev & 0xff)
 
-#define IS_OMAP_TYPE(type, id)                         \
-static inline int is_omap ##type (void)                        \
-{                                                      \
-       return (GET_OMAP_TYPE == (id)) ? 1 : 0;         \
-}
-
 #define IS_OMAP_CLASS(class, id)                       \
 static inline int is_omap ##class (void)               \
 {                                                      \
        return (GET_OMAP_CLASS == (id)) ? 1 : 0;        \
 }
 
-IS_OMAP_TYPE(730, 0x07)
-IS_OMAP_TYPE(1510, 0x15)
-IS_OMAP_TYPE(1610, 0x16)
-IS_OMAP_TYPE(5912, 0x16)
-IS_OMAP_TYPE(1710, 0x17)
-IS_OMAP_TYPE(2420, 0x24)
-
 IS_OMAP_CLASS(7xx, 0x07)
 IS_OMAP_CLASS(15xx, 0x15)
 IS_OMAP_CLASS(16xx, 0x16)
 IS_OMAP_CLASS(24xx, 0x24)
 
-/*
- * Macros to group OMAP types into cpu classes.
- * These can be used in most places.
- * cpu_is_omap15xx():  True for 1510 and 5910
- * cpu_is_omap16xx():  True for 1610, 5912 and 1710
- */
-#if defined(MULTI_OMAP)
-# define cpu_is_omap7xx()              is_omap7xx()
-# define cpu_is_omap15xx()             is_omap15xx()
-# if !(defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP730))
-#  define cpu_is_omap16xx()            1
-# else
+#define cpu_is_omap7xx()               0
+#define cpu_is_omap15xx()              0
+#define cpu_is_omap16xx()              0
+#define cpu_is_omap24xx()              0
+
+#if defined(MULTI_OMAP1)
+# if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()             is_omap7xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+#  undef  cpu_is_omap15xx
+#  define cpu_is_omap15xx()            is_omap15xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  undef  cpu_is_omap16xx
 #  define cpu_is_omap16xx()            is_omap16xx()
 # endif
 #else
 # if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap7xx
 #  define cpu_is_omap7xx()             1
-# else
-#  define cpu_is_omap7xx()             0
 # endif
 # if defined(CONFIG_ARCH_OMAP1510)
+#  undef  cpu_is_omap15xx
 #  define cpu_is_omap15xx()            1
-# else
-#  define cpu_is_omap15xx()            0
 # endif
 # if defined(CONFIG_ARCH_OMAP16XX)
+#  undef  cpu_is_omap16xx
 #  define cpu_is_omap16xx()            1
-# else
-#  define cpu_is_omap16xx()            0
+# endif
+# if defined(CONFIG_ARCH_OMAP24XX)
+#  undef  cpu_is_omap24xx
+#  define cpu_is_omap24xx()            1
 # endif
 #endif
 
-#if defined(MULTI_OMAP)
-# define cpu_is_omap730()              is_omap730()
-# define cpu_is_omap1510()             is_omap1510()
-# define cpu_is_omap1610()             is_omap1610()
-# define cpu_is_omap5912()             is_omap5912()
-# define cpu_is_omap1710()             is_omap1710()
+/*
+ * Macros to detect individual cpu types.
+ * These are only rarely needed.
+ * cpu_is_omap730():   True for OMAP730
+ * cpu_is_omap1510():  True for OMAP1510
+ * cpu_is_omap1610():  True for OMAP1610
+ * cpu_is_omap1611():  True for OMAP1611
+ * cpu_is_omap5912():  True for OMAP5912
+ * cpu_is_omap1621():  True for OMAP1621
+ * cpu_is_omap1710():  True for OMAP1710
+ * cpu_is_omap2420():  True for OMAP2420
+ */
+#define GET_OMAP_TYPE  ((system_rev >> 16) & 0xffff)
+
+#define IS_OMAP_TYPE(type, id)                         \
+static inline int is_omap ##type (void)                        \
+{                                                      \
+       return (GET_OMAP_TYPE == (id)) ? 1 : 0;         \
+}
+
+IS_OMAP_TYPE(730, 0x0730)
+IS_OMAP_TYPE(1510, 0x1510)
+IS_OMAP_TYPE(1610, 0x1610)
+IS_OMAP_TYPE(1611, 0x1611)
+IS_OMAP_TYPE(5912, 0x1611)
+IS_OMAP_TYPE(1621, 0x1621)
+IS_OMAP_TYPE(1710, 0x1710)
+IS_OMAP_TYPE(2420, 0x2420)
+
+#define cpu_is_omap730()               0
+#define cpu_is_omap1510()              0
+#define cpu_is_omap1610()              0
+#define cpu_is_omap5912()              0
+#define cpu_is_omap1611()              0
+#define cpu_is_omap1621()              0
+#define cpu_is_omap1710()              0
+#define cpu_is_omap2420()              0
+
+#if defined(MULTI_OMAP1)
+# if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap730
+#  define cpu_is_omap730()             is_omap730()
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+#  undef  cpu_is_omap1510
+#  define cpu_is_omap1510()            is_omap1510()
+# endif
 #else
 # if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap730
 #  define cpu_is_omap730()             1
-# else
-#  define cpu_is_omap730()             0
 # endif
 # if defined(CONFIG_ARCH_OMAP1510)
+#  undef  cpu_is_omap1510
 #  define cpu_is_omap1510()            1
-# else
-#  define cpu_is_omap1510()            0
 # endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-#  define cpu_is_omap1610()            1
-# else
-#  define cpu_is_omap1610()            0
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-#  define cpu_is_omap5912()            1
-# else
-#  define cpu_is_omap5912()            0
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
+#endif
+
+/*
+ * Whether we have MULTI_OMAP1 or not, we still need to distinguish
+ * between 1611B/5912 and 1710.
+ */
+#if defined(CONFIG_ARCH_OMAP16XX)
+# undef  cpu_is_omap1610
+# undef  cpu_is_omap1611
+# undef  cpu_is_omap5912
+# undef  cpu_is_omap1621
+# undef  cpu_is_omap1710
 # define cpu_is_omap1610()             is_omap1610()
+# define cpu_is_omap1611()             is_omap1611()
 # define cpu_is_omap5912()             is_omap5912()
+# define cpu_is_omap1621()             is_omap1621()
 # define cpu_is_omap1710()             is_omap1710()
-# else
-# define cpu_is_omap1610()             0
-# define cpu_is_omap5912()             0
-# define cpu_is_omap1710()             0
-# endif
-# if defined(CONFIG_ARCH_OMAP2420)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
+#  undef  cpu_is_omap2420
 #  define cpu_is_omap2420()            1
-# else
-#  define cpu_is_omap2420()            0
-# endif
 #endif
 
 #endif
index 83bb458afd0ba7480289e87d0b141596a71c2b9e..ca4f577f967588396bdd07146e74d41cda84682c 100644 (file)
@@ -14,6 +14,7 @@
                .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
+#ifdef CONFIG_ARCH_OMAP1
                moveq   \rx, #0xff000000        @ physical base address
                movne   \rx, #0xfe000000        @ virtual base
                orr     \rx, \rx, #0x00fb0000
 #endif
 #if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3)
                orr     \rx, \rx, #0x00000800   @ UART 2 & 3
+#endif
+
+#elif  CONFIG_ARCH_OMAP2
+               moveq   \rx, #0x48000000        @ physical base address
+               movne   \rx, #0xd8000000        @ virtual base
+               orr     \rx, \rx, #0x0006a000
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
+               add     \rx, \rx, #0x00002000   @ UART 2
+#endif
+#ifdef CONFIG_OMAP_LL_DEBUG_UART3
+               add     \rx, \rx, #0x00004000   @ UART 3
+#endif
 #endif
                .endm
 
index ce114ce5af5d6af63d3d44af7e49c35eb9f3b701..04ebef5c6e95d180142d3e25e938630705b4341c 100644 (file)
@@ -240,6 +240,7 @@ extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
 
 extern dma_addr_t omap_get_dma_src_pos(int lch);
 extern dma_addr_t omap_get_dma_dst_pos(int lch);
+extern int omap_get_dma_src_addr_counter(int lch);
 extern void omap_clear_dma(int lch);
 extern int omap_dma_running(void);
 
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
new file mode 100644 (file)
index 0000000..11772c7
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * linux/include/asm-arm/arm/arch-omap/dmtimer.h
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_TIMER_H
+#define __ASM_ARCH_TIMER_H
+
+#include <linux/list.h>
+
+#define OMAP_TIMER_SRC_ARMXOR          0x00
+#define OMAP_TIMER_SRC_32_KHZ          0x01
+#define OMAP_TIMER_SRC_EXT_CLK         0x02
+
+/* timer control reg bits */
+#define OMAP_TIMER_CTRL_CAPTMODE       (1 << 13)
+#define OMAP_TIMER_CTRL_PT             (1 << 12)
+#define OMAP_TIMER_CTRL_TRG_OVERFLOW   (0x1 << 10)
+#define OMAP_TIMER_CTRL_TRG_OFANDMATCH (0x2 << 10)
+#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH  (0x1 << 8)
+#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW  (0x2 << 8)
+#define OMAP_TIMER_CTRL_TCM_BOTHEDGES  (0x3 << 8)
+#define OMAP_TIMER_CTRL_SCPWM          (1 << 7)
+#define OMAP_TIMER_CTRL_CE             (1 << 6)        /* compare enable */
+#define OMAP_TIMER_CTRL_PRE            (1 << 5)        /* prescaler enable */
+#define OMAP_TIMER_CTRL_PTV_SHIFT      2               /* how much to shift the prescaler value */
+#define OMAP_TIMER_CTRL_AR             (1 << 1)        /* auto-reload enable */
+#define OMAP_TIMER_CTRL_ST             (1 << 0)        /* start timer */
+
+/* timer interrupt enable bits */
+#define OMAP_TIMER_INT_CAPTURE         (1 << 2)
+#define OMAP_TIMER_INT_OVERFLOW                (1 << 1)
+#define OMAP_TIMER_INT_MATCH           (1 << 0)
+
+
+struct omap_dm_timer {
+       struct list_head timer_list;
+
+       u32 base;
+       unsigned int irq;
+};
+
+u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg);
+void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value);
+
+struct omap_dm_timer * omap_dm_timer_request(void);
+void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value);
+void omap_dm_timer_enable_compare(struct omap_dm_timer *timer);
+void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer);
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer);
+void omap_dm_timer_start(struct omap_dm_timer *timer);
+void omap_dm_timer_stop(struct omap_dm_timer *timer);
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load);
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
+void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
+
+int omap_dm_timers_active(void);
+
+#endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
new file mode 100644 (file)
index 0000000..57bf4f3
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * linux/include/asm-arm/arch-omap/dsp.h
+ *
+ * Header for OMAP DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2005/06/01:  DSP Gateway version 3.3
+ */
+
+#ifndef ASM_ARCH_DSP_H
+#define ASM_ARCH_DSP_H
+
+
+/*
+ * for /dev/dspctl/ctl
+ */
+#define OMAP_DSP_IOCTL_RESET                   1
+#define OMAP_DSP_IOCTL_RUN                     2
+#define OMAP_DSP_IOCTL_SETRSTVECT              3
+#define OMAP_DSP_IOCTL_CPU_IDLE                        4
+#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON                5
+#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF       6
+#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON                7
+#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF       8
+#define OMAP_DSP_IOCTL_GBL_IDLE                        9
+#define OMAP_DSP_IOCTL_DSPCFG                  10
+#define OMAP_DSP_IOCTL_DSPUNCFG                        11
+#define OMAP_DSP_IOCTL_TASKCNT                 12
+#define OMAP_DSP_IOCTL_POLL                    13
+#define OMAP_DSP_IOCTL_REGMEMR                 40
+#define OMAP_DSP_IOCTL_REGMEMW                 41
+#define OMAP_DSP_IOCTL_REGIOR                  42
+#define OMAP_DSP_IOCTL_REGIOW                  43
+#define OMAP_DSP_IOCTL_GETVAR                  44
+#define OMAP_DSP_IOCTL_SETVAR                  45
+#define OMAP_DSP_IOCTL_RUNLEVEL                        50
+#define OMAP_DSP_IOCTL_SUSPEND                 51
+#define OMAP_DSP_IOCTL_RESUME                  52
+#define OMAP_DSP_IOCTL_FBEN                    53
+#define OMAP_DSP_IOCTL_FBDIS                   54
+#define OMAP_DSP_IOCTL_MBSEND                  99
+
+/*
+ * for taskdev
+ * (ioctls below should be >= 0x10000)
+ */
+#define OMAP_DSP_TASK_IOCTL_BFLSH      0x10000
+#define OMAP_DSP_TASK_IOCTL_SETBSZ     0x10001
+#define OMAP_DSP_TASK_IOCTL_LOCK       0x10002
+#define OMAP_DSP_TASK_IOCTL_UNLOCK     0x10003
+#define OMAP_DSP_TASK_IOCTL_GETNAME    0x10004
+
+/*
+ * for /dev/dspctl/mem
+ */
+#define OMAP_DSP_MEM_IOCTL_EXMAP       1
+#define OMAP_DSP_MEM_IOCTL_EXUNMAP     2
+#define OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH 3
+#define OMAP_DSP_MEM_IOCTL_FBEXPORT    5
+#define OMAP_DSP_MEM_IOCTL_MMUITACK    7
+#define OMAP_DSP_MEM_IOCTL_MMUINIT     9
+#define OMAP_DSP_MEM_IOCTL_KMEM_RESERVE        11
+#define OMAP_DSP_MEM_IOCTL_KMEM_RELEASE        12
+
+struct omap_dsp_mapinfo {
+       unsigned long dspadr;
+       unsigned long size;
+};
+
+/*
+ * for /dev/dspctl/twch
+ */
+#define OMAP_DSP_TWCH_IOCTL_MKDEV      1
+#define OMAP_DSP_TWCH_IOCTL_RMDEV      2
+#define OMAP_DSP_TWCH_IOCTL_TADD       11
+#define OMAP_DSP_TWCH_IOCTL_TDEL       12
+#define OMAP_DSP_TWCH_IOCTL_TKILL      13
+
+#define OMAP_DSP_DEVSTATE_NOTASK       0x00000001
+#define OMAP_DSP_DEVSTATE_ATTACHED     0x00000002
+#define OMAP_DSP_DEVSTATE_GARBAGE      0x00000004
+#define OMAP_DSP_DEVSTATE_INVALID      0x00000008
+#define OMAP_DSP_DEVSTATE_ADDREQ       0x00000100
+#define OMAP_DSP_DEVSTATE_DELREQ       0x00000200
+#define OMAP_DSP_DEVSTATE_ADDFAIL      0x00001000
+#define OMAP_DSP_DEVSTATE_ADDING       0x00010000
+#define OMAP_DSP_DEVSTATE_DELING       0x00020000
+#define OMAP_DSP_DEVSTATE_KILLING      0x00040000
+#define OMAP_DSP_DEVSTATE_STATE_MASK   0x7fffffff
+#define OMAP_DSP_DEVSTATE_STALE                0x80000000
+
+struct omap_dsp_taddinfo {
+       unsigned char minor;
+       unsigned long taskadr;
+};
+#define OMAP_DSP_TADD_ABORTADR 0xffffffff
+
+
+/*
+ * error cause definition (for error detection device)
+ */
+#define OMAP_DSP_ERRDT_WDT     0x00000001
+#define OMAP_DSP_ERRDT_MMU     0x00000002
+
+
+/*
+ * mailbox protocol definitions
+ */
+
+struct omap_dsp_mailbox_cmd {
+       unsigned short cmd;
+       unsigned short data;
+};
+
+struct omap_dsp_reginfo {
+       unsigned short adr;
+       unsigned short val;
+};
+
+struct omap_dsp_varinfo {
+       unsigned char varid;
+       unsigned short val[0];
+};
+
+#define OMAP_DSP_MBPROT_REVISION       0x0019
+
+#define OMAP_DSP_MBCMD_WDSND   0x10
+#define OMAP_DSP_MBCMD_WDREQ   0x11
+#define OMAP_DSP_MBCMD_BKSND   0x20
+#define OMAP_DSP_MBCMD_BKREQ   0x21
+#define OMAP_DSP_MBCMD_BKYLD   0x23
+#define OMAP_DSP_MBCMD_BKSNDP  0x24
+#define OMAP_DSP_MBCMD_BKREQP  0x25
+#define OMAP_DSP_MBCMD_TCTL    0x30
+#define OMAP_DSP_MBCMD_TCTLDATA        0x31
+#define OMAP_DSP_MBCMD_POLL    0x32
+#define OMAP_DSP_MBCMD_WDT     0x50    /* v3.3: obsolete */
+#define OMAP_DSP_MBCMD_RUNLEVEL        0x51
+#define OMAP_DSP_MBCMD_PM      0x52
+#define OMAP_DSP_MBCMD_SUSPEND 0x53
+#define OMAP_DSP_MBCMD_KFUNC   0x54
+#define OMAP_DSP_MBCMD_TCFG    0x60
+#define OMAP_DSP_MBCMD_TADD    0x62
+#define OMAP_DSP_MBCMD_TDEL    0x63
+#define OMAP_DSP_MBCMD_TSTOP   0x65
+#define OMAP_DSP_MBCMD_DSPCFG  0x70
+#define OMAP_DSP_MBCMD_REGRW   0x72
+#define OMAP_DSP_MBCMD_GETVAR  0x74
+#define OMAP_DSP_MBCMD_SETVAR  0x75
+#define OMAP_DSP_MBCMD_ERR     0x78
+#define OMAP_DSP_MBCMD_DBG     0x79
+
+#define OMAP_DSP_MBCMD_TCTL_TINIT      0x0000
+#define OMAP_DSP_MBCMD_TCTL_TEN                0x0001
+#define OMAP_DSP_MBCMD_TCTL_TDIS       0x0002
+#define OMAP_DSP_MBCMD_TCTL_TCLR       0x0003
+#define OMAP_DSP_MBCMD_TCTL_TCLR_FORCE 0x0004
+
+#define OMAP_DSP_MBCMD_RUNLEVEL_USER           0x01
+#define OMAP_DSP_MBCMD_RUNLEVEL_SUPER          0x0e
+#define OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY       0x10
+
+#define OMAP_DSP_MBCMD_PM_DISABLE      0x00
+#define OMAP_DSP_MBCMD_PM_ENABLE       0x01
+
+#define OMAP_DSP_MBCMD_KFUNC_FBCTL     0x00
+
+#define OMAP_DSP_MBCMD_FBCTL_ENABLE    0x0002
+#define OMAP_DSP_MBCMD_FBCTL_DISABLE   0x0003
+
+#define OMAP_DSP_MBCMD_TDEL_SAFE       0x0000
+#define OMAP_DSP_MBCMD_TDEL_KILL       0x0001
+
+#define OMAP_DSP_MBCMD_DSPCFG_REQ      0x00
+#define OMAP_DSP_MBCMD_DSPCFG_SYSADRH  0x28
+#define OMAP_DSP_MBCMD_DSPCFG_SYSADRL  0x29
+#define OMAP_DSP_MBCMD_DSPCFG_PROTREV  0x70
+#define OMAP_DSP_MBCMD_DSPCFG_ABORT    0x78
+#define OMAP_DSP_MBCMD_DSPCFG_LAST     0x80
+
+#define OMAP_DSP_MBCMD_REGRW_MEMR      0x00
+#define OMAP_DSP_MBCMD_REGRW_MEMW      0x01
+#define OMAP_DSP_MBCMD_REGRW_IOR       0x02
+#define OMAP_DSP_MBCMD_REGRW_IOW       0x03
+#define OMAP_DSP_MBCMD_REGRW_DATA      0x04
+
+#define OMAP_DSP_MBCMD_VARID_ICRMASK   0x00
+#define OMAP_DSP_MBCMD_VARID_LOADINFO  0x01
+
+#define OMAP_DSP_TTYP_ARCV     0x0001
+#define OMAP_DSP_TTYP_ASND     0x0002
+#define OMAP_DSP_TTYP_BKMD     0x0004
+#define OMAP_DSP_TTYP_BKDM     0x0008
+#define OMAP_DSP_TTYP_PVMD     0x0010
+#define OMAP_DSP_TTYP_PVDM     0x0020
+
+#define OMAP_DSP_EID_BADTID    0x10
+#define OMAP_DSP_EID_BADTCN    0x11
+#define OMAP_DSP_EID_BADBID    0x20
+#define OMAP_DSP_EID_BADCNT    0x21
+#define OMAP_DSP_EID_NOTLOCKED 0x22
+#define OMAP_DSP_EID_STVBUF    0x23
+#define OMAP_DSP_EID_BADADR    0x24
+#define OMAP_DSP_EID_BADTCTL   0x30
+#define OMAP_DSP_EID_BADPARAM  0x50
+#define OMAP_DSP_EID_FATAL     0x58
+#define OMAP_DSP_EID_NOMEM     0xc0
+#define OMAP_DSP_EID_NORES     0xc1
+#define OMAP_DSP_EID_IPBFULL   0xc2
+#define OMAP_DSP_EID_WDT       0xd0
+#define OMAP_DSP_EID_TASKNOTRDY        0xe0
+#define OMAP_DSP_EID_TASKBSY   0xe1
+#define OMAP_DSP_EID_TASKERR   0xef
+#define OMAP_DSP_EID_BADCFGTYP 0xf0
+#define OMAP_DSP_EID_DEBUG     0xf8
+#define OMAP_DSP_EID_BADSEQ    0xfe
+#define OMAP_DSP_EID_BADCMD    0xff
+
+#define OMAP_DSP_TNM_LEN       16
+
+#define OMAP_DSP_TID_FREE      0xff
+#define OMAP_DSP_TID_ANON      0xfe
+
+#define OMAP_DSP_BID_NULL      0xffff
+#define OMAP_DSP_BID_PVT       0xfffe
+
+#endif /* ASM_ARCH_DSP_H */
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
new file mode 100644 (file)
index 0000000..4fcce69
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-omap/dsp_common.h
+ *
+ * Header for OMAP DSP subsystem control
+ *
+ * Copyright (C) 2004,2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2005/06/03:  DSP Gateway version 3.3
+ */
+
+#ifndef ASM_ARCH_DSP_COMMON_H
+#define ASM_ARCH_DSP_COMMON_H
+
+void omap_dsp_pm_suspend(void);
+void omap_dsp_pm_resume(void);
+void omap_dsp_request_mpui(void);
+void omap_dsp_release_mpui(void);
+int omap_dsp_request_mem(void);
+int omap_dsp_release_mem(void);
+
+#endif /* ASM_ARCH_DSP_COMMON_H */
index 57b126889b989c3d3619222438d65919a9719209..0d29b9c56a957c9c83e76e1f5730fcbea5957da0 100644 (file)
@@ -8,6 +8,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#if defined(CONFIG_ARCH_OMAP1)
+
                .macro  disable_fiq
                .endm
 
 1510:
                .endm
 
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#include <asm/arch/omap24xx.h>
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               ldr     \base, =VA_IC_BASE
+               ldr     \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
+               cmp     \irqnr, #0x0
+               bne     2222f
+               ldr     \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */
+               cmp     \irqnr, #0x0
+               bne     2222f
+               ldr     \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
+               cmp     \irqnr, #0x0
+2222:
+               ldrne   \irqnr, [\base, #IRQ_SIR_IRQ]
+
+               .endm
+
+               .macro  irq_prio_table
+               .endm
+
+#endif
index fad2fc93ee7051c098ac88d00b89406da367d752..74cb2b93b70024f39bf135781e0afde230153af5 100644 (file)
@@ -3,7 +3,7 @@
  *
  * OMAP GPIO handling defines and functions
  *
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003-2005 Nokia Corporation
  *
  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  *
 #include <asm/arch/irqs.h>
 #include <asm/io.h>
 
-#define OMAP_MPUIO_BASE                        0xfffb5000
+#define OMAP_MPUIO_BASE                        (void __iomem *)0xfffb5000
+
+#ifdef CONFIG_ARCH_OMAP730
+#define OMAP_MPUIO_INPUT_LATCH         0x00
+#define OMAP_MPUIO_OUTPUT              0x02
+#define OMAP_MPUIO_IO_CNTL             0x04
+#define OMAP_MPUIO_KBR_LATCH           0x08
+#define OMAP_MPUIO_KBC                 0x0a
+#define OMAP_MPUIO_GPIO_EVENT_MODE     0x0c
+#define OMAP_MPUIO_GPIO_INT_EDGE       0x0e
+#define OMAP_MPUIO_KBD_INT             0x10
+#define OMAP_MPUIO_GPIO_INT            0x12
+#define OMAP_MPUIO_KBD_MASKIT          0x14
+#define OMAP_MPUIO_GPIO_MASKIT         0x16
+#define OMAP_MPUIO_GPIO_DEBOUNCING     0x18
+#define OMAP_MPUIO_LATCH               0x1a
+#else
 #define OMAP_MPUIO_INPUT_LATCH         0x00
 #define OMAP_MPUIO_OUTPUT              0x04
 #define OMAP_MPUIO_IO_CNTL             0x08
@@ -44,6 +60,7 @@
 #define OMAP_MPUIO_GPIO_MASKIT         0x2c
 #define OMAP_MPUIO_GPIO_DEBOUNCING     0x30
 #define OMAP_MPUIO_LATCH               0x34
+#endif
 
 #define OMAP_MPUIO(nr)         (OMAP_MAX_GPIO_LINES + (nr))
 #define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES)
                                 IH_MPUIO_BASE + ((nr) & 0x0f) : \
                                 IH_GPIO_BASE + ((nr) & 0x3f))
 
-/* For EDGECTRL */
-#define OMAP_GPIO_NO_EDGE        0x00
-#define OMAP_GPIO_FALLING_EDGE   0x01
-#define OMAP_GPIO_RISING_EDGE    0x02
-#define OMAP_GPIO_BOTH_EDGES     0x03
-
 extern int omap_gpio_init(void);       /* Call from board init only */
 extern int omap_request_gpio(int gpio);
 extern void omap_free_gpio(int gpio);
 extern void omap_set_gpio_direction(int gpio, int is_input);
 extern void omap_set_gpio_dataout(int gpio, int enable);
 extern int omap_get_gpio_datain(int gpio);
-extern void omap_set_gpio_edge_ctrl(int gpio, int edge);
 
 #endif
index 48258c7f6541ca0c890b0df2e68b2739c6704bc2..60201e1dd6ad72b2eb05e3e81f1ae014fc10fc9b 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/arch/cpu.h>
 #endif
 #include <asm/arch/io.h>
+#include <asm/arch/serial.h>
 
 /*
  * ---------------------------------------------------------------------------
 /* DPLL control registers */
 #define DPLL_CTL               (0xfffecf00)
 
-/* DSP clock control */
+/* DSP clock control. Must use __raw_readw() and __raw_writew() with these */
 #define DSP_CONFIG_REG_BASE     (0xe1008000)
 #define DSP_CKCTL              (DSP_CONFIG_REG_BASE + 0x0)
 #define DSP_IDLECT1            (DSP_CONFIG_REG_BASE + 0x4)
 #define DSP_IDLECT2            (DSP_CONFIG_REG_BASE + 0x8)
+#define DSP_RSTCT2             (DSP_CONFIG_REG_BASE + 0x14)
 
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
  * ---------------------------------------------------------------------------
  */
+#ifdef CONFIG_ARCH_OMAP1
+
+/*
+ * XXX: These probably want to be moved to arch/arm/mach-omap/omap1/irq.c
+ * or something similar.. -- PFM.
+ */
+
 #define OMAP_IH1_BASE          0xfffecb00
 #define OMAP_IH2_BASE          0xfffe0000
 
 #define IRQ_ILR0_REG_OFFSET    0x1c
 #define IRQ_GMR_REG_OFFSET     0xa0
 
+#endif
+
 /*
  * ----------------------------------------------------------------------------
  * System control registers
 
 #ifndef __ASSEMBLER__
 
-/*
- * ---------------------------------------------------------------------------
- * Serial ports
- * ---------------------------------------------------------------------------
- */
-#define OMAP_UART1_BASE                (unsigned char *)0xfffb0000
-#define OMAP_UART2_BASE                (unsigned char *)0xfffb0800
-#define OMAP_UART3_BASE                (unsigned char *)0xfffb9800
-#define OMAP_MAX_NR_PORTS      3
-#define OMAP1510_BASE_BAUD     (12000000/16)
-#define OMAP16XX_BASE_BAUD     (48000000/16)
-
-#define is_omap_port(p)        ({int __ret = 0;                        \
-                       if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
-                           p == IO_ADDRESS(OMAP_UART2_BASE) || \
-                           p == IO_ADDRESS(OMAP_UART3_BASE))   \
-                               __ret = 1;                      \
-                       __ret;                                  \
-                       })
-
 /*
  * ---------------------------------------------------------------------------
  * Processor specific defines
 
 #include "omap730.h"
 #include "omap1510.h"
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#include "omap24xx.h"
+#endif
+
 #include "omap16xx.h"
 
 /*
 
 #ifdef CONFIG_MACH_OMAP_H4
 #include "board-h4.h"
-#error "Support for H4 board not yet implemented."
 #endif
 
 #ifdef CONFIG_MACH_OMAP_OSK
index 1c8c9fcc766e5254c989c33e8999465e198b6f1b..11fbf629bf755410a10efee0b52f1711b584b931 100644 (file)
  * I/O mapping
  * ----------------------------------------------------------------------------
  */
-#define IO_PHYS                        0xFFFB0000
-#define IO_OFFSET              0x01000000      /* Virtual IO = 0xfefb0000 */
-#define IO_VIRT                        (IO_PHYS - IO_OFFSET)
-#define IO_SIZE                        0x40000
-#define IO_ADDRESS(x)          ((x) - IO_OFFSET)
 
-#define PCIO_BASE              0
+#if defined(CONFIG_ARCH_OMAP1)
+#define IO_PHYS                0xFFFB0000
+#define IO_OFFSET      -0x01000000     /* Virtual IO = 0xfefb0000 */
+#define IO_SIZE                0x40000
 
-#define io_p2v(x)               ((x) - IO_OFFSET)
-#define io_v2p(x)               ((x) + IO_OFFSET)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define IO_PHYS                0x48000000      /* L4 peripherals; other stuff has to be mapped *
+                                        * manually. */
+#define IO_OFFSET      0x90000000      /* Virtual IO = 0xd8000000 */
+#define IO_SIZE                0x08000000
+#endif
+
+#define IO_VIRT                (IO_PHYS + IO_OFFSET)
+#define IO_ADDRESS(x)  ((x) + IO_OFFSET)
+#define PCIO_BASE      0
+#define io_p2v(x)      ((x) + IO_OFFSET)
+#define io_v2p(x)      ((x) - IO_OFFSET)
 
 #ifndef __ASSEMBLER__
 
@@ -96,6 +104,8 @@ typedef struct { volatile u32 offset[4096]; } __regbase32;
                                        ->offset[((vaddr)&4095)>>2]
 #define __REG32(paddr)         __REGV32(io_p2v(paddr))
 
+extern void omap_map_common_io(void);
+
 #else
 
 #define __REG8(paddr)          io_p2v(paddr)
index 0d05a7c957d155799e1acaf61a4dab8cf7184f42..74e108ccac168fc34444731e59611d82eca6403f 100644 (file)
 /*
  * OMAP-1510 specific IRQ numbers for interrupt handler 2
  */
-#define INT_1510_OS_32kHz_TIMER (22 + IH2_BASE)
 #define INT_1510_COM_SPI_RO    (31 + IH2_BASE)
 
 /*
 #define INT_730_DMA_CH15       (62 + IH2_BASE)
 #define INT_730_NAND           (63 + IH2_BASE)
 
+#define INT_24XX_GPIO_BANK1    29
+#define INT_24XX_GPIO_BANK2    30
+#define INT_24XX_GPIO_BANK3    31
+#define INT_24XX_GPIO_BANK4    32
+
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
 #define OMAP_MAX_GPIO_LINES    192
index f6b57dd846a318a2099981cd402fd478aacca6f9..84f81e315a25da0aa010154473dfbc272e1cfd8c 100644 (file)
 /*
  * Physical DRAM offset.
  */
+#if defined(CONFIG_ARCH_OMAP1)
 #define PHYS_OFFSET            (0x10000000UL)
-
-/*
- * OMAP-1510 Local Bus address offset
- */
-#define OMAP1510_LB_OFFSET     (0x30000000UL)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define PHYS_OFFSET            (0x80000000UL)
+#endif
 
 /*
  * Conversion between SDRAM and fake PCI bus, used by USB
  */
 #ifdef CONFIG_ARCH_OMAP1510
 
+/*
+ * OMAP-1510 Local Bus address offset
+ */
+#define OMAP1510_LB_OFFSET     (0x30000000UL)
+
 #define virt_to_lbus(x)                ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)                ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
 #define is_lbus_device(dev)    (cpu_is_omap1510() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
diff --git a/include/asm-arm/arch-omap/mtd-xip.h b/include/asm-arm/arch-omap/mtd-xip.h
new file mode 100644 (file)
index 0000000..a73a285
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * MTD primitives for XIP support. Architecture specific functions.
+ *
+ * Do not include this file directly. It's included from linux/mtd/xip.h
+ *
+ * Author: Vladimir Barinov <vbarinov@ru.mvista.com>
+ *
+ * (c) 2005 MontaVista Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2.  This program is
+ * licensed "as is" without any warranty of any kind, whether express or
+ * implied.
+ */
+
+#ifndef __ARCH_OMAP_MTD_XIP_H__
+#define __ARCH_OMAP_MTD_XIP_H__
+
+#include <asm/hardware.h>
+#define OMAP_MPU_TIMER_BASE    (0xfffec500)
+#define OMAP_MPU_TIMER_OFFSET  0x100
+
+typedef struct {
+       u32 cntl;                       /* CNTL_TIMER, R/W */
+       u32 load_tim;                   /* LOAD_TIM,   W */
+       u32 read_tim;                   /* READ_TIM,   R */
+} xip_omap_mpu_timer_regs_t;
+
+#define xip_omap_mpu_timer_base(n)                                     \
+((volatile xip_omap_mpu_timer_regs_t*)IO_ADDRESS(OMAP_MPU_TIMER_BASE + \
+       (n)*OMAP_MPU_TIMER_OFFSET))
+
+static inline unsigned long xip_omap_mpu_timer_read(int nr)
+{
+       volatile xip_omap_mpu_timer_regs_t* timer = xip_omap_mpu_timer_base(nr);
+       return timer->read_tim;
+}
+
+#define xip_irqpending()       \
+       (omap_readl(OMAP_IH1_ITR) & ~omap_readl(OMAP_IH1_MIR))
+#define xip_currtime()         (~xip_omap_mpu_timer_read(0))
+
+/*
+ * It's permitted to do approxmation for xip_elapsed_since macro
+ * (see linux/mtd/xip.h)
+ */
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+#define xip_elapsed_since(x)   (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 7)
+#else
+#define xip_elapsed_since(x)   (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 6)
+#endif
+
+/*
+ * xip_cpu_idle() is used when waiting for a delay equal or larger than
+ * the system timer tick period.  This should put the CPU into idle mode
+ * to save power and to be woken up only when some interrupts are pending.
+ * As above, this should not rely upon standard kernel code.
+ */
+
+#define xip_cpu_idle()  asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (1))
+
+#endif /* __ARCH_OMAP_MTD_XIP_H__ */
index 5bd3f0097fc6313e7f8a98623b5a26f2f8e35c62..1b1ad410534908a013515b737a7065c66d51b3bc 100644 (file)
@@ -185,6 +185,7 @@ typedef enum {
 
        /* MPUIO */
        MPUIO2,
+       N15_1610_MPUIO2,
        MPUIO4,
        MPUIO5,
        T20_1610_MPUIO5,
@@ -210,6 +211,7 @@ typedef enum {
 
        /* Misc ballouts */
        BALLOUT_V8_ARMIO3,
+       N20_HDQ,
 
        /* OMAP-1610 MMC2 */
        W8_1610_MMC2_DAT0,
@@ -235,6 +237,7 @@ typedef enum {
        P20_1610_GPIO4,
        V9_1610_GPIO7,
        W8_1610_GPIO9,
+       N20_1610_GPIO11,
        N19_1610_GPIO13,
        P10_1610_GPIO22,
        V5_1610_GPIO24,
@@ -250,7 +253,7 @@ typedef enum {
        U18_1610_UWIRE_SDI,
        W21_1610_UWIRE_SDO,
        N14_1610_UWIRE_CS0,
-       P15_1610_UWIRE_CS0,
+       P15_1610_UWIRE_CS3,
        N15_1610_UWIRE_CS1,
 
        /* OMAP-1610 Flash */
@@ -411,7 +414,8 @@ MUX_CFG("N21_1710_GPIO14",       6,    9,    0,   1,   1,   1,    1,     1,  1)
 MUX_CFG("W15_1710_GPIO40",       9,   27,    7,   2,   5,   1,    2,     1,  1)
 
 /* MPUIO */
-MUX_CFG("MPUIO2",               7,   18,    0,   1,   1,   1,   NA,     0,  1)
+MUX_CFG("MPUIO2",               7,   18,    0,   1,  14,   1,   NA,     0,  1)
+MUX_CFG("N15_1610_MPUIO2",      7,   18,    0,   1,  14,   1,    1,     0,  1)
 MUX_CFG("MPUIO4",               7,   15,    0,   1,  13,   1,   NA,     0,  1)
 MUX_CFG("MPUIO5",               7,   12,    0,   1,  12,   1,   NA,     0,  1)
 
@@ -438,6 +442,7 @@ MUX_CFG("MCBSP3_CLKX",               9,    3,    1,   1,  29,   0,   NA,     0,  1)
 
 /* Misc ballouts */
 MUX_CFG("BALLOUT_V8_ARMIO3",    B,   18,    0,   2,  25,   1,   NA,     0,  1)
+MUX_CFG("N20_HDQ",            6,   18,    1,   1,   4,   0,    1,     4,  0)
 
 /* OMAP-1610 MMC2 */
 MUX_CFG("W8_1610_MMC2_DAT0",    B,   21,    6,   2,  23,   1,    2,     1,  1)
@@ -463,6 +468,7 @@ MUX_CFG("J18_1610_ETM_D7",   5,   27,    1,   0,  19,   0,    0,     0,  1)
 MUX_CFG("P20_1610_GPIO4",       6,   27,    0,   1,   7,   0,    1,     1,  1)
 MUX_CFG("V9_1610_GPIO7",        B,   12,    1,   2,  20,   0,    2,     1,  1)
 MUX_CFG("W8_1610_GPIO9",        B,   21,    0,   2,  23,   0,    2,     1,  1)
+MUX_CFG("N20_1610_GPIO11",       6,   18,    0,   1,   4,   0,    1,     1,  1)
 MUX_CFG("N19_1610_GPIO13",      6,   12,    0,   1,   2,   0,    1,     1,  1)
 MUX_CFG("P10_1610_GPIO22",      C,    0,    7,   2,  26,   0,    2,     1,  1)
 MUX_CFG("V5_1610_GPIO24",       B,   15,    7,   2,  21,   0,    2,     1,  1)
index f491a48ef2e118904d1c36c3b9b24a96445ef360..f086a39339060c1012036f0e68cbaf0120ad0fb9 100644 (file)
 
 /* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
 
-#define OMAP1510_SRAM_BASE     0xD0000000
-#define OMAP1510_SRAM_SIZE     (SZ_128K + SZ_64K)
-#define OMAP1510_SRAM_START    0x20000000
-
 #define OMAP1510_DSP_BASE      0xE0000000
 #define OMAP1510_DSP_SIZE      0x28000
 #define OMAP1510_DSP_START     0xE0000000
 #define OMAP1510_DSPREG_SIZE   SZ_128K
 #define OMAP1510_DSPREG_START  0xE1000000
 
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1510_SRAM_IDLE_SUSPEND     (OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
-#define OMAP1510_SRAM_API_SUSPEND      (OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
-
 #endif /*  __ASM_ARCH_OMAP1510_H */
 
index 38a9b95e6a336c7e12a3ebef89c629b37a22b6d9..f0c7f0fb4dc032e2a8c2303714b49504c3b7235b 100644 (file)
 
 /* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
 
-#define OMAP16XX_SRAM_BASE     0xD0000000
-#define OMAP1610_SRAM_SIZE     (SZ_16K)
-#define OMAP5912_SRAM_SIZE     0x3E800
-#define OMAP16XX_SRAM_START    0x20000000
-
 #define OMAP16XX_DSP_BASE      0xE0000000
 #define OMAP16XX_DSP_SIZE      0x28000
 #define OMAP16XX_DSP_START     0xE0000000
 #define OMAP16XX_DSPREG_SIZE   SZ_128K
 #define OMAP16XX_DSPREG_START  0xE1000000
 
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1610_SRAM_IDLE_SUSPEND     (OMAP16XX_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
-#define OMAP1610_SRAM_API_SUSPEND      (OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
-#define OMAP5912_SRAM_IDLE_SUSPEND     (OMAP16XX_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
-#define OMAP5912_SRAM_API_SUSPEND      (OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
-
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
new file mode 100644 (file)
index 0000000..a910546
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASM_ARCH_OMAP24XX_H
+#define __ASM_ARCH_OMAP24XX_H
+
+#define OMAP24XX_L4_IO_BASE    0x48000000
+
+/* interrupt controller */
+#define OMAP24XX_IC_BASE       (OMAP24XX_L4_IO_BASE + 0xfe000)
+#define VA_IC_BASE             IO_ADDRESS(OMAP24XX_IC_BASE)
+
+#define OMAP24XX_IVA_INTC_BASE 0x40000000
+
+#define IRQ_SIR_IRQ            0x0040
+
+#endif /* __ASM_ARCH_OMAP24XX_H */
+
index 599ab00f5488a5b0ebb14e352683cc473344703a..755b64c5e9f07342fdacf476c407226dbe66eab8 100644 (file)
 
 /* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
 
-#define OMAP730_SRAM_BASE      0xD0000000
-#define OMAP730_SRAM_SIZE      (SZ_128K + SZ_64K + SZ_8K)
-#define OMAP730_SRAM_START     0x20000000
-
 #define OMAP730_DSP_BASE       0xE0000000
 #define OMAP730_DSP_SIZE       0x50000
 #define OMAP730_DSP_START      0xE0000000
index f209fc0953fb86559f39ffb48734ba93be13bf5d..fbd742d0c49997fc46e5ddc1299dd9d399242389 100644 (file)
 #define PER_EN                         0x1
 
 #define CPU_SUSPEND_SIZE               200
-#define ULPD_LOW_POWER_EN              0x0001
+#define ULPD_LOW_PWR_EN                        0x0001
+#define ULPD_DEEP_SLEEP_TRANSITION_EN  0x0010
+#define ULPD_SETUP_ANALOG_CELL_3_VAL   0
+#define ULPD_POWER_CTRL_REG_VAL                0x0219
 
 #define DSP_IDLE_DELAY                 10
 #define DSP_IDLE                       0x0040
 #define OMAP1510_BIG_SLEEP_REQUEST     0x0cc5
 #define OMAP1510_IDLE_LOOP_REQUEST     0x0c00
 #define OMAP1510_IDLE_CLOCK_DOMAINS    0x2
-#define OMAP1510_ULPD_LOW_POWER_REQ    0x0001
 
-#define OMAP1610_DEEP_SLEEP_REQUEST    0x17c7
-#define OMAP1610_BIG_SLEEP_REQUEST     TBD
+/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
+#define OMAP1610_IDLECT1_SLEEP_VAL     0x13c7
+#define OMAP1610_IDLECT2_SLEEP_VAL     0x09c7
+#define OMAP1610_IDLECT3_VAL           0x3f
+#define OMAP1610_IDLECT3_SLEEP_ORMASK  0x2c
+#define OMAP1610_IDLECT3               0xfffece24
 #define OMAP1610_IDLE_LOOP_REQUEST     0x0400
-#define OMAP1610_IDLE_CLOCK_DOMAINS    0x09c7
-#define OMAP1610_ULPD_LOW_POWER_REQ    0x3
-
-#ifndef OMAP1510_SRAM_IDLE_SUSPEND
-#define OMAP1510_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_IDLE_SUSPEND
-#define OMAP1610_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_IDLE_SUSPEND
-#define OMAP5912_SRAM_IDLE_SUSPEND 0
-#endif
-
-#ifndef OMAP1510_SRAM_API_SUSPEND
-#define OMAP1510_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_API_SUSPEND
-#define OMAP1610_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_API_SUSPEND
-#define OMAP5912_SRAM_API_SUSPEND 0
-#endif
 
 #if     !defined(CONFIG_ARCH_OMAP1510) && \
-       !defined(CONFIG_ARCH_OMAP16XX)
+       !defined(CONFIG_ARCH_OMAP16XX) && \
+       !defined(CONFIG_ARCH_OMAP24XX)
 #error "Power management for this processor not implemented yet"
 #endif
 
 #ifndef __ASSEMBLER__
 extern void omap_pm_idle(void);
 extern void omap_pm_suspend(void);
-extern int omap1510_cpu_suspend(unsigned short, unsigned short);
-extern int omap1610_cpu_suspend(unsigned short, unsigned short);
-extern int omap1510_idle_loop_suspend(void);
-extern int omap1610_idle_loop_suspend(void);
+extern void omap1510_cpu_suspend(unsigned short, unsigned short);
+extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap1510_idle_loop_suspend(void);
+extern void omap1610_idle_loop_suspend(void);
+
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+extern void omap_serial_wake_trigger(int enable);
+#else
+#define omap_serial_wake_trigger(x)    {}
+#endif /* CONFIG_OMAP_SERIAL_WAKE */
+
 extern unsigned int omap1510_cpu_suspend_sz;
 extern unsigned int omap1510_idle_loop_suspend_sz;
 extern unsigned int omap1610_cpu_suspend_sz;
@@ -161,6 +153,7 @@ enum arm_save_state {
        ARM_SLEEP_SAVE_ARM_CKCTL,
        ARM_SLEEP_SAVE_ARM_IDLECT1,
        ARM_SLEEP_SAVE_ARM_IDLECT2,
+       ARM_SLEEP_SAVE_ARM_IDLECT3,
        ARM_SLEEP_SAVE_ARM_EWUPCT,
        ARM_SLEEP_SAVE_ARM_RSTCT1,
        ARM_SLEEP_SAVE_ARM_RSTCT2,
diff --git a/include/asm-arm/arch-omap/serial.h b/include/asm-arm/arch-omap/serial.h
new file mode 100644 (file)
index 0000000..79a5297
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  linux/include/asm-arm/arch-omap/serial.h
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#if defined(CONFIG_ARCH_OMAP1)
+/* OMAP1 serial ports */
+#define OMAP_UART1_BASE                0xfffb0000
+#define OMAP_UART2_BASE                0xfffb0800
+#define OMAP_UART3_BASE                0xfffb9800
+#elif defined(CONFIG_ARCH_OMAP2)
+/* OMAP2 serial ports */
+#define OMAP_UART1_BASE                0x4806a000
+#define OMAP_UART2_BASE                0x4806c000
+#define OMAP_UART3_BASE                0x4806e000
+#endif
+
+#define OMAP_MAX_NR_PORTS      3
+#define OMAP1510_BASE_BAUD     (12000000/16)
+#define OMAP16XX_BASE_BAUD     (48000000/16)
+
+#define is_omap_port(p)        ({int __ret = 0;                        \
+                       if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
+                           p == IO_ADDRESS(OMAP_UART2_BASE) || \
+                           p == IO_ADDRESS(OMAP_UART3_BASE))   \
+                               __ret = 1;                      \
+                       __ret;                                  \
+                       })
+
+#endif
index 3e640aba8c20f576410fb22b1ca72a365df431a6..3545c86859cc9a9700b02760a35fb1ba9a811ba8 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial_reg.h>
-#include <asm/arch/hardware.h>
+#include <asm/arch/serial.h>
 
 unsigned int system_rev;
 
@@ -34,8 +34,9 @@ static void
 putstr(const char *s)
 {
        volatile u8 * uart = 0;
-       int shift;
+       int shift = 2;
 
+#ifdef CONFIG_ARCH_OMAP
 #ifdef CONFIG_OMAP_LL_DEBUG_UART3
        uart = (volatile u8 *)(OMAP_UART3_BASE);
 #elif  CONFIG_OMAP_LL_DEBUG_UART2
@@ -44,6 +45,7 @@ putstr(const char *s)
        uart = (volatile u8 *)(OMAP_UART1_BASE);
 #endif
 
+#ifdef CONFIG_ARCH_OMAP1
        /* Determine which serial port to use */
        do {
                /* MMU is not on, so cpu_is_omapXXXX() won't work here */
@@ -51,14 +53,14 @@ putstr(const char *s)
 
                if (omap_id == OMAP_ID_730)
                        shift = 0;
-               else
-                       shift = 2;
 
                if (check_port(uart, shift))
                        break;
                /* Silent boot if no serial ports are enabled. */
                return;
        } while (0);
+#endif /* CONFIG_ARCH_OMAP1 */
+#endif
 
        /*
         * Now, xmit each character
index 324db06b5dd4b219f83316dd8a6d4aff1906e6d1..4b7aa0b8391e0741aab1fcee845ff1cc919421e1 100644 (file)
  * Shared data structures
  */
 extern struct platform_device corgiscoop_device;
+extern struct platform_device corgissp_device;
+extern struct platform_device corgifb_device;
 
 /*
  * External Functions
  */
 extern unsigned long corgi_ssp_ads7846_putget(unsigned long);
 extern unsigned long corgi_ssp_ads7846_get(void);
-extern void corgi_ssp_ads7846_put(ulong data);
+extern void corgi_ssp_ads7846_put(unsigned long data);
 extern void corgi_ssp_ads7846_lock(void);
 extern void corgi_ssp_ads7846_unlock(void);
-extern void corgi_ssp_lcdtg_send (u8 adrs, u8 data);
+extern void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
 extern void corgi_ssp_blduty_set(int duty);
-extern int corgi_ssp_max1111_get(ulong data);
+extern int corgi_ssp_max1111_get(unsigned long data);
 
 #endif /* __ASM_ARCH_CORGI_H  */
 
index 7492ea7ea6141158f7bf24903541881dfa79db86..9718063a211959472bce3f7990cbdd5e8257948b 100644 (file)
@@ -10,6 +10,7 @@ struct mmc_host;
 struct pxamci_platform_data {
        unsigned int ocr_mask;                  /* available voltages */
        int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
+       int (*get_ro)(struct device *);
        void (*setpower)(struct device *, unsigned int);
        void (*exit)(struct device *, void *);
 };
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
new file mode 100644 (file)
index 0000000..5675b17
--- /dev/null
@@ -0,0 +1,24 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-cpld.h
+ *
+ * (c) 2005 Simtec Electronics
+ *     http://www.simtec.co.uk/products/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * ANUBIS - CPLD control constants
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+ *
+*/
+
+#ifndef __ASM_ARCH_ANUBISCPLD_H
+#define __ASM_ARCH_ANUBISCPLD_H
+
+/* CTRL2 - NAND WP control, IDE Reset assert/check */
+
+#define ANUBIS_CTRL1_NANDSEL           (0x3)
+
+#endif /* __ASM_ARCH_ANUBISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-irq.h b/include/asm-arm/arch-s3c2410/anubis-irq.h
new file mode 100644 (file)
index 0000000..82f15db
--- /dev/null
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-irq.h
+ *
+ * (c) 2005 Simtec Electronics
+ *     http://www.simtec.co.uk/products/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ *  ANUBIS - IRQ Number definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+ */
+
+#ifndef __ASM_ARCH_ANUBISIRQ_H
+#define __ASM_ARCH_ANUBISIRQ_H
+
+#define IRQ_IDE0       IRQ_EINT2
+#define IRQ_IDE1       IRQ_EINT3
+#define IRQ_ASIX       IRQ_EINT1
+
+#endif /* __ASM_ARCH_ANUBISIRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
new file mode 100644 (file)
index 0000000..97741d6
--- /dev/null
@@ -0,0 +1,46 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-map.h
+ *
+ * (c) 2005 Simtec Electronics
+ *     http://www.simtec.co.uk/products/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * ANUBIS - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+*/
+
+/* needs arch/map.h including with this */
+
+#ifndef __ASM_ARCH_ANUBISMAP_H
+#define __ASM_ARCH_ANUBISMAP_H
+
+/* start peripherals off after the S3C2410 */
+
+#define ANUBIS_IOADDR(x)       (S3C2410_ADDR((x) + 0x02000000))
+
+#define ANUBIS_PA_CPLD         (S3C2410_CS1 | (1<<26))
+
+/* we put the CPLD registers next, to get them out of the way */
+
+#define ANUBIS_VA_CTRL1            ANUBIS_IOADDR(0x00000000)    /* 0x01300000 */
+#define ANUBIS_PA_CTRL1            (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL2            ANUBIS_IOADDR(0x00100000)    /* 0x01400000 */
+#define ANUBIS_PA_CTRL2            (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL3            ANUBIS_IOADDR(0x00200000)    /* 0x01500000 */
+#define ANUBIS_PA_CTRL3            (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL4            ANUBIS_IOADDR(0x00300000)    /* 0x01600000 */
+#define ANUBIS_PA_CTRL4            (ANUBIS_PA_CPLD)
+
+#define ANUBIS_IDEPRI      ANUBIS_IOADDR(0x01000000)
+#define ANUBIS_IDEPRIAUX    ANUBIS_IOADDR(0x01100000)
+#define ANUBIS_IDESEC      ANUBIS_IOADDR(0x01200000)
+#define ANUBIS_IDESECAUX    ANUBIS_IOADDR(0x01300000)
+
+#endif /* __ASM_ARCH_ANUBISMAP_H */
diff --git a/include/asm-arm/auxvec.h b/include/asm-arm/auxvec.h
new file mode 100644 (file)
index 0000000..c0536f6
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMARM_AUXVEC_H
+#define __ASMARM_AUXVEC_H
+
+#endif
index 485b6bdf4d7a1fde9812d12c6b3b43da53562aa6..a80b6607b2efe35281d476d852e106cd3d6ca31b 100644 (file)
@@ -1,87 +1,11 @@
 #ifndef _ARM_FCNTL_H
 #define _ARM_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
 #define O_DIRECTORY     040000 /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
-#define O_NOATIME      01000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
+#include <asm-generic/fcntl.h>
 
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-arm/hdreg.h b/include/asm-arm/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index a7c018b8a0d4b88f7da350709a94558dd103d3aa..a2fdad0138b3e5bf2e7e2500e97a8821fe7b036e 100644 (file)
@@ -77,12 +77,6 @@ static inline void set_fs (mm_segment_t fs)
 
 #define access_ok(type,addr,size)      (__range_ok(addr,size) == 0)
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * Single-value transfer routines.  They automatically use the right
  * size if we just have the right pointer type.  Note that the functions
diff --git a/include/asm-arm26/auxvec.h b/include/asm-arm26/auxvec.h
new file mode 100644 (file)
index 0000000..c0536f6
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMARM_AUXVEC_H
+#define __ASMARM_AUXVEC_H
+
+#endif
index 485b6bdf4d7a1fde9812d12c6b3b43da53562aa6..d85995e7459e4e011bcd3215c5ebe4a970721f9b 100644 (file)
@@ -3,85 +3,11 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
 #define O_DIRECTORY     040000 /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
-#define O_NOATIME      01000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
+#include <asm-generic/fcntl.h>
 
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif
diff --git a/include/asm-arm26/futex.h b/include/asm-arm26/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-arm26/hdreg.h b/include/asm-arm26/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index ab9ce38c6aec994875f9a39ce8bfa63612b8388f..3f2dd1093e58b6a233c20f223043f7efaa8afc13 100644 (file)
@@ -40,12 +40,6 @@ extern int fixup_exception(struct pt_regs *regs);
 
 #define access_ok(type,addr,size)      (__range_ok(addr,size) == 0)
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * Single-value transfer routines.  They automatically use the right
  * size if we just have the right pointer type.  Note that the functions
diff --git a/include/asm-cris/auxvec.h b/include/asm-cris/auxvec.h
new file mode 100644 (file)
index 0000000..cb30b01
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMCRIS_AUXVEC_H
+#define __ASMCRIS_AUXVEC_H
+
+#endif
index 61c563242b519707f9203e0720d4ce92f583ac60..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,90 +1 @@
-#ifndef _CRIS_FCNTL_H
-#define _CRIS_FCNTL_H
-
-/* verbatim copy of i386 version */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get f_flags */
-#define F_SETFD                2       /* set f_flags */
-#define F_GETFL                3       /* more flags (cloexec) */
-#define F_SETFL                4
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW        192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-cris/futex.h b/include/asm-cris/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index 8e787fdaedd41835db69807807278d953b337c34..4fab5c3b2e15ca4ee294346535d14456145c520e 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
 #include <asm/arch/irq.h>
 
 extern __inline__ int irq_canonicalize(int irq)
index 6db17221fd9e5f412002cc3c9a8d8a2a9f417f8d..7d50086eb5ea08a6de01e4f4f4f7735a2ec4eee0 100644 (file)
 #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
 #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
 #include <asm/arch/uaccess.h>
 
 /*
diff --git a/include/asm-frv/auxvec.h b/include/asm-frv/auxvec.h
new file mode 100644 (file)
index 0000000..0771077
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __FRV_AUXVEC_H
+#define __FRV_AUXVEC_H
+
+#endif
index d61b999f9973a2e4a0b4288b007ff8c1f3f64030..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,88 +1 @@
-#ifndef _ASM_FCNTL_H
-#define _ASM_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-#endif /* _ASM_FCNTL_H */
-
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index 32dc52e883e54a31344405a48702003762688953..991b50fbba24d77b64c402389f2e93e0c48bb2a8 100644 (file)
@@ -67,12 +67,6 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
 #define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
 #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
 
-/* this function will go away soon - use access_ok() / __range_ok() instead */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
-       return __range_ok(addr, size);
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
new file mode 100644 (file)
index 0000000..b663520
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef _ASM_GENERIC_FCNTL_H
+#define _ASM_GENERIC_FCNTL_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE      00000003
+#define O_RDONLY       00000000
+#define O_WRONLY       00000001
+#define O_RDWR         00000002
+#ifndef O_CREAT
+#define O_CREAT                00000100        /* not fcntl */
+#endif
+#ifndef O_EXCL
+#define O_EXCL         00000200        /* not fcntl */
+#endif
+#ifndef O_NOCTTY
+#define O_NOCTTY       00000400        /* not fcntl */
+#endif
+#ifndef O_TRUNC
+#define O_TRUNC                00001000        /* not fcntl */
+#endif
+#ifndef O_APPEND
+#define O_APPEND       00002000
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK     00004000
+#endif
+#ifndef O_SYNC
+#define O_SYNC         00010000
+#endif
+#ifndef FASYNC
+#define FASYNC         00020000        /* fcntl, for BSD compatibility */
+#endif
+#ifndef O_DIRECT
+#define O_DIRECT       00040000        /* direct disk access hint */
+#endif
+#ifndef O_LARGEFILE
+#define O_LARGEFILE    00100000
+#endif
+#ifndef O_DIRECTORY
+#define O_DIRECTORY    00200000        /* must be a directory */
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW     00400000        /* don't follow links */
+#endif
+#ifndef O_NOATIME
+#define O_NOATIME      01000000
+#endif
+#ifndef O_NDELAY
+#define O_NDELAY       O_NONBLOCK
+#endif
+
+#define F_DUPFD                0       /* dup */
+#define F_GETFD                1       /* get close_on_exec */
+#define F_SETFD                2       /* set/clear close_on_exec */
+#define F_GETFL                3       /* get file->f_flags */
+#define F_SETFL                4       /* set file->f_flags */
+#ifndef F_GETLK
+#define F_GETLK                5
+#define F_SETLK                6
+#define F_SETLKW       7
+#endif
+#ifndef F_SETOWN
+#define F_SETOWN       8       /* for sockets. */
+#define F_GETOWN       9       /* for sockets. */
+#endif
+#ifndef F_SETSIG
+#define F_SETSIG       10      /* for sockets. */
+#define F_GETSIG       11      /* for sockets. */
+#endif
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#ifndef F_RDLCK
+#define F_RDLCK                0
+#define F_WRLCK                1
+#define F_UNLCK                2
+#endif
+
+/* for old implementation of bsd flock () */
+#ifndef F_EXLCK
+#define F_EXLCK                4       /* or 3 */
+#define F_SHLCK                8       /* or 4 */
+#endif
+
+/* for leases */
+#ifndef F_INPROGRESS
+#define F_INPROGRESS   16
+#endif
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH                1       /* shared lock */
+#define LOCK_EX                2       /* exclusive lock */
+#define LOCK_NB                4       /* or'd with one of the above to prevent
+                                  blocking */
+#define LOCK_UN                8       /* remove lock */
+
+#define LOCK_MAND      32      /* This is a mandatory flock ... */
+#define LOCK_READ      64      /* which allows concurrent read operations */
+#define LOCK_WRITE     128     /* which allows concurrent write operations */
+#define LOCK_RW                192     /* which allows concurrent read & write ops */
+
+#define F_LINUX_SPECIFIC_BASE  1024
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK
+#ifndef __ARCH_FLOCK_PAD
+#define __ARCH_FLOCK_PAD
+#endif
+
+struct flock {
+       short   l_type;
+       short   l_whence;
+       off_t   l_start;
+       off_t   l_len;
+       pid_t   l_pid;
+       __ARCH_FLOCK_PAD
+};
+#endif
+
+#ifndef CONFIG_64BIT
+
+#ifndef F_GETLK64
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+#endif
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK64
+#ifndef __ARCH_FLOCK64_PAD
+#define __ARCH_FLOCK64_PAD
+#endif
+
+struct flock64 {
+       short  l_type;
+       short  l_whence;
+       loff_t l_start;
+       loff_t l_len;
+       pid_t  l_pid;
+       __ARCH_FLOCK64_PAD
+};
+#endif
+#endif /* !CONFIG_64BIT */
+
+#endif /* _ASM_GENERIC_FCNTL_H */
diff --git a/include/asm-generic/hdreg.h b/include/asm-generic/hdreg.h
deleted file mode 100644 (file)
index 7051fba..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#warning <asm/hdreg.h> is obsolete, please do not use it
-
-#ifndef __ASM_GENERIC_HDREG_H
-#define __ASM_GENERIC_HDREG_H
-
-typedef unsigned long ide_ioreg_t;
-
-#endif /* __ASM_GENERIC_HDREG_H */
index 450eae22c39a3e2a517dea059a7e3b01bb7ce6d6..886dbd11689991396238d2cc6bdf9f09374762ff 100644 (file)
@@ -12,5 +12,6 @@ extern char _sextratext[] __attribute__((weak));
 extern char _eextratext[] __attribute__((weak));
 extern char _end[];
 extern char __per_cpu_start[], __per_cpu_end[];
+extern char __kprobes_text_start[], __kprobes_text_end[];
 
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
index 6c90f0f36eec9990dc9f00f87454215c2acfe9c4..4dc8ddb401c15828797b4a7e21586e4b6d3e3418 100644 (file)
@@ -16,9 +16,9 @@
  * The main single-value unaligned transfer routines.
  */
 #define get_unaligned(ptr) \
-       ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
+       __get_unaligned((ptr), sizeof(*(ptr)))
 #define put_unaligned(x,ptr) \
-       __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+       __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
 
 /*
  * This function doesn't actually exist.  The idea is that when
@@ -36,19 +36,19 @@ struct __una_u16 { __u16 x __attribute__((packed)); };
  * Elemental unaligned loads 
  */
 
-static inline unsigned long __uldq(const __u64 *addr)
+static inline __u64 __uldq(const __u64 *addr)
 {
        const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
        return ptr->x;
 }
 
-static inline unsigned long __uldl(const __u32 *addr)
+static inline __u32 __uldl(const __u32 *addr)
 {
        const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
        return ptr->x;
 }
 
-static inline unsigned long __uldw(const __u16 *addr)
+static inline __u16 __uldw(const __u16 *addr)
 {
        const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
        return ptr->x;
@@ -78,7 +78,7 @@ static inline void __ustw(__u16 val, __u16 *addr)
 
 #define __get_unaligned(ptr, size) ({          \
        const void *__gu_p = ptr;               \
-       unsigned long val;                      \
+       __typeof__(*(ptr)) val;                 \
        switch (size) {                         \
        case 1:                                 \
                val = *(const __u8 *)__gu_p;    \
index 3fa94288aa9329473e7eda8d7f8d5893dd5c99ba..6f857be2b6447ac3f64f134ce45844ef2555b11b 100644 (file)
@@ -97,3 +97,9 @@
                VMLINUX_SYMBOL(__lock_text_start) = .;                  \
                *(.spinlock.text)                                       \
                VMLINUX_SYMBOL(__lock_text_end) = .;
+
+#define KPROBES_TEXT                                                   \
+               ALIGN_FUNCTION();                                       \
+               VMLINUX_SYMBOL(__kprobes_text_start) = .;               \
+               *(.kprobes.text)                                        \
+               VMLINUX_SYMBOL(__kprobes_text_end) = .;
diff --git a/include/asm-h8300/auxvec.h b/include/asm-h8300/auxvec.h
new file mode 100644 (file)
index 0000000..1d36fe3
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMH8300_AUXVEC_H
+#define __ASMH8300_AUXVEC_H
+
+#endif
index 355350a57bf97b6ef1d054375a2b2395c6a3b973..1952cb2e3b06e406f865cba82eb64fb790628804 100644 (file)
@@ -1,87 +1,11 @@
 #ifndef _H8300_FCNTL_H
 #define _H8300_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE        0003
-#define O_RDONLY           00
-#define O_WRONLY           01
-#define O_RDWR             02
-#define O_CREAT                  0100  /* not fcntl */
-#define O_EXCL           0200  /* not fcntl */
-#define O_NOCTTY         0400  /* not fcntl */
-#define O_TRUNC                 01000  /* not fcntl */
-#define O_APPEND        02000
-#define O_NONBLOCK      04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC         010000
-#define FASYNC         020000  /* fcntl, for BSD compatibility */
 #define O_DIRECTORY    040000  /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
-#define O_NOATIME      01000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
+#include <asm-generic/fcntl.h>
 
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif /* _H8300_FCNTL_H */
diff --git a/include/asm-h8300/futex.h b/include/asm-h8300/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-h8300/hdreg.h b/include/asm-h8300/hdreg.h
deleted file mode 100644 (file)
index 36d0c06..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- *  linux/include/asm-h8300/hdreg.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-#warning this file is obsolete, please do not use it
-
-#ifndef _H8300_HDREG_H
-#define _H8300_HDREG_H
-
-typedef unsigned int   q40ide_ioreg_t;
-typedef unsigned char * ide_ioreg_t;
-
-#endif /* _H8300_HDREG_H */
index 1480f307a4749f69e1199da2c03c1b41410084d4..ebe58c6c83878396ada351e1f142b55a159c899a 100644 (file)
@@ -24,12 +24,6 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
        return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend));
 }
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
-{
-       return access_ok(type,addr,size)?0:-EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-i386/auxvec.h b/include/asm-i386/auxvec.h
new file mode 100644 (file)
index 0000000..395e130
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASMi386_AUXVEC_H
+#define __ASMi386_AUXVEC_H
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO             32
+#define AT_SYSINFO_EHDR                33
+
+#endif
index 130bdc8c68cfd381f3ed731de5d4d9e9a4b31a2e..fa11117d3cfac32de2b2e6b3694c8d65f56b5ac5 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/user.h>
 #include <asm/processor.h>
 #include <asm/system.h>                /* for savesegment */
+#include <asm/auxvec.h>
 
 #include <linux/utsname.h>
 
@@ -109,13 +110,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
 
 #define ELF_PLATFORM  (system_utsname.machine)
 
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO             32
-#define AT_SYSINFO_EHDR                33
-
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2) do { } while (0)
 
index 511cde94a3ed0fe230cd71d8214617113130121b..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,88 +1 @@
-#ifndef _I386_FCNTL_H
-#define _I386_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
new file mode 100644 (file)
index 0000000..44b9db8
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+  __asm__ __volatile (                                         \
+"1:    " insn "\n"                                             \
+"2:    .section .fixup,\"ax\"\n\
+3:     mov     %3, %1\n\
+       jmp     2b\n\
+       .previous\n\
+       .section __ex_table,\"a\"\n\
+       .align  8\n\
+       .long   1b,3b\n\
+       .previous"                                              \
+       : "=r" (oldval), "=r" (ret), "=m" (*uaddr)              \
+       : "i" (-EFAULT), "m" (*uaddr), "0" (oparg), "1" (0))
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+  __asm__ __volatile (                                         \
+"1:    movl    %2, %0\n\
+       movl    %0, %3\n"                                       \
+       insn "\n"                                               \
+"2:    " LOCK_PREFIX "cmpxchgl %3, %2\n\
+       jnz     1b\n\
+3:     .section .fixup,\"ax\"\n\
+4:     mov     %5, %1\n\
+       jmp     3b\n\
+       .previous\n\
+       .section __ex_table,\"a\"\n\
+       .align  8\n\
+       .long   1b,4b,2b,4b\n\
+       .previous"                                              \
+       : "=&a" (oldval), "=&r" (ret), "=m" (*uaddr),           \
+         "=&r" (tem)                                           \
+       : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0))
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       if (op == FUTEX_OP_SET)
+               __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
+       else {
+#ifndef CONFIG_X86_BSWAP
+               if (boot_cpu_data.x86 == 3)
+                       ret = -ENOSYS;
+               else
+#endif
+               switch (op) {
+               case FUTEX_OP_ADD:
+                       __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
+                                          oldval, uaddr, oparg);
+                       break;
+               case FUTEX_OP_OR:
+                       __futex_atomic_op2("orl %4, %3", ret, oldval, uaddr,
+                                          oparg);
+                       break;
+               case FUTEX_OP_ANDN:
+                       __futex_atomic_op2("andl %4, %3", ret, oldval, uaddr,
+                                          ~oparg);
+                       break;
+               case FUTEX_OP_XOR:
+                       __futex_atomic_op2("xorl %4, %3", ret, oldval, uaddr,
+                                          oparg);
+                       break;
+               default:
+                       ret = -ENOSYS;
+               }
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-i386/hdreg.h b/include/asm-i386/hdreg.h
deleted file mode 100644 (file)
index 5989bbc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
index 886867aea947094185fcac17610acc67f9310caf..89ab7e2bc5aaac8a1e230fbd7772ff5340e7b3a1 100644 (file)
@@ -83,30 +83,6 @@ extern struct movsl_mask {
  */
 #define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
 
-/**
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only.  This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-ia64/auxvec.h b/include/asm-ia64/auxvec.h
new file mode 100644 (file)
index 0000000..23cebe5
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_IA64_AUXVEC_H
+#define _ASM_IA64_AUXVEC_H
+
+/*
+ * Architecture-neutral AT_ values are in the range 0-17.  Leave some room for more of
+ * them, start the architecture-specific ones at 32.
+ */
+#define AT_SYSINFO     32
+#define AT_SYSINFO_EHDR        33
+
+#endif /* _ASM_IA64_AUXVEC_H */
index 0c05e5bad8a0fe01e4ba88abcb84d1516014d414..aaf11f4e916997643d60c7d45fb4718ac5092363 100644 (file)
@@ -13,10 +13,10 @@ typedef s32         compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_key_t;
 typedef s32            compat_pid_t;
-typedef u16            compat_uid_t;
-typedef u16            compat_gid_t;
-typedef u32            compat_uid32_t;
-typedef u32            compat_gid32_t;
+typedef u16            __compat_uid_t;
+typedef u16            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u16            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u16            compat_dev_t;
@@ -50,8 +50,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid_t  st_uid;
+       __compat_gid_t  st_gid;
        compat_dev_t    st_rdev;
        u16             __pad2;
        u32             st_size;
@@ -120,10 +120,10 @@ typedef u32               compat_sigset_word;
 
 struct compat_ipc64_perm {
        compat_key_t key;
-       compat_uid32_t uid;
-       compat_gid32_t gid;
-       compat_uid32_t cuid;
-       compat_gid32_t cgid;
+       __compat_uid32_t uid;
+       __compat_gid32_t gid;
+       __compat_uid32_t cuid;
+       __compat_gid32_t cgid;
        unsigned short mode;
        unsigned short __pad1;
        unsigned short seq;
index 7d4ccc4b976e2150fb4ab909902c68cf9ea701af..446fce036fd929eedb87ffdf95917703a568a9ae 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/fpu.h>
 #include <asm/page.h>
+#include <asm/auxvec.h>
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -177,13 +178,6 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
    relevant until we have real hardware to play with... */
 #define ELF_PLATFORM   NULL
 
-/*
- * Architecture-neutral AT_ values are in the range 0-17.  Leave some room for more of
- * them, start the architecture-specific ones at 32.
- */
-#define AT_SYSINFO     32
-#define AT_SYSINFO_EHDR        33
-
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2)     set_personality(PER_LINUX)
 #define elf_read_implies_exec(ex, executable_stack)                                    \
index cee16ea1780aa6e9046bd2982ad9694b2188018d..1dd275dc8f653a0b6be00f469998bfa8711044a0 100644 (file)
@@ -1,87 +1,13 @@
 #ifndef _ASM_IA64_FCNTL_H
 #define _ASM_IA64_FCNTL_H
 /*
- * Based on <asm-i386/fcntl.h>.
- *
  * Modified 1998-2000
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
-/*
- * open/fcntl - O_SYNC is only implemented on blocks devices and on
- * files located on an ext2 file system
- */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
 #define force_o_largefile()    \
                (personality(current->personality) != PER_LINUX32)
 
+#include <asm-generic/fcntl.h>
+
 #endif /* _ASM_IA64_FCNTL_H */
diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-ia64/hdreg.h b/include/asm-ia64/hdreg.h
deleted file mode 100644 (file)
index 83b5161..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- *  linux/include/asm-ia64/hdreg.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-#warning this file is obsolete, please do not use it
-
-#ifndef __ASM_IA64_HDREG_H
-#define __ASM_IA64_HDREG_H
-
-typedef unsigned short ide_ioreg_t;
-
-#endif /* __ASM_IA64_HDREG_H */
index 041ab8c51a6409469c1e40e3652814ac666f9817..0cf119b42f7d5c4d1d25ce4eb0e55b9a849d52cb 100644 (file)
@@ -116,13 +116,6 @@ __ia64_local_vector_to_irq (ia64_vector vec)
  * and to obtain the irq descriptor for a given irq number.
  */
 
-/* Return a pointer to the irq descriptor for IRQ.  */
-static inline irq_desc_t *
-irq_descp (int irq)
-{
-       return irq_desc + irq;
-}
-
 /* Extract the IA-64 vector that corresponds to IRQ.  */
 static inline ia64_vector
 irq_to_vector (int irq)
index bd07d11d9f37ac81e55a51c7e8ea35b0f19ce0c3..cd984d08fd15b09f27cdc28c4698b38d7bd57ddc 100644 (file)
 #define NR_IRQS                256
 #define NR_IRQ_VECTORS NR_IRQS
 
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
 static __inline__ int
 irq_canonicalize (int irq)
 {
@@ -30,12 +35,6 @@ extern void disable_irq_nosync (unsigned int);
 extern void enable_irq (unsigned int);
 extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
 
-#ifdef CONFIG_SMP
-extern void move_irq(int irq);
-#else
-#define move_irq(irq)
-#endif
-
 struct irqaction;
 struct pt_regs;
 int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
index bf36a32e37e4661dd4abaa944f55e7776c16ee65..573a3574a24fe86ebcd4ecb5be7800c3057b4df5 100644 (file)
@@ -92,6 +92,7 @@ struct arch_specific_insn {
        kprobe_opcode_t insn;
  #define INST_FLAG_FIX_RELATIVE_IP_ADDR                1
  #define INST_FLAG_FIX_BRANCH_REG              2
+ #define INST_FLAG_BREAK_INST                  4
        unsigned long inst_flag;
        unsigned short target_br_reg;
 };
index 91bbd1f2246140121bbaec497101790c6dc278cf..94e07e7273955b1174537b9f0093612c057c1ee0 100644 (file)
@@ -20,9 +20,6 @@
 #include <asm/ptrace.h>
 #include <asm/ustack.h>
 
-/* Our arch specific arch_init_sched_domain is in arch/ia64/kernel/domain.c */
-#define ARCH_HAS_SCHED_DOMAIN
-
 #define IA64_NUM_DBG_REGS      8
 /*
  * Limits for PMC and PMD are set to less than maximum architected values
index 399bc29729fd2c532b20d472fcb208b83be35fa2..a9f738bf18a7e739325a4221269128fa0857ba2b 100644 (file)
@@ -98,29 +98,6 @@ void build_cpu_to_node_map(void);
        .nr_balance_failed      = 0,                    \
 }
 
-/* sched_domains SD_ALLNODES_INIT for IA64 NUMA machines */
-#define SD_ALLNODES_INIT (struct sched_domain) {       \
-       .span                   = CPU_MASK_NONE,        \
-       .parent                 = NULL,                 \
-       .groups                 = NULL,                 \
-       .min_interval           = 64,                   \
-       .max_interval           = 64*num_online_cpus(), \
-       .busy_factor            = 128,                  \
-       .imbalance_pct          = 133,                  \
-       .cache_hot_time         = (10*1000000),         \
-       .cache_nice_tries       = 1,                    \
-       .busy_idx               = 3,                    \
-       .idle_idx               = 3,                    \
-       .newidle_idx            = 0, /* unused */       \
-       .wake_idx               = 0, /* unused */       \
-       .forkexec_idx           = 0, /* unused */       \
-       .per_cpu_gain           = 100,                  \
-       .flags                  = SD_LOAD_BALANCE,      \
-       .last_balance           = jiffies,              \
-       .balance_interval       = 64,                   \
-       .nr_balance_failed      = 0,                    \
-}
-
 #endif /* CONFIG_NUMA */
 
 #include <asm-generic/topology.h>
index 8edd9a90949cf9fa94134f9ebb3b71a889d71322..3a7829bb5954030cfb3a2eee73620de5a3f37403 100644 (file)
 })
 #define access_ok(type, addr, size)    __access_ok((addr), (size), get_fs())
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated
-verify_area (int type, const void __user *addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
diff --git a/include/asm-m32r/auxvec.h b/include/asm-m32r/auxvec.h
new file mode 100644 (file)
index 0000000..f76dcc8
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _ASM_M32R__AUXVEC_H
+#define _ASM_M32R__AUXVEC_H
+
+#endif  /* _ASM_M32R__AUXVEC_H */
index 3e3089572028f85e05b314536914fc08ac25f6c6..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,92 +1 @@
-#ifndef _ASM_M32R_FCNTL_H
-#define _ASM_M32R_FCNTL_H
-
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
-#endif  /* _ASM_M32R_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-m32r/futex.h b/include/asm-m32r/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-m32r/hdreg.h b/include/asm-m32r/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index bbb8ac4018a070d615d9df5d6fa356da3ed91ded..93d863c455a19ff302af1e231a578616bc1d9270 100644 (file)
@@ -120,31 +120,6 @@ static inline int access_ok(int type, const void *addr, unsigned long size)
 }
 #endif /* CONFIG_MMU */
 
-/**
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only.  This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void __user *addr,
-                             unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-m68k/auxvec.h b/include/asm-m68k/auxvec.h
new file mode 100644 (file)
index 0000000..844d6d5
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
index 0d4212983a3313221c5cf31bea0f0fc8e16c2863..1c369b20dc45b7587ad0993cb272dd57390b50d1 100644 (file)
@@ -1,87 +1,11 @@
 #ifndef _M68K_FCNTL_H
 #define _M68K_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE        0003
-#define O_RDONLY           00
-#define O_WRONLY           01
-#define O_RDWR             02
-#define O_CREAT                  0100  /* not fcntl */
-#define O_EXCL           0200  /* not fcntl */
-#define O_NOCTTY         0400  /* not fcntl */
-#define O_TRUNC                 01000  /* not fcntl */
-#define O_APPEND        02000
-#define O_NONBLOCK      04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC         010000
-#define FASYNC         020000  /* fcntl, for BSD compatibility */
 #define O_DIRECTORY    040000  /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
-#define O_NOATIME      01000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
+#include <asm-generic/fcntl.h>
 
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif /* _M68K_FCNTL_H */
diff --git a/include/asm-m68k/futex.h b/include/asm-m68k/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-m68k/hdreg.h b/include/asm-m68k/hdreg.h
deleted file mode 100644 (file)
index 5989bbc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
index 605e6cb811f80847fc6646ace670d2312da7339e..f5cedf19cf682c51349cd4b0856162ad0d6a1bf0 100644 (file)
 /* We let the MMU do all checking */
 #define access_ok(type,addr,size) 1
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-m68knommu/auxvec.h b/include/asm-m68knommu/auxvec.h
new file mode 100644 (file)
index 0000000..844d6d5
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
diff --git a/include/asm-m68knommu/futex.h b/include/asm-m68knommu/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-m68knommu/hdreg.h b/include/asm-m68knommu/hdreg.h
deleted file mode 100644 (file)
index 5cdd9b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/hdreg.h>
index f0be74bb353c634d04ea2400e30b2a1d180e7ac1..05be9515a2d2e8509cdac90753c3903435b24b70 100644 (file)
@@ -23,12 +23,6 @@ static inline int _access_ok(unsigned long addr, unsigned long size)
                (is_in_rom(addr) && is_in_rom(addr+size)));
 }
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
-       return access_ok(type,addr,size)?0:-EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-mips/auxvec.h b/include/asm-mips/auxvec.h
new file mode 100644 (file)
index 0000000..7cf7f2d
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _ASM_AUXVEC_H
+#define _ASM_AUXVEC_H
+
+#endif /* _ASM_AUXVEC_H */
index d78002afb1e12927f080b13f930da9006d698ed1..2c084cd4bc0af81a2b3e3ad686022cfa18e3f3d9 100644 (file)
@@ -15,8 +15,10 @@ typedef s32          compat_clock_t;
 typedef s32            compat_suseconds_t;
 
 typedef s32            compat_pid_t;
-typedef s32            compat_uid_t;
-typedef s32            compat_gid_t;
+typedef u32            __compat_uid_t;
+typedef u32            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u32            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u32            compat_dev_t;
@@ -52,8 +54,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid32_t        st_uid;
+       __compat_gid32_t        st_gid;
        compat_dev_t    st_rdev;
        s32             st_pad2[2];
        compat_off_t    st_size;
index 2436392e7990d1fec80312ccfcea02e9e3eeb28d..06c5d13faf6629f933c22c7f70cb9ceea14495dd 100644 (file)
@@ -8,33 +8,16 @@
 #ifndef _ASM_FCNTL_H
 #define _ASM_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE      0x0003
-#define O_RDONLY       0x0000
-#define O_WRONLY       0x0001
-#define O_RDWR         0x0002
 #define O_APPEND       0x0008
 #define O_SYNC         0x0010
 #define O_NONBLOCK     0x0080
 #define O_CREAT         0x0100 /* not fcntl */
-#define O_TRUNC                0x0200  /* not fcntl */
 #define O_EXCL         0x0400  /* not fcntl */
 #define O_NOCTTY       0x0800  /* not fcntl */
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
 #define O_LARGEFILE    0x2000  /* allow large file opens */
 #define O_DIRECT       0x8000  /* direct disk access hint */
-#define O_DIRECTORY    0x10000 /* must be a directory */
-#define O_NOFOLLOW     0x20000 /* don't follow links */
-#define O_NOATIME      0x40000
 
-#define O_NDELAY       O_NONBLOCK
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
 #define F_GETLK                14
 #define F_SETLK                6
 #define F_SETLKW       7
 #define F_SETLKW64     35
 #endif
 
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
 /*
  * The flavours of struct flock.  "struct flock" is the ABI compliant
  * variant.  Finally struct flock64 is the LFS variant of struct flock.  As
@@ -86,7 +42,7 @@
 
 #ifndef __mips64
 
-typedef struct flock {
+struct flock {
        short   l_type;
        short   l_whence;
        __kernel_off_t l_start;
@@ -94,32 +50,17 @@ typedef struct flock {
        long    l_sysid;
        __kernel_pid_t l_pid;
        long    pad[4];
-} flock_t;
-
-typedef struct flock64 {
-       short   l_type;
-       short   l_whence;
-       loff_t  l_start;
-       loff_t  l_len;
-       pid_t   l_pid;
-} flock64_t;
+};
 
-#else /* 64-bit definitions */
+#define HAVE_ARCH_STRUCT_FLOCK
 
-typedef struct flock {
-       short   l_type;
-       short   l_whence;
-       __kernel_off_t l_start;
-       __kernel_off_t l_len;
-       __kernel_pid_t l_pid;
-} flock_t;
-
-#ifdef __KERNEL__
-#define flock64                flock
 #endif
 
-#endif
+#include <asm-generic/fcntl.h>
 
-#define F_LINUX_SPECIFIC_BASE  1024
+typedef struct flock flock_t;
+#ifndef __mips64
+typedef struct flock64 flock64_t;
+#endif
 
 #endif /* _ASM_FCNTL_H */
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
new file mode 100644 (file)
index 0000000..9feff4c
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-mips/hdreg.h b/include/asm-mips/hdreg.h
deleted file mode 100644 (file)
index 5989bbc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
index a543ead72ecf5e5c70e7f937a35760536a3b8db0..5c2c9832901204ade583cf5314f629a1b5624178 100644 (file)
 #define access_ok(type, addr, size)                                    \
        likely(__access_ok((unsigned long)(addr), (size),__access_mask))
 
-/*
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only.  This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * put_user: - Write a simple value into user space.
  * @x:   Value to copy to user space.
diff --git a/include/asm-parisc/auxvec.h b/include/asm-parisc/auxvec.h
new file mode 100644 (file)
index 0000000..9c3ac4b
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMPARISC_AUXVEC_H
+#define __ASMPARISC_AUXVEC_H
+
+#endif
index 7630d1ad2391ada9799226cb13eadaf5fc3edf63..38b918feead90ee9e2218d052346cef8046975a8 100644 (file)
@@ -13,8 +13,10 @@ typedef s32  compat_ssize_t;
 typedef s32    compat_time_t;
 typedef s32    compat_clock_t;
 typedef s32    compat_pid_t;
-typedef u32    compat_uid_t;
-typedef u32    compat_gid_t;
+typedef u32    __compat_uid_t;
+typedef u32    __compat_gid_t;
+typedef u32    __compat_uid32_t;
+typedef u32    __compat_gid32_t;
 typedef u16    compat_mode_t;
 typedef u32    compat_ino_t;
 typedef u32    compat_dev_t;
@@ -67,8 +69,8 @@ struct compat_stat {
        compat_dev_t            st_realdev;
        u16                     st_basemode;
        u16                     st_spareshort;
-       compat_uid_t            st_uid;
-       compat_gid_t            st_gid;
+       __compat_uid32_t        st_uid;
+       __compat_gid32_t        st_gid;
        u32                     st_spare4[3];
 };
 
index def35230716afc55a1e14f81fede288b96de35ad..317851fa78f3f99b702ba30fff49dea37da728ef 100644 (file)
@@ -3,38 +3,22 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE      00000003
-#define O_RDONLY       00000000
-#define O_WRONLY       00000001
-#define O_RDWR         00000002
 #define O_APPEND       00000010
 #define O_BLKSEEK      00000100 /* HPUX only */
 #define O_CREAT                00000400 /* not fcntl */
-#define O_TRUNC                00001000 /* not fcntl */
 #define O_EXCL         00002000 /* not fcntl */
 #define O_LARGEFILE    00004000
 #define O_SYNC         00100000
 #define O_NONBLOCK     00200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NDELAY       O_NONBLOCK
 #define O_NOCTTY       00400000 /* not fcntl */
 #define O_DSYNC                01000000 /* HPUX only */
 #define O_RSYNC                02000000 /* HPUX only */
 #define O_NOATIME      04000000
 
-#define FASYNC         00020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT       00040000 /* direct disk access hint - currently ignored */
 #define O_DIRECTORY    00010000 /* must be a directory */
 #define O_NOFOLLOW     00000200 /* don't follow links */
 #define O_INVISIBLE    04000000 /* invisible I/O, for DMAPI/XDSM */
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get f_flags */
-#define F_SETFD                2       /* set f_flags */
-#define F_GETFL                3       /* more flags (cloexec) */
-#define F_SETFL                4
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
 #define F_GETLK64      8
 #define F_SETLK64      9
 #define F_SETLKW64     10
 #define F_SETSIG       13      /*  for sockets. */
 #define F_GETSIG       14      /*  for sockets. */
 
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
 /* for posix fcntl() and lockf() */
 #define F_RDLCK                01
 #define F_WRLCK                02
 #define F_UNLCK                03
 
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short l_type;
-       short l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
+#include <asm-generic/fcntl.h>
 
 #endif
diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-parisc/hdreg.h b/include/asm-parisc/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index 75654ba9335359b71c61bd2f0369b757e188c196..f876bdf220569f0f90eaec0436665a8bf95d1464 100644 (file)
 
 #define NR_IRQS                (CPU_IRQ_MAX + 1)
 
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
 static __inline__ int irq_canonicalize(int irq)
 {
        return (irq == 2) ? 9 : irq;
index c1b5bdea53ee078773584f3842393b8640740ed0..f6c417c8c484a8965eee6ac6cfd175d45a82c8d4 100644 (file)
@@ -40,10 +40,6 @@ static inline long access_ok(int type, const void __user * addr,
        return 1;
 }
 
-#define verify_area(type,addr,size) (0)        /* FIXME: all users should go away soon,
-                                         * and use access_ok instead, then this
-                                         * should be removed. */
-
 #define put_user __put_user
 #define get_user __get_user
 
diff --git a/include/asm-powerpc/fcntl.h b/include/asm-powerpc/fcntl.h
new file mode 100644 (file)
index 0000000..ce5c451
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_FCNTL_H
+#define _ASM_FCNTL_H
+
+#define O_DIRECTORY      040000        /* must be a directory */
+#define O_NOFOLLOW      0100000        /* don't follow links */
+#define O_LARGEFILE     0200000
+#define O_DIRECT       0400000 /* direct disk access hint */
+
+#include <asm-generic/fcntl.h>
+
+#endif /* _ASM_FCNTL_H */
diff --git a/include/asm-ppc/auxvec.h b/include/asm-ppc/auxvec.h
new file mode 100644 (file)
index 0000000..172358d
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __PPC_AUXVEC_H
+#define __PPC_AUXVEC_H
+
+/*
+ * We need to put in some extra aux table entries to tell glibc what
+ * the cache block size is, so it can use the dcbz instruction safely.
+ */
+#define AT_DCACHEBSIZE         19
+#define AT_ICACHEBSIZE         20
+#define AT_UCACHEBSIZE         21
+/* A special ignored type value for PPC, for glibc compatibility.  */
+#define AT_IGNOREPPC           22
+
+#endif
index 2c056966efd34650ee5dfeb6f0d79c0516659bc2..c25cc35e6ab5818702dbca5241c92a93bbad2a97 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/cputable.h>
+#include <asm/auxvec.h>
 
 /* PowerPC relocations defined by the ABIs */
 #define R_PPC_NONE             0
@@ -122,16 +123,6 @@ extern int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpu);
 
 #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
 
-/*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE         19
-#define AT_ICACHEBSIZE         20
-#define AT_UCACHEBSIZE         21
-/* A special ignored type value for PPC, for glibc compatibility.  */
-#define AT_IGNOREPPC           22
-
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
diff --git a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h
deleted file mode 100644 (file)
index 5e28e41..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef _PPC_FCNTL_H
-#define _PPC_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECTORY      040000        /* must be a directory */
-#define O_NOFOLLOW      0100000        /* don't follow links */
-#define O_LARGEFILE     0200000
-#define O_DIRECT       0400000 /* direct disk access hint */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-#ifdef __KERNEL__
-#define F_POSIX                1
-#define F_FLOCK                2
-#define F_BROKEN       4       /* broken flock() emulation */
-#endif /* __KERNEL__ */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-#endif
diff --git a/include/asm-ppc/futex.h b/include/asm-ppc/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index bd7656fa20266d0efa7cedf8f1f78231e754ad8a..6f10a25bd628c18cc2f4bd1462d79c9f61936a86 100644 (file)
@@ -84,6 +84,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx)    \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, tah_idx)      \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, phy_mode)     \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_map)  \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_feat_exc)\
                                                                        \
 void ocp_show_emac_data(struct device *dev)                            \
 {                                                                      \
@@ -99,6 +100,7 @@ void ocp_show_emac_data(struct device *dev)                          \
        device_create_file(dev, &dev_attr_emac_tah_idx);                \
        device_create_file(dev, &dev_attr_emac_phy_mode);               \
        device_create_file(dev, &dev_attr_emac_phy_map);                \
+       device_create_file(dev, &dev_attr_emac_phy_feat_exc);           \
 }
 
 /*
index a244d93ca9537179a7fe6835df81d19eeb9325fb..b4b270457eddce51eac0e30a6e604fb82630740e 100644 (file)
 #define IRQ_POLARITY_POSITIVE  0x2     /* high level or low->high edge */
 #define IRQ_POLARITY_NEGATIVE  0x0     /* low level or high->low edge */
 
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
 #if defined(CONFIG_40x)
 #include <asm/ibm4xx.h>
 
index b044ae03ac5638b01dff66e5bd150b404effe07e..63f56224da8ca3b69361b9f6801a81a80d12c6e3 100644 (file)
 #define access_ok(type, addr, size) \
        (__chk_user_ptr(addr),__access_ok((unsigned long)(addr),(size)))
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-ppc64/auxvec.h b/include/asm-ppc64/auxvec.h
new file mode 100644 (file)
index 0000000..ac6381a
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __PPC64_AUXVEC_H
+#define __PPC64_AUXVEC_H
+
+/*
+ * We need to put in some extra aux table entries to tell glibc what
+ * the cache block size is, so it can use the dcbz instruction safely.
+ */
+#define AT_DCACHEBSIZE         19
+#define AT_ICACHEBSIZE         20
+#define AT_UCACHEBSIZE         21
+/* A special ignored type value for PPC, for glibc compatibility.  */
+#define AT_IGNOREPPC           22
+
+/* The vDSO location. We have to use the same value as x86 for glibc's
+ * sake :-)
+ */
+#define AT_SYSINFO_EHDR                33
+
+#endif /* __PPC64_AUXVEC_H */
index 12414f5fc666b00a13c433aa42326127e93c168b..6ec62cd2d1d1e24f8559b8cf65316d929a45474d 100644 (file)
@@ -13,8 +13,10 @@ typedef s32          compat_ssize_t;
 typedef s32            compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_pid_t;
-typedef u32            compat_uid_t;
-typedef u32            compat_gid_t;
+typedef u32            __compat_uid_t;
+typedef u32            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u32            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u32            compat_dev_t;
@@ -48,8 +50,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;       
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid32_t        st_uid;
+       __compat_gid32_t        st_gid;
        compat_dev_t    st_rdev;
        compat_off_t    st_size;
        compat_off_t    st_blksize;
@@ -144,10 +146,10 @@ static inline void __user *compat_alloc_user_space(long len)
  */
 struct compat_ipc64_perm {
        compat_key_t key;
-       compat_uid_t uid;
-       compat_gid_t gid;
-       compat_uid_t cuid;
-       compat_gid_t cgid;
+       __compat_uid_t uid;
+       __compat_gid_t gid;
+       __compat_uid_t cuid;
+       __compat_gid_t cgid;
        compat_mode_t mode;
        unsigned int seq;
        unsigned int __pad2;
index 085eedb956fe02f7a0f34c1cbea0895e476b00ee..c919a89343db0a3b0efb583b63fbf3ebad30ac8b 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/cputable.h>
+#include <asm/auxvec.h>
 
 /* PowerPC relocations defined by the ABIs */
 #define R_PPC_NONE             0
@@ -237,21 +238,6 @@ do {                                                               \
 
 #endif
 
-/*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE         19
-#define AT_ICACHEBSIZE         20
-#define AT_UCACHEBSIZE         21
-/* A special ignored type value for PPC, for glibc compatibility.  */
-#define AT_IGNOREPPC           22
-
-/* The vDSO location. We have to use the same value as x86 for glibc's
- * sake :-)
- */
-#define AT_SYSINFO_EHDR                33
-
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
diff --git a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h
deleted file mode 100644 (file)
index 842560d..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef _PPC64_FCNTL_H
-#define _PPC64_FCNTL_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECTORY      040000        /* must be a directory */
-#define O_NOFOLLOW      0100000        /* don't follow links */
-#define O_LARGEFILE     0200000
-#define O_DIRECT       0400000 /* direct disk access hint */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-#ifdef __KERNEL__
-#define F_POSIX                1
-#define F_FLOCK                2
-#define F_BROKEN       4       /* broken flock() emulation */
-#endif /* __KERNEL__ */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
-#endif /* _PPC64_FCNTL_H */
diff --git a/include/asm-ppc64/futex.h b/include/asm-ppc64/futex.h
new file mode 100644 (file)
index 0000000..cb2640b
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/memory.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+  __asm__ __volatile (SYNC_ON_SMP                              \
+"1:    lwarx   %0,0,%2\n"                                      \
+       insn                                                    \
+"2:    stwcx.  %1,0,%2\n\
+       bne-    1b\n\
+       li      %1,0\n\
+3:     .section .fixup,\"ax\"\n\
+4:     li      %1,%3\n\
+       b       3b\n\
+       .previous\n\
+       .section __ex_table,\"a\"\n\
+       .align 3\n\
+       .llong  1b,4b,2b,4b\n\
+       .previous"                                              \
+       : "=&r" (oldval), "=&r" (ret)                           \
+       : "b" (uaddr), "i" (-EFAULT), "1" (oparg)               \
+       : "cr0", "memory")
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op("", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index 570678b1da950335f1821485745381f470af62ee..99782afb4cdede53a3e1edfc41050f9c2a9ad990 100644 (file)
 #define IRQ_POLARITY_POSITIVE  0x2     /* high level or low->high edge */
 #define IRQ_POLARITY_NEGATIVE  0x0     /* low level or high->low edge */
 
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
 #define get_irq_desc(irq) (&irq_desc[(irq)])
 
 /* Define a way to iterate across irqs. */
index 0802919c3235c1b5cc2debe8a0930558525e6615..d9129d2b038ee7d09f87bd22aa6b10b95e1e3329 100644 (file)
@@ -42,6 +42,9 @@ typedef unsigned int kprobe_opcode_t;
 
 #define JPROBE_ENTRY(pentry)   (kprobe_opcode_t *)((func_descr_t *)pentry)
 
+#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
+                       IS_TWI(instr) || IS_TDI(instr))
+
 #define ARCH_SUPPORTS_KRETPROBES
 void kretprobe_trampoline(void);
 
index 56e09face9a8409e03230d7618b0fd8038eebc1e..af53ffb5572640e2246b9963a2b582d514d98d6d 100644 (file)
 #ifdef CONFIG_SMP
 #define EIEIO_ON_SMP   "eieio\n"
 #define ISYNC_ON_SMP   "\n\tisync"
+#define SYNC_ON_SMP    "lwsync\n\t"
 #else
 #define EIEIO_ON_SMP
 #define ISYNC_ON_SMP
+#define SYNC_ON_SMP
 #endif
 
 static inline void eieio(void)
index 7bd4796f1236c5efe6f7c881ab0aa18a141a1fd8..8bd7aa959385d01d33c530526609e7302cf97921 100644 (file)
@@ -311,6 +311,20 @@ name: \
        .type GLUE(.,name),@function; \
 GLUE(.,name):
 
+#define _KPROBE(name) \
+       .section ".kprobes.text","a"; \
+       .align 2 ; \
+       .globl name; \
+       .globl GLUE(.,name); \
+       .section ".opd","aw"; \
+name: \
+       .quad GLUE(.,name); \
+       .quad .TOC.@tocbase; \
+       .quad 0; \
+       .previous; \
+       .type GLUE(.,name),@function; \
+GLUE(.,name):
+
 #define _STATIC(name) \
        .section ".text"; \
        .align 2 ; \
index 05b5943ab1ee5ade4a88fdd32b3622c4089ece63..c181a60d868c7ee82e79db9ce1d57f9817a8d8d4 100644 (file)
 #define access_ok(type,addr,size) \
        __access_ok(((__force unsigned long)(addr)),(size),get_fs())
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-s390/auxvec.h b/include/asm-s390/auxvec.h
new file mode 100644 (file)
index 0000000..0d34072
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMS390_AUXVEC_H
+#define __ASMS390_AUXVEC_H
+
+#endif
index 7f8f544eb262f8edb58a97090559ad280eea2918..a007715f4aea8150577e00b9777baee9dc04c7b9 100644 (file)
@@ -13,10 +13,10 @@ typedef s32         compat_ssize_t;
 typedef s32            compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_pid_t;
-typedef u16            compat_uid_t;
-typedef u16            compat_gid_t;
-typedef u32            compat_uid32_t;
-typedef u32            compat_gid32_t;
+typedef u16            __compat_uid_t;
+typedef u16            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u16            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u16            compat_dev_t;
@@ -51,8 +51,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid_t  st_uid;
+       __compat_gid_t  st_gid;
        compat_dev_t    st_rdev;
        u16             __pad2;
        u32             st_size;
@@ -140,10 +140,10 @@ static inline void __user *compat_alloc_user_space(long len)
 
 struct compat_ipc64_perm {
        compat_key_t key;
-       compat_uid32_t uid;
-       compat_gid32_t gid;
-       compat_uid32_t cuid;
-       compat_gid32_t cgid;
+       __compat_uid32_t uid;
+       __compat_gid32_t gid;
+       __compat_uid32_t cuid;
+       __compat_gid32_t cgid;
        compat_mode_t mode;
        unsigned short __pad1;
        unsigned short seq;
index 48f692b45732494165dd7f38028731214ed1f1a0..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,97 +1 @@
-/*
- *  include/asm-s390/fcntl.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/fcntl.h"
- */
-#ifndef _S390_FCNTL_H
-#define _S390_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#ifndef __s390x__
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-#endif /* ! __s390x__ */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-#ifndef __s390x__
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-#endif
-#define F_LINUX_SPECIFIC_BASE  1024
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index 3e3bfe6a8fa84188f86f1acef2d17e84814771c3..38a5cf8ab9e3e5cc69f162f1b8af363f886b7046 100644 (file)
 
 #define access_ok(type,addr,size) __access_ok(addr,size)
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user *addr,
-                                               unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-sh/auxvec.h b/include/asm-sh/auxvec.h
new file mode 100644 (file)
index 0000000..fc21e4d
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASM_SH_AUXVEC_H
+#define __ASM_SH_AUXVEC_H
+
+#endif /* __ASM_SH_AUXVEC_H */
index 0b3ae524e34cca05d8cf77cc617ccb72fca7fb27..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,88 +1 @@
-#ifndef __ASM_SH_FCNTL_H
-#define __ASM_SH_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-#endif /* __ASM_SH_FCNTL_H */
-
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-sh/hdreg.h b/include/asm-sh/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index fb9e334afa2be050acd666412a4e5c8264a1d7f2..2cb01861e7c550babe2e44409aa0be3942d2415a 100644 (file)
@@ -146,12 +146,6 @@ static inline int access_ok(int type, const void __user *p, unsigned long size)
        return __access_ok(addr, size);
 }
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * Uh, these should become the main single-value transfer routines ...
  * They automatically use the right size if we just have the right
diff --git a/include/asm-sh64/auxvec.h b/include/asm-sh64/auxvec.h
new file mode 100644 (file)
index 0000000..1ad5a44
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASM_SH64_AUXVEC_H
+#define __ASM_SH64_AUXVEC_H
+
+#endif /* __ASM_SH64_AUXVEC_H */
index ffcc36c64fa5a3dc01996514010d176bc495b443..744dd79b9d5d4ee40c5a63e1542c5cf26109fc13 100644 (file)
@@ -1,7 +1 @@
-#ifndef __ASM_SH64_FCNTL_H
-#define __ASM_SH64_FCNTL_H
-
 #include <asm-sh/fcntl.h>
-
-#endif /* __ASM_SH64_FCNTL_H */
-
diff --git a/include/asm-sh64/futex.h b/include/asm-sh64/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-sh64/hdreg.h b/include/asm-sh64/hdreg.h
deleted file mode 100644 (file)
index 52d9836..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_SH64_HDREG_H
-#define __ASM_SH64_HDREG_H
-
-#include <asm-generic/hdreg.h>
-
-#endif /* __ASM_SH64_HDREG_H */
index a33654d576a1a05dd2328a605217298dbbd18381..56aa3cf0f2734da96dda1ce66469dd4d5b4fcb13 100644 (file)
 #define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
 #define __access_ok(addr,size) (__range_ok(addr,size) == 0)
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * Uh, these should become the main single-value transfer routines ...
  * They automatically use the right size if we just have the right
diff --git a/include/asm-sparc/auxvec.h b/include/asm-sparc/auxvec.h
new file mode 100644 (file)
index 0000000..ad6f360
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMSPARC_AUXVEC_H
+#define __ASMSPARC_AUXVEC_H
+
+#endif /* !(__ASMSPARC_AUXVEC_H) */
index df9c75d41d6802527e72b912635b85777ddb40f0..5db60b5ae7b09d26812f7dfb1d735183e721aced 100644 (file)
@@ -4,10 +4,6 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_RDONLY       0x0000
-#define O_WRONLY       0x0001
-#define O_RDWR         0x0002
-#define O_ACCMODE      0x0003
 #define O_APPEND       0x0008
 #define FASYNC         0x0040  /* fcntl, for BSD compatibility */
 #define O_CREAT                0x0200  /* not fcntl */
 #define O_NONBLOCK     0x4000
 #define O_NDELAY       (0x0004 | O_NONBLOCK)
 #define O_NOCTTY       0x8000  /* not fcntl */
-#define O_DIRECTORY    0x10000 /* must be a directory */
-#define O_NOFOLLOW     0x20000 /* don't follow links */
 #define O_LARGEFILE    0x40000
 #define O_DIRECT        0x100000 /* direct disk access hint */
 #define O_NOATIME      0x200000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
 #define F_GETOWN       5       /*  for sockets. */
 #define F_SETOWN       6       /*  for sockets. */
 #define F_GETLK                7
 #define F_SETLK                8
 #define F_SETLKW       9
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
 
 /* for posix fcntl() and lockf() */
 #define F_RDLCK                1
 #define F_WRLCK                2
 #define F_UNLCK                3
 
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-       short __unused;
-};
+#define __ARCH_FLOCK_PAD       short __unused;
+#define __ARCH_FLOCK64_PAD     short __unused;
 
-struct flock64 {
-       short l_type;
-       short l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t l_pid;
-       short __unused;
-};
+#include <asm-generic/fcntl.h>
 
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif
diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-sparc/hdreg.h b/include/asm-sparc/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index 0a780e84a12b749fd6f1e4381407f34affcb895b..f8f1ec1f06e6ce840dc9cc5a7edc76ad03c63ebf 100644 (file)
 #define access_ok(type, addr, size)                                    \
        ({ (void)(type); __access_ok((unsigned long)(addr), size); })
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-sparc64/auxvec.h b/include/asm-sparc64/auxvec.h
new file mode 100644 (file)
index 0000000..436a291
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASM_SPARC64_AUXVEC_H
+#define __ASM_SPARC64_AUXVEC_H
+
+#endif /* !(__ASM_SPARC64_AUXVEC_H) */
index b59122dd176dd0583fd7a1a60b0cb0303927f73c..c73935dc7ba11c8e800b79596d6ae27e3431fd30 100644 (file)
@@ -12,8 +12,10 @@ typedef s32          compat_ssize_t;
 typedef s32            compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_pid_t;
-typedef u16            compat_uid_t;
-typedef u16            compat_gid_t;
+typedef u16            __compat_uid_t;
+typedef u16            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u16            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u16            compat_dev_t;
@@ -47,8 +49,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid_t  st_uid;
+       __compat_gid_t  st_gid;
        compat_dev_t    st_rdev;
        compat_off_t    st_size;
        compat_time_t   st_atime;
@@ -177,10 +179,10 @@ static __inline__ void __user *compat_alloc_user_space(long len)
 
 struct compat_ipc64_perm {
        compat_key_t key;
-       __kernel_uid_t uid;
-       __kernel_gid_t gid;
-       __kernel_uid_t cuid;
-       __kernel_gid_t cgid;
+       __compat_uid32_t uid;
+       __compat_gid32_t gid;
+       __compat_uid32_t cuid;
+       __compat_gid32_t cgid;
        unsigned short __pad1;
        compat_mode_t mode;
        unsigned short __pad2;
index e36def0d0d809de784e850648afb0b939581ccef..b2aecf0054bd2167b990ddc2da53dec57458aca9 100644 (file)
@@ -4,10 +4,6 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_RDONLY       0x0000
-#define O_WRONLY       0x0001
-#define O_RDWR         0x0002
-#define O_ACCMODE      0x0003
 #define O_NDELAY       0x0004
 #define O_APPEND       0x0008
 #define FASYNC         0x0040  /* fcntl, for BSD compatibility */
 #define O_SYNC         0x2000
 #define O_NONBLOCK     0x4000
 #define O_NOCTTY       0x8000  /* not fcntl */
-#define O_DIRECTORY    0x10000 /* must be a directory */
-#define O_NOFOLLOW     0x20000 /* don't follow links */
 #define O_LARGEFILE    0x40000
 #define O_DIRECT        0x100000 /* direct disk access hint */
 #define O_NOATIME      0x200000
 
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
 #define F_GETOWN       5       /*  for sockets. */
 #define F_SETOWN       6       /*  for sockets. */
 #define F_GETLK                7
 #define F_SETLK                8
 #define F_SETLKW       9
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
 
 /* for posix fcntl() and lockf() */
 #define F_RDLCK                1
 #define F_WRLCK                2
 #define F_UNLCK                3
 
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-       short __unused;
-};
+#define __ARCH_FLOCK_PAD       short __unused;
 
-#define F_LINUX_SPECIFIC_BASE  1024
+#include <asm-generic/fcntl.h>
 
 #endif /* !(_SPARC64_FCNTL_H) */
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-sparc64/hdreg.h b/include/asm-sparc64/hdreg.h
deleted file mode 100644 (file)
index 7f7fd1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
index 5690142f82de3774d56faceee2539229ee0e382a..80a65d7e3dbff92308d2b4e1bf5e394e45c97551 100644 (file)
@@ -59,12 +59,6 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
        return 1;
 }
 
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return 0;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-um/auxvec.h b/include/asm-um/auxvec.h
new file mode 100644 (file)
index 0000000..1e5e1c2
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __UM_AUXVEC_H
+#define __UM_AUXVEC_H
+
+#endif
diff --git a/include/asm-um/futex.h b/include/asm-um/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-um/hdreg.h b/include/asm-um/hdreg.h
deleted file mode 100644 (file)
index cf6363a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_HDREG_H
-#define __UM_HDREG_H
-
-#include "asm/arch/hdreg.h"
-
-#endif
diff --git a/include/asm-v850/auxvec.h b/include/asm-v850/auxvec.h
new file mode 100644 (file)
index 0000000..f493232
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __V850_AUXVEC_H__
+#define __V850_AUXVEC_H__
+
+#endif /* __V850_AUXVEC_H__ */
index 31d4b59612211fa3a33b912b19f3c5a74160aeae..3af4d56776ddfafe217e81fd5da095d83e29f19e 100644 (file)
@@ -1,87 +1,11 @@
 #ifndef __V850_FCNTL_H__
 #define __V850_FCNTL_H__
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE        0003
-#define O_RDONLY           00
-#define O_WRONLY           01
-#define O_RDWR             02
-#define O_CREAT                  0100  /* not fcntl */
-#define O_EXCL           0200  /* not fcntl */
-#define O_NOCTTY         0400  /* not fcntl */
-#define O_TRUNC                 01000  /* not fcntl */
-#define O_APPEND        02000
-#define O_NONBLOCK      04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC         010000
-#define FASYNC         020000  /* fcntl, for BSD compatibility */
 #define O_DIRECTORY    040000  /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
-#define O_NOATIME      01000000
 
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
+#include <asm-generic/fcntl.h>
 
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-#define F_GETLK64      12      /*  using 'struct flock64' */
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short l_type;
-       short l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t l_pid;
-};
-
-struct flock64 {
-       short  l_type;
-       short  l_whence;
-       loff_t l_start;
-       loff_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
 #endif /* __V850_FCNTL_H__ */
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h
new file mode 100644 (file)
index 0000000..2cac5ec
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
index 4386cfc6a8dda338cf7ed677f998e4834095221f..188b28597cf1f680a96f271fa7e3244ffdc74831 100644 (file)
@@ -27,12 +27,6 @@ extern inline int access_ok (int type, const void *addr, unsigned long size)
        return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
 }
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area (int type, const void *addr, unsigned long size)
-{
-       return access_ok (type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-x86_64/auxvec.h b/include/asm-x86_64/auxvec.h
new file mode 100644 (file)
index 0000000..2403c4c
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASM_X86_64_AUXVEC_H
+#define __ASM_X86_64_AUXVEC_H
+
+#endif
index d0f453c5adfc6dd04edc3353ddd61750d5cc322e..f0155c38f639056f6c4f812fb8ad5ab345e090d0 100644 (file)
@@ -14,10 +14,10 @@ typedef s32         compat_ssize_t;
 typedef s32            compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_pid_t;
-typedef u16            compat_uid_t;
-typedef u16            compat_gid_t;
-typedef u32            compat_uid32_t;
-typedef u32            compat_gid32_t;
+typedef u16            __compat_uid_t;
+typedef u16            __compat_gid_t;
+typedef u32            __compat_uid32_t;
+typedef u32            __compat_gid32_t;
 typedef u16            compat_mode_t;
 typedef u32            compat_ino_t;
 typedef u16            compat_dev_t;
@@ -52,8 +52,8 @@ struct compat_stat {
        compat_ino_t    st_ino;
        compat_mode_t   st_mode;
        compat_nlink_t  st_nlink;
-       compat_uid_t    st_uid;
-       compat_gid_t    st_gid;
+       __compat_uid_t  st_uid;
+       __compat_gid_t  st_gid;
        compat_dev_t    st_rdev;
        u16             __pad2;
        u32             st_size;
@@ -122,10 +122,10 @@ typedef u32               compat_sigset_word;
 
 struct compat_ipc64_perm {
        compat_key_t key;
-       compat_uid32_t uid;
-       compat_gid32_t gid;
-       compat_uid32_t cuid;
-       compat_gid32_t cgid;
+       __compat_uid32_t uid;
+       __compat_gid32_t gid;
+       __compat_uid32_t cuid;
+       __compat_gid32_t cgid;
        unsigned short mode;
        unsigned short __pad1;
        unsigned short seq;
index 4411f221c03789976a6b3f367cfeec7d06c7c2a4..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -1,76 +1 @@
-#ifndef _X86_64_FCNTL_H
-#define _X86_64_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE         0003
-#define O_RDONLY            00
-#define O_WRONLY            01
-#define O_RDWR              02
-#define O_CREAT                   0100 /* not fcntl */
-#define O_EXCL            0200 /* not fcntl */
-#define O_NOCTTY          0400 /* not fcntl */
-#define O_TRUNC                  01000 /* not fcntl */
-#define O_APPEND         02000
-#define O_NONBLOCK       04000
-#define O_NDELAY       O_NONBLOCK
-#define O_SYNC          010000
-#define FASYNC          020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT        040000 /* direct disk access hint */
-#define O_LARGEFILE    0100000
-#define O_DIRECTORY    0200000 /* must be a directory */
-#define O_NOFOLLOW     0400000 /* don't follow links */
-#define O_NOATIME      01000000
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
-#define F_GETLK                5
-#define F_SETLK                6
-#define F_SETLKW       7
-
-#define F_SETOWN       8       /*  for sockets. */
-#define F_GETOWN       9       /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock */
-#define LOCK_READ      64      /* ... Which allows concurrent read operations */
-#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
-#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
-
-struct flock {
-       short  l_type;
-       short  l_whence;
-       off_t l_start;
-       off_t l_len;
-       pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE  1024
-
-#endif /* !_X86_64_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h
new file mode 100644 (file)
index 0000000..8602c09
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+  __asm__ __volatile (                                         \
+"1:    " insn "\n"                                             \
+"2:    .section .fixup,\"ax\"\n\
+3:     mov     %3, %1\n\
+       jmp     2b\n\
+       .previous\n\
+       .section __ex_table,\"a\"\n\
+       .align  8\n\
+       .quad   1b,3b\n\
+       .previous"                                              \
+       : "=r" (oldval), "=r" (ret), "=m" (*uaddr)              \
+       : "i" (-EFAULT), "m" (*uaddr), "0" (oparg), "1" (0))
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+  __asm__ __volatile (                                         \
+"1:    movl    %2, %0\n\
+       movl    %0, %3\n"                                       \
+       insn "\n"                                               \
+"2:    " LOCK_PREFIX "cmpxchgl %3, %2\n\
+       jnz     1b\n\
+3:     .section .fixup,\"ax\"\n\
+4:     mov     %5, %1\n\
+       jmp     3b\n\
+       .previous\n\
+       .section __ex_table,\"a\"\n\
+       .align  8\n\
+       .quad   1b,4b,2b,4b\n\
+       .previous"                                              \
+       : "=&a" (oldval), "=&r" (ret), "=m" (*uaddr),           \
+         "=&r" (tem)                                           \
+       : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0))
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
+                                  uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op2("orl %4, %3", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op2("andl %4, %3", ret, oldval, uaddr, ~oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op2("xorl %4, %3", ret, oldval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif
+#endif
diff --git a/include/asm-x86_64/hdreg.h b/include/asm-x86_64/hdreg.h
deleted file mode 100644 (file)
index 5989bbc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
index 194160f6a43f2064e8f1561a0111f91d5a084286..a8321999448f840e256d142a3cf2a62cd62db120 100644 (file)
@@ -398,7 +398,7 @@ static inline void prefetch(void *x)
 #define ARCH_HAS_PREFETCHW 1
 static inline void prefetchw(void *x) 
 { 
-       alternative_input(ASM_NOP5,
+       alternative_input("prefetcht0 (%1)",
                          "prefetchw (%1)",
                          X86_FEATURE_3DNOW,
                          "r" (x));
index 48f292752c96bac97900682b98e947651b701d6b..1bb8b8a24436b2387a348b8d0ae880e14d61c6c6 100644 (file)
 
 #define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
 
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
-       return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-xtensa/auxvec.h b/include/asm-xtensa/auxvec.h
new file mode 100644 (file)
index 0000000..257dec7
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __XTENSA_AUXVEC_H
+#define __XTENSA_AUXVEC_H
+
+#endif
index 48876bb727d213bc14a1df93f9bcac0d36b85a5e..ec066ae96caf166c09433442f2ac516d2c501c8c 100644 (file)
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE      0x0003
-#define O_RDONLY       0x0000
-#define O_WRONLY       0x0001
-#define O_RDWR         0x0002
 #define O_APPEND       0x0008
 #define O_SYNC         0x0010
 #define O_NONBLOCK     0x0080
 #define O_CREAT         0x0100 /* not fcntl */
-#define O_TRUNC                0x0200  /* not fcntl */
 #define O_EXCL         0x0400  /* not fcntl */
 #define O_NOCTTY       0x0800  /* not fcntl */
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
 #define O_LARGEFILE    0x2000  /* allow large file opens - currently ignored */
 #define O_DIRECT       0x8000  /* direct disk access hint - currently ignored*/
-#define O_DIRECTORY    0x10000 /* must be a directory */
-#define O_NOFOLLOW     0x20000 /* don't follow links */
 #define O_NOATIME      0x100000
 
-#define O_NDELAY       O_NONBLOCK
-
-#define F_DUPFD                0       /* dup */
-#define F_GETFD                1       /* get close_on_exec */
-#define F_SETFD                2       /* set/clear close_on_exec */
-#define F_GETFL                3       /* get file->f_flags */
-#define F_SETFL                4       /* set file->f_flags */
 #define F_GETLK                14
 #define F_GETLK64       15
 #define F_SETLK                6
 
 #define F_SETOWN       24      /*  for sockets. */
 #define F_GETOWN       23      /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                0
-#define F_WRLCK                1
-#define F_UNLCK                2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK                4       /* or 3 */
-#define F_SHLCK                8       /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS   16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH                1       /* shared lock */
-#define LOCK_EX                2       /* exclusive lock */
-#define LOCK_NB                4       /* or'd with one of the above to prevent
-                                  blocking */
-#define LOCK_UN                8       /* remove lock */
-
-#define LOCK_MAND      32      /* This is a mandatory flock ... */
-#define LOCK_READ      64      /*  which allows concurrent read operations */
-#define LOCK_WRITE     128     /*  which allows concurrent write operations */
-#define LOCK_RW                192     /*  which allows concurrent read & write ops */
 
 typedef struct flock {
        short l_type;
@@ -96,6 +53,9 @@ struct flock64 {
        pid_t  l_pid;
 };
 
-#define F_LINUX_SPECIFIC_BASE  1024
+#define HAVE_ARCH_STRUCT_FLOCK
+#define HAVE_ARCH_STRUCT_FLOCK64
+
+#include <asm-generic/fcntl.h>
 
 #endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/hdreg.h b/include/asm-xtensa/hdreg.h
deleted file mode 100644 (file)
index 64b8060..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-xtensa/hdreg.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- * Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-#ifndef _XTENSA_HDREG_H
-#define _XTENSA_HDREG_H
-
-typedef unsigned int ide_ioreg_t;
-
-#endif
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
new file mode 100644 (file)
index 0000000..9a7b374
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _LINUX_AUXVEC_H
+#define _LINUX_AUXVEC_H
+
+#include <asm/auxvec.h>
+
+/* Symbolic values for the entries in the auxiliary table
+   put on the initial stack */
+#define AT_NULL   0    /* end of vector */
+#define AT_IGNORE 1    /* entry should be ignored */
+#define AT_EXECFD 2    /* file descriptor of program */
+#define AT_PHDR   3    /* program headers for program */
+#define AT_PHENT  4    /* size of program header entry */
+#define AT_PHNUM  5    /* number of program headers */
+#define AT_PAGESZ 6    /* system page size */
+#define AT_BASE   7    /* base address of interpreter */
+#define AT_FLAGS  8    /* flags */
+#define AT_ENTRY  9    /* entry point of program */
+#define AT_NOTELF 10   /* program is not ELF */
+#define AT_UID    11   /* real uid */
+#define AT_EUID   12   /* effective uid */
+#define AT_GID    13   /* real gid */
+#define AT_EGID   14   /* effective gid */
+#define AT_PLATFORM 15  /* string identifying CPU for optimizations */
+#define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
+#define AT_CLKTCK 17   /* frequency at which times() increments */
+
+#define AT_SECURE 23   /* secure mode boolean */
+
+#define AT_VECTOR_SIZE  42 /* Size of auxiliary table.  */
+
+#endif /* _LINUX_AUXVEC_H */
index 36ef29fa0d8b64a1cc2e2406bd9a8b30f83ab026..69e047989f1c45f4b417a7ad99d024ff60c83c88 100644 (file)
@@ -111,7 +111,6 @@ struct bio {
        void                    *bi_private;
 
        bio_destructor_t        *bi_destructor; /* destructor */
-       struct bio_set          *bi_set;        /* memory pools set */
 };
 
 /*
@@ -280,6 +279,7 @@ extern void bioset_free(struct bio_set *);
 extern struct bio *bio_alloc(unsigned int __nocast, int);
 extern struct bio *bio_alloc_bioset(unsigned int __nocast, int, struct bio_set *);
 extern void bio_put(struct bio *);
+extern void bio_free(struct bio *, struct bio_set *);
 
 extern void bio_endio(struct bio *, unsigned int, int);
 struct request_queue;
index b58b7d6f2fdb9168b2dc48d58849ef8f7c5d7c22..f9ca534787e24c1075a965843e87bddd9632e3a9 100644 (file)
@@ -18,6 +18,9 @@
 #define compat_jiffies_to_clock_t(x)   \
                (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
+typedef __compat_uid32_t       compat_uid_t;
+typedef __compat_gid32_t       compat_gid_t;
+
 struct rusage;
 
 struct compat_itimerspec { 
index 3438233305a3aecb1674d527744117f22bd55d95..24062a1dbf61e2674719eb24e36b0d1b062fa396 100644 (file)
@@ -23,7 +23,8 @@ void cpuset_init_current_mems_allowed(void);
 void cpuset_update_current_mems_allowed(void);
 void cpuset_restrict_to_mems_allowed(unsigned long *nodes);
 int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
-int cpuset_zone_allowed(struct zone *z);
+extern int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask);
+extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
 extern struct file_operations proc_cpuset_operations;
 extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
 
@@ -48,7 +49,13 @@ static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
        return 1;
 }
 
-static inline int cpuset_zone_allowed(struct zone *z)
+static inline int cpuset_zone_allowed(struct zone *z,
+                                       unsigned int __nocast gfp_mask)
+{
+       return 1;
+}
+
+static inline int cpuset_excl_nodes_overlap(const struct task_struct *p)
 {
        return 1;
 }
index 50be290d24d2705e92c17cdf4f6173e9702e581e..ab04b4f9b0db0e822dc08bc5a2abccdab32cadd3 100644 (file)
@@ -88,8 +88,9 @@ struct dentry {
                                         * negative */
        /*
         * The next three fields are touched by __d_lookup.  Place them here
-        * so they all fit in a 16-byte range, with 16-byte alignment.
+        * so they all fit in a cache line.
         */
+       struct hlist_node d_hash;       /* lookup hash list */
        struct dentry *d_parent;        /* parent directory */
        struct qstr d_name;
 
@@ -103,7 +104,6 @@ struct dentry {
        void *d_fsdata;                 /* fs-specific data */
        struct rcu_head d_rcu;
        struct dcookie_struct *d_cookie; /* cookie, if any */
-       struct hlist_node d_hash;       /* lookup hash list */  
        int d_mounted;
        unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* small names */
 };
index 5e93e6dce9a4751b7107d24e4e241a1eb1989651..c30175e8dec67fa39f7a7fb1bf753f4fa40d0dda 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __DMI_H__
 #define __DMI_H__
 
+#include <linux/list.h>
+
 enum dmi_field {
        DMI_NONE,
        DMI_BIOS_VENDOR,
@@ -16,6 +18,24 @@ enum dmi_field {
        DMI_STRING_MAX,
 };
 
+enum dmi_device_type {
+       DMI_DEV_TYPE_ANY = 0,
+       DMI_DEV_TYPE_OTHER,
+       DMI_DEV_TYPE_UNKNOWN,
+       DMI_DEV_TYPE_VIDEO,
+       DMI_DEV_TYPE_SCSI,
+       DMI_DEV_TYPE_ETHERNET,
+       DMI_DEV_TYPE_TOKENRING,
+       DMI_DEV_TYPE_SOUND,
+       DMI_DEV_TYPE_IPMI = -1
+};
+
+struct dmi_header {
+       u8 type;
+       u8 length;
+       u16 handle;
+};
+
 /*
  *     DMI callbacks for problem boards
  */
@@ -26,22 +46,32 @@ struct dmi_strmatch {
 
 struct dmi_system_id {
        int (*callback)(struct dmi_system_id *);
-       char *ident;
+       const char *ident;
        struct dmi_strmatch matches[4];
        void *driver_data;
 };
 
-#define DMI_MATCH(a,b) { a, b }
+#define DMI_MATCH(a, b)        { a, b }
+
+struct dmi_device {
+       struct list_head list;
+       int type;
+       const char *name;
+       void *device_data;      /* Type specific data */
+};
 
 #if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern char * dmi_get_system_info(int field);
-
+extern struct dmi_device * dmi_find_device(int type, const char *name,
+       struct dmi_device *from);
 #else
 
 static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
 static inline char * dmi_get_system_info(int field) { return NULL; }
+static struct dmi_device * dmi_find_device(int type, const char *name,
+       struct dmi_device *from) { return NULL; }
 
 #endif
 
index f5b3ba5a317df0c90af0a7513678fb9fd5a003cc..ff955dbf510d918503b2f634e85e55ed8bd150c5 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_ELF_H
 
 #include <linux/types.h>
+#include <linux/auxvec.h>
 #include <asm/elf.h>
 
 #ifndef elf_read_implies_exec
@@ -158,29 +159,6 @@ typedef __s64      Elf64_Sxword;
 #define ELF64_ST_BIND(x)       ELF_ST_BIND(x)
 #define ELF64_ST_TYPE(x)       ELF_ST_TYPE(x)
 
-/* Symbolic values for the entries in the auxiliary table
-   put on the initial stack */
-#define AT_NULL   0    /* end of vector */
-#define AT_IGNORE 1    /* entry should be ignored */
-#define AT_EXECFD 2    /* file descriptor of program */
-#define AT_PHDR   3    /* program headers for program */
-#define AT_PHENT  4    /* size of program header entry */
-#define AT_PHNUM  5    /* number of program headers */
-#define AT_PAGESZ 6    /* system page size */
-#define AT_BASE   7    /* base address of interpreter */
-#define AT_FLAGS  8    /* flags */
-#define AT_ENTRY  9    /* entry point of program */
-#define AT_NOTELF 10   /* program is not ELF */
-#define AT_UID    11   /* real uid */
-#define AT_EUID   12   /* effective uid */
-#define AT_GID    13   /* real gid */
-#define AT_EGID   14   /* effective gid */
-#define AT_PLATFORM 15  /* string identifying CPU for optimizations */
-#define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
-#define AT_CLKTCK 17   /* frequency at which times() increments */
-
-#define AT_SECURE 23   /* secure mode boolean */
-
 typedef struct dynamic{
   Elf32_Sword d_tag;
   union{
index a657130ba03ae576df96b8e6ec4539d64dc6df3f..f7bd1c7ebefbd2a116c4970608b6cfb3c341bf90 100644 (file)
@@ -313,6 +313,9 @@ struct ext2_inode {
 #define EXT2_MOUNT_XATTR_USER          0x004000  /* Extended user attributes */
 #define EXT2_MOUNT_POSIX_ACL           0x008000  /* POSIX Access Control Lists */
 #define EXT2_MOUNT_XIP                 0x010000  /* Execute in place */
+#define EXT2_MOUNT_USRQUOTA            0x020000 /* user quota */
+#define EXT2_MOUNT_GRPQUOTA            0x040000 /* group quota */
+
 
 #define clear_opt(o, opt)              o &= ~EXT2_MOUNT_##opt
 #define set_opt(o, opt)                        o |= EXT2_MOUNT_##opt
index c16662836c582230111f7237f916c96e0aeb6da7..c0272d73ab20a576dfc96c2291e7ab7c74076c48 100644 (file)
@@ -373,6 +373,8 @@ struct ext3_inode {
 #define EXT3_MOUNT_BARRIER             0x20000 /* Use block barriers */
 #define EXT3_MOUNT_NOBH                        0x40000 /* No bufferheads */
 #define EXT3_MOUNT_QUOTA               0x80000 /* Some quota option set */
+#define EXT3_MOUNT_USRQUOTA            0x100000 /* "old" user quota */
+#define EXT3_MOUNT_GRPQUOTA            0x200000 /* "old" group quota */
 
 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
index 886255b69bb9ada407534b9621398e2543006e2e..2063c0839d4fc3e0da2022d4303b4cce327e7d0e 100644 (file)
@@ -3,6 +3,9 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #define FIRMWARE_NAME_MAX 30 
+#define FW_ACTION_NOHOTPLUG 0
+#define FW_ACTION_HOTPLUG 1
+
 struct firmware {
        size_t size;
        u8 *data;
@@ -11,7 +14,7 @@ struct device;
 int request_firmware(const struct firmware **fw, const char *name,
                     struct device *device);
 int request_firmware_nowait(
-       struct module *module,
+       struct module *module, int hotplug,
        const char *name, struct device *device, void *context,
        void (*cont)(const struct firmware *fw, void *context));
 
index 67e6732d4fdc736ec39f4c57324e4d64064e063e..fd93ab7da905041938a7e59473d086d4657a152b 100644 (file)
@@ -69,6 +69,7 @@ extern int dir_notify_enable;
 #define READ 0
 #define WRITE 1
 #define READA 2                /* read-ahead  - don't block if no resources */
+#define SWRITE 3       /* for ll_rw_block() - wait for buffer lock */
 #define SPECIAL 4      /* For non-blockdevice requests in request queue */
 #define READ_SYNC      (READ | (1 << BIO_RW_SYNC))
 #define WRITE_SYNC     (WRITE | (1 << BIO_RW_SYNC))
@@ -281,18 +282,8 @@ struct iattr {
        struct timespec ia_atime;
        struct timespec ia_mtime;
        struct timespec ia_ctime;
-       unsigned int    ia_attr_flags;
 };
 
-/*
- * This is the inode attributes flag definitions
- */
-#define ATTR_FLAG_SYNCRONOUS   1       /* Syncronous write */
-#define ATTR_FLAG_NOATIME      2       /* Don't update atime */
-#define ATTR_FLAG_APPEND       4       /* Append-only file */
-#define ATTR_FLAG_IMMUTABLE    8       /* Immutable file */
-#define ATTR_FLAG_NODIRATIME   16      /* Don't update atime for directory */
-
 /*
  * Includes for diskquotas.
  */
@@ -594,7 +585,6 @@ struct file {
        unsigned int            f_uid, f_gid;
        struct file_ra_state    f_ra;
 
-       size_t                  f_maxcount;
        unsigned long           f_version;
        void                    *f_security;
 
@@ -1291,6 +1281,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
 /* fs/open.c */
 
 extern int do_truncate(struct dentry *, loff_t start);
+extern long do_sys_open(const char __user *filename, int flags, int mode);
 extern struct file *filp_open(const char *, int, int);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
 extern int filp_close(struct file *, fl_owner_t id);
index 65d6cfdb6d39c11098008268c6e97df7a3b5b462..10f96c31971ea30daf38c9226d656c0e993af3c0 100644 (file)
@@ -4,14 +4,40 @@
 /* Second argument to futex syscall */
 
 
-#define FUTEX_WAIT (0)
-#define FUTEX_WAKE (1)
-#define FUTEX_FD (2)
-#define FUTEX_REQUEUE (3)
-#define FUTEX_CMP_REQUEUE (4)
+#define FUTEX_WAIT             0
+#define FUTEX_WAKE             1
+#define FUTEX_FD               2
+#define FUTEX_REQUEUE          3
+#define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
 
 long do_futex(unsigned long uaddr, int op, int val,
                unsigned long timeout, unsigned long uaddr2, int val2,
                int val3);
 
+#define FUTEX_OP_SET           0       /* *(int *)UADDR2 = OPARG; */
+#define FUTEX_OP_ADD           1       /* *(int *)UADDR2 += OPARG; */
+#define FUTEX_OP_OR            2       /* *(int *)UADDR2 |= OPARG; */
+#define FUTEX_OP_ANDN          3       /* *(int *)UADDR2 &= ~OPARG; */
+#define FUTEX_OP_XOR           4       /* *(int *)UADDR2 ^= OPARG; */
+
+#define FUTEX_OP_OPARG_SHIFT   8       /* Use (1 << OPARG) instead of OPARG.  */
+
+#define FUTEX_OP_CMP_EQ                0       /* if (oldval == CMPARG) wake */
+#define FUTEX_OP_CMP_NE                1       /* if (oldval != CMPARG) wake */
+#define FUTEX_OP_CMP_LT                2       /* if (oldval < CMPARG) wake */
+#define FUTEX_OP_CMP_LE                3       /* if (oldval <= CMPARG) wake */
+#define FUTEX_OP_CMP_GT                4       /* if (oldval > CMPARG) wake */
+#define FUTEX_OP_CMP_GE                5       /* if (oldval >= CMPARG) wake */
+
+/* FUTEX_WAKE_OP will perform atomically
+   int oldval = *(int *)UADDR2;
+   *(int *)UADDR2 = oldval OP OPARG;
+   if (oldval CMP CMPARG)
+     wake UADDR2;  */
+
+#define FUTEX_OP(op, oparg, cmp, cmparg) \
+  (((op & 0xf) << 28) | ((cmp & 0xf) << 24)            \
+   | ((oparg & 0xfff) << 12) | (cmparg & 0xfff))
+
 #endif
index 7c7400137e97f11dffd425004321d1e675b802a0..4dc990f3b5ccea27bf5854d1e0f96e4367b4cb7c 100644 (file)
@@ -40,6 +40,7 @@ struct vm_area_struct;
 #define __GFP_ZERO     0x8000u /* Return zeroed page on success */
 #define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
 #define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */
+#define __GFP_HARDWALL   0x40000u /* Enforce hardwall cpuset memory allocs */
 
 #define __GFP_BITS_SHIFT 20    /* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -48,14 +49,15 @@ struct vm_area_struct;
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
                        __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
                        __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
-                       __GFP_NOMEMALLOC|__GFP_NORECLAIM)
+                       __GFP_NOMEMALLOC|__GFP_NORECLAIM|__GFP_HARDWALL)
 
 #define GFP_ATOMIC     (__GFP_HIGH)
 #define GFP_NOIO       (__GFP_WAIT)
 #define GFP_NOFS       (__GFP_WAIT | __GFP_IO)
 #define GFP_KERNEL     (__GFP_WAIT | __GFP_IO | __GFP_FS)
-#define GFP_USER       (__GFP_WAIT | __GFP_IO | __GFP_FS)
-#define GFP_HIGHUSER   (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM)
+#define GFP_USER       (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
+#define GFP_HIGHUSER   (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
+                        __GFP_HIGHMEM)
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
index 93bb3afe646bc315d1ce17849acdad149e9b8684..ee5b239092edbb03dee1765dd7919246bf4a2400 100644 (file)
@@ -47,6 +47,7 @@ struct inotify_event {
 #define IN_MOVE                        (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
 
 /* special flags */
+#define IN_MASK_ADD            0x20000000      /* add to the mask of an already existing watch */
 #define IN_ISDIR               0x40000000      /* event occurred against dir */
 #define IN_ONESHOT             0x80000000      /* only send event once */
 
index bdc53c6cc962ad78989fbbb0cfbac2a68cb57aa2..4767e5429534dff11c004923b5a3ee9827bcac50 100644 (file)
@@ -66,6 +66,7 @@ struct input_absinfo {
 #define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global keystate */
 #define EVIOCGLED(len)         _IOC(_IOC_READ, 'E', 0x19, len)         /* get all LEDs */
 #define EVIOCGSND(len)         _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
+#define EVIOCGSW(len)          _IOC(_IOC_READ, 'E', 0x1b, len)         /* get all switch states */
 
 #define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
 #define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)             /* get abs value/limits */
@@ -86,6 +87,7 @@ struct input_absinfo {
 #define EV_REL                 0x02
 #define EV_ABS                 0x03
 #define EV_MSC                 0x04
+#define EV_SW                  0x05
 #define EV_LED                 0x11
 #define EV_SND                 0x12
 #define EV_REP                 0x14
@@ -550,6 +552,20 @@ struct input_absinfo {
 #define ABS_MISC               0x28
 #define ABS_MAX                        0x3f
 
+/*
+ * Switch events
+ */
+
+#define SW_0           0x00
+#define SW_1           0x01
+#define SW_2           0x02
+#define SW_3           0x03
+#define SW_4           0x04
+#define SW_5           0x05
+#define SW_6           0x06
+#define SW_7           0x07
+#define SW_MAX         0x0f
+
 /*
  * Misc events
  */
@@ -824,6 +840,7 @@ struct input_dev {
        unsigned long ledbit[NBITS(LED_MAX)];
        unsigned long sndbit[NBITS(SND_MAX)];
        unsigned long ffbit[NBITS(FF_MAX)];
+       unsigned long swbit[NBITS(SW_MAX)];
        int ff_effects_max;
 
        unsigned int keycodemax;
@@ -844,6 +861,7 @@ struct input_dev {
        unsigned long key[NBITS(KEY_MAX)];
        unsigned long led[NBITS(LED_MAX)];
        unsigned long snd[NBITS(SND_MAX)];
+       unsigned long sw[NBITS(SW_MAX)];
 
        int absmax[ABS_MAX + 1];
        int absmin[ABS_MAX + 1];
@@ -886,6 +904,7 @@ struct input_dev {
 #define INPUT_DEVICE_ID_MATCH_LEDBIT   0x200
 #define INPUT_DEVICE_ID_MATCH_SNDBIT   0x400
 #define INPUT_DEVICE_ID_MATCH_FFBIT    0x800
+#define INPUT_DEVICE_ID_MATCH_SWBIT    0x1000
 
 #define INPUT_DEVICE_ID_MATCH_DEVICE\
        (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
@@ -906,6 +925,7 @@ struct input_device_id {
        unsigned long ledbit[NBITS(LED_MAX)];
        unsigned long sndbit[NBITS(SND_MAX)];
        unsigned long ffbit[NBITS(FF_MAX)];
+       unsigned long swbit[NBITS(SW_MAX)];
 
        unsigned long driver_info;
 };
@@ -998,6 +1018,11 @@ static inline void input_report_ff_status(struct input_dev *dev, unsigned int co
        input_event(dev, EV_FF_STATUS, code, value);
 }
 
+static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+       input_event(dev, EV_SW, code, !!value);
+}
+
 static inline void input_regs(struct input_dev *dev, struct pt_regs *regs)
 {
        dev->regs = regs;
index e8c4af32b3bb6ddcbd2005aa57a776d79216aef5..948809d999177867fb0820236f32e59a3d7ce52a 100644 (file)
@@ -14,26 +14,4 @@ struct ioctl_trans {
        struct ioctl_trans *next;
 };
 
-/* 
- * Register an 32bit ioctl translation handler for ioctl cmd.
- *
- * handler == NULL: use 64bit ioctl handler.
- * arguments to handler:  fd: file descriptor
- *                        cmd: ioctl command.
- *                        arg: ioctl argument
- *                        struct file *file: file descriptor pointer.
- */ 
-
-#ifdef CONFIG_COMPAT
-extern int __deprecated register_ioctl32_conversion(unsigned int cmd,
-                               ioctl_trans_handler_t handler);
-extern int __deprecated unregister_ioctl32_conversion(unsigned int cmd);
-
-#else
-
-#define register_ioctl32_conversion(cmd, handler)      ({ 0; })
-#define unregister_ioctl32_conversion(cmd)             ({ 0; })
-
-#endif
-
 #endif
index 596ca6130159f749036cf15860ba275c2122a6d3..938d55b813a5f600050fcc557331195b036fa12c 100644 (file)
@@ -35,6 +35,7 @@
 #define __LINUX_IPMI_H
 
 #include <linux/ipmi_msgdefs.h>
+#include <linux/compiler.h>
 
 /*
  * This file describes an interface to an IPMI driver.  You have to
@@ -241,7 +242,8 @@ struct ipmi_recv_msg
        /* The user_msg_data is the data supplied when a message was
           sent, if this is a response to a sent message.  If this is
           not a response to a sent message, then user_msg_data will
-          be NULL. */
+          be NULL.  If the user above is NULL, then this will be the
+          intf. */
        void             *user_msg_data;
 
        /* Call this when done with the message.  It will presumably free
@@ -298,13 +300,19 @@ void ipmi_get_version(ipmi_user_t   user,
    this user, so it will affect all users of this interface.  This is
    so some initialization code can come in and do the OEM-specific
    things it takes to determine your address (if not the BMC) and set
-   it for everyone else. */
-void ipmi_set_my_address(ipmi_user_t   user,
-                        unsigned char address);
-unsigned char ipmi_get_my_address(ipmi_user_t user);
-void ipmi_set_my_LUN(ipmi_user_t   user,
-                    unsigned char LUN);
-unsigned char ipmi_get_my_LUN(ipmi_user_t user);
+   it for everyone else.  Note that each channel can have its own address. */
+int ipmi_set_my_address(ipmi_user_t   user,
+                       unsigned int  channel,
+                       unsigned char address);
+int ipmi_get_my_address(ipmi_user_t   user,
+                       unsigned int  channel,
+                       unsigned char *address);
+int ipmi_set_my_LUN(ipmi_user_t   user,
+                   unsigned int  channel,
+                   unsigned char LUN);
+int ipmi_get_my_LUN(ipmi_user_t   user,
+                   unsigned int  channel,
+                   unsigned char *LUN);
 
 /*
  * Like ipmi_request, but lets you specify the number of retries and
@@ -585,6 +593,16 @@ struct ipmi_cmdspec
  * things it takes to determine your address (if not the BMC) and set
  * it for everyone else.  You should probably leave the LUN alone.
  */
+struct ipmi_channel_lun_address_set
+{
+       unsigned short channel;
+       unsigned char  value;
+};
+#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
+#define IPMICTL_SET_MY_CHANNEL_LUN_CMD    _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_LUN_CMD    _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
+/* Legacy interfaces, these only set IPMB 0. */
 #define IPMICTL_SET_MY_ADDRESS_CMD     _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
 #define IPMICTL_GET_MY_ADDRESS_CMD     _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
 #define IPMICTL_SET_MY_LUN_CMD         _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
index 069d3b84d311b442ffbbe2074733b78f5e894b7b..69681c3b1f05f8fac09efb8ad5334c60b65686c0 100644 (file)
 #define IRQ_WAITING    32      /* IRQ not yet seen - for autodetection */
 #define IRQ_LEVEL      64      /* IRQ level triggered */
 #define IRQ_MASKED     128     /* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU    256     /* IRQ is per CPU */
+#if defined(ARCH_HAS_IRQ_PER_CPU)
+# define IRQ_PER_CPU   256     /* IRQ is per CPU */
+# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
+#else
+# define CHECK_IRQ_PER_CPU(var) 0
+#endif
 
 /*
  * Interrupt controller descriptor. This is all we need
@@ -71,16 +76,139 @@ typedef struct irq_desc {
        unsigned int irq_count;         /* For detecting broken interrupts */
        unsigned int irqs_unhandled;
        spinlock_t lock;
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+       unsigned int move_irq;          /* Flag need to re-target intr dest*/
+#endif
 } ____cacheline_aligned irq_desc_t;
 
 extern irq_desc_t irq_desc [NR_IRQS];
 
+/* Return a pointer to the irq descriptor for IRQ.  */
+static inline irq_desc_t *
+irq_descp (int irq)
+{
+       return irq_desc + irq;
+}
+
 #include <asm/hw_irq.h> /* the arch dependent stuff */
 
 extern int setup_irq(unsigned int irq, struct irqaction * new);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 extern cpumask_t irq_affinity[NR_IRQS];
+
+#ifdef CONFIG_SMP
+static inline void set_native_irq_info(int irq, cpumask_t mask)
+{
+       irq_affinity[irq] = mask;
+}
+#else
+static inline void set_native_irq_info(int irq, cpumask_t mask)
+{
+}
+#endif
+
+#ifdef CONFIG_SMP
+
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+extern cpumask_t pending_irq_cpumask[NR_IRQS];
+
+static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
+{
+       irq_desc_t *desc = irq_desc + irq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       desc->move_irq = 1;
+       pending_irq_cpumask[irq] = mask;
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+static inline void
+move_native_irq(int irq)
+{
+       cpumask_t tmp;
+       irq_desc_t *desc = irq_descp(irq);
+
+       if (likely (!desc->move_irq))
+               return;
+
+       desc->move_irq = 0;
+
+       if (likely(cpus_empty(pending_irq_cpumask[irq])))
+               return;
+
+       if (!desc->handler->set_affinity)
+               return;
+
+       /* note - we hold the desc->lock */
+       cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+
+       /*
+        * If there was a valid mask to work with, please
+        * do the disable, re-program, enable sequence.
+        * This is *not* particularly important for level triggered
+        * but in a edge trigger case, we might be setting rte
+        * when an active trigger is comming in. This could
+        * cause some ioapics to mal-function.
+        * Being paranoid i guess!
+        */
+       if (unlikely(!cpus_empty(tmp))) {
+               desc->handler->disable(irq);
+               desc->handler->set_affinity(irq,tmp);
+               desc->handler->enable(irq);
+       }
+       cpus_clear(pending_irq_cpumask[irq]);
+}
+
+#ifdef CONFIG_PCI_MSI
+/*
+ * Wonder why these are dummies?
+ * For e.g the set_ioapic_affinity_vector() calls the set_ioapic_affinity_irq()
+ * counter part after translating the vector to irq info. We need to perform
+ * this operation on the real irq, when we dont use vector, i.e when
+ * pci_use_vector() is false.
+ */
+static inline void move_irq(int irq)
+{
+}
+
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+}
+
+#else // CONFIG_PCI_MSI
+
+static inline void move_irq(int irq)
+{
+       move_native_irq(irq);
+}
+
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+       set_native_irq_info(irq, mask);
+}
+#endif // CONFIG_PCI_MSI
+
+#else  // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE
+
+#define move_irq(x)
+#define move_native_irq(x)
+#define set_pending_irq(x,y)
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+       set_native_irq_info(irq, mask);
+}
+
+#endif // CONFIG_GENERIC_PENDING_IRQ
+
+#else // CONFIG_SMP
+
+#define move_irq(x)
+#define move_native_irq(x)
+
+#endif // CONFIG_SMP
+
 extern int no_irq_affinity;
 extern int noirqdebug_setup(char *str);
 
index 862083eb58ab2d6650b876576d2ddd9e81e162b2..53eaee96065bc0512370b866511c7b3ed4f11737 100644 (file)
@@ -150,7 +150,6 @@ typedef struct {
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
index 593407e865b1b0ce543f3bee6059b71452b32ede..84321a4cac93a1e942a4df994f28dbf44aeeec86 100644 (file)
@@ -914,7 +914,6 @@ extern int     journal_wipe       (journal_t *, int);
 extern int        journal_skip_recovery        (journal_t *);
 extern void       journal_update_superblock    (journal_t *, int);
 extern void       __journal_abort_hard (journal_t *);
-extern void       __journal_abort_soft (journal_t *, int);
 extern void       journal_abort      (journal_t *, int);
 extern int        journal_errno      (journal_t *);
 extern void       journal_ack_err    (journal_t *);
index e050fc2d4c26146fac9d289de9b2cfda5663e400..e30afdca79174f9a01b0b538dca138f62bf697f2 100644 (file)
@@ -42,6 +42,9 @@
 #define KPROBE_REENTER         0x00000004
 #define KPROBE_HIT_SSDONE      0x00000008
 
+/* Attach to insert probes on any functions which should be ignored*/
+#define __kprobes      __attribute__((__section__(".kprobes.text")))
+
 struct kprobe;
 struct pt_regs;
 struct kretprobe;
index 338f7795d8a071d63b05969505b6fe9894eafc46..147eb01e0d4bbe536da8bef077fac4ed8d9cdd37 100644 (file)
   ALIGN; \
   name:
 
+#define KPROBE_ENTRY(name) \
+  .section .kprobes.text, "ax"; \
+  .globl name; \
+  ALIGN; \
+  name:
+
+
 #endif
 
 #define NORET_TYPE    /**/
index aefedf04b9bb24384ed423b8876ee3a4d6219331..18fc77f682de8dcf629c83945c4595fd3cc0b82c 100644 (file)
@@ -33,6 +33,13 @@ struct mmc_csd {
        unsigned int            capacity;
 };
 
+struct sd_scr {
+       unsigned char           sda_vsn;
+       unsigned char           bus_widths;
+#define SD_SCR_BUS_WIDTH_1     (1<<0)
+#define SD_SCR_BUS_WIDTH_4     (1<<2)
+};
+
 struct mmc_host;
 
 /*
@@ -47,19 +54,27 @@ struct mmc_card {
 #define MMC_STATE_PRESENT      (1<<0)          /* present in sysfs */
 #define MMC_STATE_DEAD         (1<<1)          /* device no longer in stack */
 #define MMC_STATE_BAD          (1<<2)          /* unrecognised device */
+#define MMC_STATE_SDCARD       (1<<3)          /* is an SD card */
+#define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
+       u32                     raw_scr[2];     /* raw card SCR */
        struct mmc_cid          cid;            /* card identification */
        struct mmc_csd          csd;            /* card specific */
+       struct sd_scr           scr;            /* extra SD information */
 };
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_dead(c)       ((c)->state & MMC_STATE_DEAD)
 #define mmc_card_bad(c)                ((c)->state & MMC_STATE_BAD)
+#define mmc_card_sd(c)         ((c)->state & MMC_STATE_SDCARD)
+#define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)   ((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)    ((c)->state |= MMC_STATE_BAD)
+#define mmc_card_set_sd(c)     ((c)->state |= MMC_STATE_SDCARD)
+#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 
 #define mmc_card_name(c)       ((c)->cid.prod_name)
 #define mmc_card_id(c)         ((c)->dev.bus_id)
index 30f68c0c8c6ebfa5b3c2cfe9b51aca76c86159fa..6014160d9c0665acc497ade8b1236f93f1f4637a 100644 (file)
@@ -57,11 +57,17 @@ struct mmc_ios {
 #define MMC_POWER_OFF          0
 #define MMC_POWER_UP           1
 #define MMC_POWER_ON           2
+
+       unsigned char   bus_width;              /* data bus width */
+
+#define MMC_BUS_WIDTH_1                0
+#define MMC_BUS_WIDTH_4                2
 };
 
 struct mmc_host_ops {
        void    (*request)(struct mmc_host *host, struct mmc_request *req);
        void    (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
+       int     (*get_ro)(struct mmc_host *host);
 };
 
 struct mmc_card;
@@ -76,6 +82,10 @@ struct mmc_host {
        unsigned int            f_max;
        u32                     ocr_avail;
 
+       unsigned long           caps;           /* Host capabilities */
+
+#define MMC_CAP_4_BIT_DATA     (1 << 0)        /* Can the host do 4 bit transfers */
+
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
        unsigned short          max_hw_segs;    /* see blk_queue_max_hw_segments */
@@ -87,6 +97,10 @@ struct mmc_host {
        struct mmc_ios          ios;            /* current io bus settings */
        u32                     ocr;            /* the current OCR setting */
 
+       unsigned int            mode;           /* current card mode of host */
+#define MMC_MODE_MMC           0
+#define MMC_MODE_SD            1
+
        struct list_head        cards;          /* devices attached to this host */
 
        wait_queue_head_t       wq;
index 0d35d4ffb360d8def93506fa05fe99be852d1dc2..1ab78e8d6c530ac36c69c12038aea7112063a2d7 100644 (file)
@@ -88,6 +88,8 @@ struct mmc_card;
 
 extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
+       struct mmc_command *, int);
 
 extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
 
index 896342817b97bab2a7b20bb247115317224583fe..f819cae92266aa2fdd889d7bbe9b6480828d9680 100644 (file)
@@ -236,5 +236,12 @@ struct _mmc_csd {
 #define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
 #define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 */
 
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1      0
+#define SD_BUS_WIDTH_4      2
+
 #endif  /* MMC_MMC_PROTOCOL_H */
 
index 2c4c6aa643ff42f20217f88205ef55349b0c707f..903e0ab8101fad230721c7ecd27653b413a5d058 100644 (file)
@@ -77,6 +77,7 @@ struct msg_msg {
 /* one msq_queue structure for each present queue on the system */
 struct msg_queue {
        struct kern_ipc_perm q_perm;
+       int q_id;
        time_t q_stime;                 /* last msgsnd time */
        time_t q_rtime;                 /* last msgrcv time */
        time_t q_ctime;                 /* last change time */
index 088742befe4975dd3f9c08441c99da207f4aae20..7e033e9271a88efbb2b214e4834176147d33d28f 100644 (file)
@@ -263,6 +263,9 @@ struct ip_conntrack_expect
        /* Unique ID */
        unsigned int id;
 
+       /* Flags */
+       unsigned int flags;
+
 #ifdef CONFIG_IP_NF_NAT_NEEDED
        /* This is the original per-proto part, used to map the
         * expected connection the way the recipient expects. */
@@ -272,6 +275,8 @@ struct ip_conntrack_expect
 #endif
 };
 
+#define IP_CT_EXPECT_PERMANENT 0x1
+
 static inline struct ip_conntrack *
 tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
 {
index dc4d2a0575de9c666ac45428b81d47e634ac1805..907d4f5ca5dc50f2384ad69730f8c5686e085cf1 100644 (file)
@@ -52,7 +52,7 @@ static inline int ip_conntrack_confirm(struct sk_buff **pskb)
        return ret;
 }
 
-extern void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp);
+extern void ip_ct_unlink_expect(struct ip_conntrack_expect *exp);
 
 extern struct list_head *ip_conntrack_hash;
 extern struct list_head ip_conntrack_expect_list;
index fecd2a06dcd81166c8fd2037e57bd4d5c3d22ccd..73b9552e6a8941eea8c3c30ba74c9bb96ad69c2e 100644 (file)
@@ -19,5 +19,10 @@ extern unsigned int
 alloc_null_binding(struct ip_conntrack *conntrack,
                   struct ip_nat_info *info,
                   unsigned int hooknum);
+
+extern unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+                            struct ip_nat_info *info,
+                            unsigned int hooknum);
 #endif
 #endif /* _IP_NAT_RULE_H */
index 36725e7c02c69494222719d1aa334dc5da258c94..1767073df26fe03720176c080d13908ade41f291 100644 (file)
@@ -39,9 +39,6 @@ struct pipe_inode_info {
 
 #define PIPE_SEM(inode)                (&(inode).i_sem)
 #define PIPE_WAIT(inode)       (&(inode).i_pipe->wait)
-#define PIPE_BASE(inode)       ((inode).i_pipe->base)
-#define PIPE_START(inode)      ((inode).i_pipe->start)
-#define PIPE_LEN(inode)                ((inode).i_pipe->len)
 #define PIPE_READERS(inode)    ((inode).i_pipe->readers)
 #define PIPE_WRITERS(inode)    ((inode).i_pipe->writers)
 #define PIPE_WAITING_WRITERS(inode)    ((inode).i_pipe->waiting_writers)
index 5ec2bd0c28483c0011de79920011fe3aaa4bc2d1..aadbac29103cfc7601291e8fc0415f46d6cafc85 100644 (file)
@@ -443,7 +443,7 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
 #define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
 #define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg)
 
-#ifdef DEBUG
+#ifdef CONFIG_PNP_DEBUG
 #define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg)
 #else
 #define pnp_dbg(format, arg...) do {} while (0)
index 2afdafb62123c212d0b6366a210078d38760ba81..dc6f3647bfbc01cfcfca8192d631b12d4c9bdd80 100644 (file)
@@ -90,6 +90,7 @@ extern void __ptrace_link(struct task_struct *child,
                          struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
 extern void ptrace_untrace(struct task_struct *child);
+extern int ptrace_may_attach(struct task_struct *task);
 
 static inline void ptrace_link(struct task_struct *child,
                               struct task_struct *new_parent)
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
new file mode 100644 (file)
index 0000000..cfafc3e
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * linux/include/linux/relayfs_fs.h
+ *
+ * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
+ * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
+ *
+ * RelayFS definitions and declarations
+ */
+
+#ifndef _LINUX_RELAYFS_FS_H
+#define _LINUX_RELAYFS_FS_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/kref.h>
+
+/*
+ * Tracks changes to rchan_buf struct
+ */
+#define RELAYFS_CHANNEL_VERSION                5
+
+/*
+ * Per-cpu relay channel buffer
+ */
+struct rchan_buf
+{
+       void *start;                    /* start of channel buffer */
+       void *data;                     /* start of current sub-buffer */
+       size_t offset;                  /* current offset into sub-buffer */
+       size_t subbufs_produced;        /* count of sub-buffers produced */
+       size_t subbufs_consumed;        /* count of sub-buffers consumed */
+       struct rchan *chan;             /* associated channel */
+       wait_queue_head_t read_wait;    /* reader wait queue */
+       struct work_struct wake_readers; /* reader wake-up work struct */
+       struct dentry *dentry;          /* channel file dentry */
+       struct kref kref;               /* channel buffer refcount */
+       struct page **page_array;       /* array of current buffer pages */
+       unsigned int page_count;        /* number of current buffer pages */
+       unsigned int finalized;         /* buffer has been finalized */
+       size_t *padding;                /* padding counts per sub-buffer */
+       size_t prev_padding;            /* temporary variable */
+       size_t bytes_consumed;          /* bytes consumed in cur read subbuf */
+       unsigned int cpu;               /* this buf's cpu */
+} ____cacheline_aligned;
+
+/*
+ * Relay channel data structure
+ */
+struct rchan
+{
+       u32 version;                    /* the version of this struct */
+       size_t subbuf_size;             /* sub-buffer size */
+       size_t n_subbufs;               /* number of sub-buffers per buffer */
+       size_t alloc_size;              /* total buffer size allocated */
+       struct rchan_callbacks *cb;     /* client callbacks */
+       struct kref kref;               /* channel refcount */
+       void *private_data;             /* for user-defined data */
+       struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
+};
+
+/*
+ * Relayfs inode
+ */
+struct relayfs_inode_info
+{
+       struct inode vfs_inode;
+       struct rchan_buf *buf;
+};
+
+static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode)
+{
+       return container_of(inode, struct relayfs_inode_info, vfs_inode);
+}
+
+/*
+ * Relay channel client callbacks
+ */
+struct rchan_callbacks
+{
+       /*
+        * subbuf_start - called on buffer-switch to a new sub-buffer
+        * @buf: the channel buffer containing the new sub-buffer
+        * @subbuf: the start of the new sub-buffer
+        * @prev_subbuf: the start of the previous sub-buffer
+        * @prev_padding: unused space at the end of previous sub-buffer
+        *
+        * The client should return 1 to continue logging, 0 to stop
+        * logging.
+        *
+        * NOTE: subbuf_start will also be invoked when the buffer is
+        *       created, so that the first sub-buffer can be initialized
+        *       if necessary.  In this case, prev_subbuf will be NULL.
+        *
+        * NOTE: the client can reserve bytes at the beginning of the new
+        *       sub-buffer by calling subbuf_start_reserve() in this callback.
+        */
+       int (*subbuf_start) (struct rchan_buf *buf,
+                            void *subbuf,
+                            void *prev_subbuf,
+                            size_t prev_padding);
+
+       /*
+        * buf_mapped - relayfs buffer mmap notification
+        * @buf: the channel buffer
+        * @filp: relayfs file pointer
+        *
+        * Called when a relayfs file is successfully mmapped
+        */
+        void (*buf_mapped)(struct rchan_buf *buf,
+                          struct file *filp);
+
+       /*
+        * buf_unmapped - relayfs buffer unmap notification
+        * @buf: the channel buffer
+        * @filp: relayfs file pointer
+        *
+        * Called when a relayfs file is successfully unmapped
+        */
+        void (*buf_unmapped)(struct rchan_buf *buf,
+                            struct file *filp);
+};
+
+/*
+ * relayfs kernel API, fs/relayfs/relay.c
+ */
+
+struct rchan *relay_open(const char *base_filename,
+                        struct dentry *parent,
+                        size_t subbuf_size,
+                        size_t n_subbufs,
+                        struct rchan_callbacks *cb);
+extern void relay_close(struct rchan *chan);
+extern void relay_flush(struct rchan *chan);
+extern void relay_subbufs_consumed(struct rchan *chan,
+                                  unsigned int cpu,
+                                  size_t consumed);
+extern void relay_reset(struct rchan *chan);
+extern int relay_buf_full(struct rchan_buf *buf);
+
+extern size_t relay_switch_subbuf(struct rchan_buf *buf,
+                                 size_t length);
+extern struct dentry *relayfs_create_dir(const char *name,
+                                        struct dentry *parent);
+extern int relayfs_remove_dir(struct dentry *dentry);
+
+/**
+ *     relay_write - write data into the channel
+ *     @chan: relay channel
+ *     @data: data to be written
+ *     @length: number of bytes to write
+ *
+ *     Writes data into the current cpu's channel buffer.
+ *
+ *     Protects the buffer by disabling interrupts.  Use this
+ *     if you might be logging from interrupt context.  Try
+ *     __relay_write() if you know you won't be logging from
+ *     interrupt context.
+ */
+static inline void relay_write(struct rchan *chan,
+                              const void *data,
+                              size_t length)
+{
+       unsigned long flags;
+       struct rchan_buf *buf;
+
+       local_irq_save(flags);
+       buf = chan->buf[smp_processor_id()];
+       if (unlikely(buf->offset + length > chan->subbuf_size))
+               length = relay_switch_subbuf(buf, length);
+       memcpy(buf->data + buf->offset, data, length);
+       buf->offset += length;
+       local_irq_restore(flags);
+}
+
+/**
+ *     __relay_write - write data into the channel
+ *     @chan: relay channel
+ *     @data: data to be written
+ *     @length: number of bytes to write
+ *
+ *     Writes data into the current cpu's channel buffer.
+ *
+ *     Protects the buffer by disabling preemption.  Use
+ *     relay_write() if you might be logging from interrupt
+ *     context.
+ */
+static inline void __relay_write(struct rchan *chan,
+                                const void *data,
+                                size_t length)
+{
+       struct rchan_buf *buf;
+
+       buf = chan->buf[get_cpu()];
+       if (unlikely(buf->offset + length > buf->chan->subbuf_size))
+               length = relay_switch_subbuf(buf, length);
+       memcpy(buf->data + buf->offset, data, length);
+       buf->offset += length;
+       put_cpu();
+}
+
+/**
+ *     relay_reserve - reserve slot in channel buffer
+ *     @chan: relay channel
+ *     @length: number of bytes to reserve
+ *
+ *     Returns pointer to reserved slot, NULL if full.
+ *
+ *     Reserves a slot in the current cpu's channel buffer.
+ *     Does not protect the buffer at all - caller must provide
+ *     appropriate synchronization.
+ */
+static inline void *relay_reserve(struct rchan *chan, size_t length)
+{
+       void *reserved;
+       struct rchan_buf *buf = chan->buf[smp_processor_id()];
+
+       if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
+               length = relay_switch_subbuf(buf, length);
+               if (!length)
+                       return NULL;
+       }
+       reserved = buf->data + buf->offset;
+       buf->offset += length;
+
+       return reserved;
+}
+
+/**
+ *     subbuf_start_reserve - reserve bytes at the start of a sub-buffer
+ *     @buf: relay channel buffer
+ *     @length: number of bytes to reserve
+ *
+ *     Helper function used to reserve bytes at the beginning of
+ *     a sub-buffer in the subbuf_start() callback.
+ */
+static inline void subbuf_start_reserve(struct rchan_buf *buf,
+                                       size_t length)
+{
+       BUG_ON(length >= buf->chan->subbuf_size - 1);
+       buf->offset = length;
+}
+
+/*
+ * exported relayfs file operations, fs/relayfs/inode.c
+ */
+
+extern struct file_operations relayfs_file_operations;
+
+#endif /* _LINUX_RELAYFS_FS_H */
+
index dec5827c77422ebbd8e7f0238cdf7f34e08cb906..ea1b5f32ec5c1952cbf254f4563d7d707a85e155 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/topology.h>
 #include <linux/seccomp.h>
 
+#include <linux/auxvec.h>      /* For AT_VECTOR_SIZE */
+
 struct exec_domain;
 
 /*
@@ -176,6 +178,23 @@ extern void trap_init(void);
 extern void update_process_times(int user);
 extern void scheduler_tick(void);
 
+#ifdef CONFIG_DETECT_SOFTLOCKUP
+extern void softlockup_tick(struct pt_regs *regs);
+extern void spawn_softlockup_task(void);
+extern void touch_softlockup_watchdog(void);
+#else
+static inline void softlockup_tick(struct pt_regs *regs)
+{
+}
+static inline void spawn_softlockup_task(void)
+{
+}
+static inline void touch_softlockup_watchdog(void)
+{
+}
+#endif
+
+
 /* Attach to any functions which should be ignored in wchan output. */
 #define __sched                __attribute__((__section__(".sched.text")))
 /* Is this address in the __sched functions? */
@@ -244,7 +263,7 @@ struct mm_struct {
        mm_counter_t _rss;
        mm_counter_t _anon_rss;
 
-       unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
+       unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
 
        unsigned dumpable:2;
        cpumask_t cpu_vm_mask;
@@ -545,13 +564,6 @@ struct sched_domain {
 
 extern void partition_sched_domains(cpumask_t *partition1,
                                    cpumask_t *partition2);
-#ifdef ARCH_HAS_SCHED_DOMAIN
-/* Useful helpers that arch setup code may use. Defined in kernel/sched.c */
-extern cpumask_t cpu_isolated_map;
-extern void init_sched_build_groups(struct sched_group groups[],
-                               cpumask_t span, int (*group_fn)(int cpu));
-extern void cpu_attach_domain(struct sched_domain *sd, int cpu);
-#endif /* ARCH_HAS_SCHED_DOMAIN */
 #endif /* CONFIG_SMP */
 
 
index 2d8516be9fd7f71aac09b09076f2a04e2d37cc9f..106f9757339a54aeffc52a440129b5827040c8c1 100644 (file)
@@ -88,6 +88,7 @@ struct sem {
 /* One sem_array data structure for each set of semaphores in the system. */
 struct sem_array {
        struct kern_ipc_perm    sem_perm;       /* permissions .. see ipc.h */
+       int                     sem_id;
        time_t                  sem_otime;      /* last semop time */
        time_t                  sem_ctime;      /* last change time */
        struct sem              *sem_base;      /* ptr to first semaphore in array */
index cf0f64ea2bc0d36eb742c41c7db0e966525a0685..9b12fe731612dfd2ccb1665278dd5416e2e509f3 100644 (file)
@@ -385,11 +385,11 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port);
 /*
  * The following are helper functions for the low level drivers.
  */
-#ifdef SUPPORT_SYSRQ
 static inline int
 uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
                       struct pt_regs *regs)
 {
+#ifdef SUPPORT_SYSRQ
        if (port->sysrq) {
                if (ch && time_before(jiffies, port->sysrq)) {
                        handle_sysrq(ch, regs, NULL);
@@ -398,11 +398,9 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
                }
                port->sysrq = 0;
        }
+#endif
        return 0;
 }
-#else
-#define uart_handle_sysrq_char(port,ch,regs)   (0)
-#endif
 
 /*
  * We do the SysRQ and SAK checking like this...
index 42edce6abe2349fc428c6321f81af81578ca5cb2..da7da9c0ed1b50e1f8dac7c08b919c104c287e30 100644 (file)
@@ -1251,7 +1251,7 @@ extern void skb_add_mtu(int mtu);
  *     This function converts the offset back to a struct timeval and stores
  *     it in stamp.
  */
-static inline void skb_get_timestamp(struct sk_buff *skb, struct timeval *stamp)
+static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp)
 {
        stamp->tv_sec  = skb->tstamp.off_sec;
        stamp->tv_usec = skb->tstamp.off_usec;
@@ -1270,7 +1270,7 @@ static inline void skb_get_timestamp(struct sk_buff *skb, struct timeval *stamp)
  *     This function converts a struct timeval to an offset and stores
  *     it in the skb.
  */
-static inline void skb_set_timestamp(struct sk_buff *skb, struct timeval *stamp)
+static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
 {
        skb->tstamp.off_sec  = stamp->tv_sec - skb_tv_base.tv_sec;
        skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec;
index 80b2dfde2e8087d84ec06f945f3fa4a61ece4f55..42a6bea58af369f4408eba0cf020dbc6d74352eb 100644 (file)
@@ -99,7 +99,21 @@ found:
        return __kmalloc(size, flags);
 }
 
-extern void *kcalloc(size_t, size_t, unsigned int __nocast);
+extern void *kzalloc(size_t, unsigned int __nocast);
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+static inline void *kcalloc(size_t n, size_t size, unsigned int __nocast flags)
+{
+       if (n != 0 && size > INT_MAX / n)
+               return NULL;
+       return kzalloc(n * size, flags);
+}
+
 extern void kfree(const void *);
 extern unsigned int ksize(const void *);
 
index 768cbba617d02533388270a1a0e1795752d15cb6..f56d2473495004a6958b95fc5a07b54f28a5aba8 100644 (file)
@@ -99,6 +99,8 @@
 #define SONYPI_EVENT_BATTERY_INSERT            57
 #define SONYPI_EVENT_BATTERY_REMOVE            58
 #define SONYPI_EVENT_FNKEY_RELEASED            59
+#define SONYPI_EVENT_WIRELESS_ON               60
+#define SONYPI_EVENT_WIRELESS_OFF              61
 
 /* get/set brightness */
 #define SONYPI_IOCGBRT         _IOR('v', 0, __u8)
index 6864063d1b9f0c6638a2c7fa94f525536179e522..c4e3ea7cf1545e5da79e504c8fabddbc1f4a8d87 100644 (file)
@@ -60,6 +60,7 @@ struct cache_head {
 #define        CACHE_NEW_EXPIRY 120    /* keep new things pending confirmation for 120 seconds */
 
 struct cache_detail {
+       struct module *         owner;
        int                     hash_size;
        struct cache_head **    hash_table;
        rwlock_t                hash_lock;
index e82be96d4906654bbb91e9c8fbf0a8ab7696d713..532a6c5c24e9cc105b30accf34f4a6e792967988 100644 (file)
@@ -711,6 +711,7 @@ enum {
        DEV_RAID=4,
        DEV_MAC_HID=5,
        DEV_SCSI=6,
+       DEV_IPMI=7,
 };
 
 /* /proc/sys/dev/cdrom */
@@ -776,6 +777,11 @@ enum {
        DEV_SCSI_LOGGING_LEVEL=1,
 };
 
+/* /proc/sys/dev/ipmi */
+enum {
+       DEV_IPMI_POWEROFF_POWERCYCLE=1,
+};
+
 /* /proc/sys/abi */
 enum
 {
index 5634497ff5dfd62a7e5327dd7a8fbd95cb467698..c10d4c21c18397cd3bfe66ea83d173d89a5d85b2 100644 (file)
@@ -97,7 +97,6 @@ extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
 extern void clock_was_set(void); // call when ever the clock is set
 extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
-extern long do_nanosleep(struct timespec *t);
 extern long do_utimes(char __user * filename, struct timeval * times);
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
index 74fdd07d3792a55cf970c9a1ad4942511976adf7..7e050a2cc35be69f2685309ff9c445adbba8ae68 100644 (file)
@@ -260,6 +260,29 @@ extern long pps_calcnt;            /* calibration intervals */
 extern long pps_errcnt;                /* calibration errors */
 extern long pps_stbcnt;                /* stability limit exceeded */
 
+/**
+ * ntp_clear - Clears the NTP state variables
+ *
+ * Must be called while holding a write on the xtime_lock
+ */
+static inline void ntp_clear(void)
+{
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+}
+
+/**
+ * ntp_synced - Returns 1 if the NTP status is not UNSYNC
+ *
+ */
+static inline int ntp_synced(void)
+{
+       return !(time_status & STA_UNSYNC);
+}
+
+
 #ifdef CONFIG_TIME_INTERPOLATION
 
 #define TIME_SOURCE_CPU 0
index 0320225e96da5b6b24bc5e3d5107fc55527e6aab..3df1d474e5c56dcd4ce2ca4d371ad86fc945368b 100644 (file)
 }
 #endif
 
+/* sched_domains SD_ALLNODES_INIT for NUMA machines */
+#define SD_ALLNODES_INIT (struct sched_domain) {       \
+       .span                   = CPU_MASK_NONE,        \
+       .parent                 = NULL,                 \
+       .groups                 = NULL,                 \
+       .min_interval           = 64,                   \
+       .max_interval           = 64*num_online_cpus(), \
+       .busy_factor            = 128,                  \
+       .imbalance_pct          = 133,                  \
+       .cache_hot_time         = (10*1000000),         \
+       .cache_nice_tries       = 1,                    \
+       .busy_idx               = 3,                    \
+       .idle_idx               = 3,                    \
+       .newidle_idx            = 0, /* unused */       \
+       .wake_idx               = 0, /* unused */       \
+       .forkexec_idx           = 0, /* unused */       \
+       .per_cpu_gain           = 100,                  \
+       .flags                  = SD_LOAD_BALANCE,      \
+       .last_balance           = jiffies,              \
+       .balance_interval       = 64,                   \
+       .nr_balance_failed      = 0,                    \
+}
+
 #ifdef CONFIG_NUMA
 #ifndef SD_NODE_INIT
 #error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
index 926eed543023906328aa7a95908d9e54039bfc2c..364b046e9f478b545316236d592bf29039c3fad2 100644 (file)
@@ -257,7 +257,7 @@ extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
 
 /* ax25_addr.c */
 extern ax25_address null_ax25_address;
-extern char *ax2asc(ax25_address *);
+extern char *ax2asc(char *buf, ax25_address *);
 extern ax25_address *asc2ax(char *);
 extern int  ax25cmp(ax25_address *, ax25_address *);
 extern int  ax25digicmp(ax25_digi *, ax25_digi *);
index f72b3ef515e25e7d8ca1ee64f7f063a7b8d84f9f..3dc41fd5c54d46730d39c01967c93d05e5b48b32 100644 (file)
@@ -291,12 +291,14 @@ void snd_memory_done(void);
 int snd_memory_info_init(void);
 int snd_memory_info_done(void);
 void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags);
+void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags);
 void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags);
 void snd_hidden_kfree(const void *obj);
 void *snd_hidden_vmalloc(unsigned long size);
 void snd_hidden_vfree(void *obj);
 char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags);
 #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
+#define kzalloc(size, flags) snd_hidden_kzalloc(size, flags)
 #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
 #define kfree(obj) snd_hidden_kfree(obj)
 #define vmalloc(size) snd_hidden_vmalloc(size)
index bd548c2b47c4f0376960b3fabc41634354d29b0d..e6da2d7ded8cfa7a0a5c1d16ae1e732b98af996a 100644 (file)
 /*
  *  Support for the w100 frame buffer.
  *
- *  Copyright (c) 2004 Richard Purdie
+ *  Copyright (c) 2004-2005 Richard Purdie
+ *  Copyright (c) 2005 Ian Molton
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
 
+#define W100_GPIO_PORT_A       0
+#define W100_GPIO_PORT_B       1
+
+#define CLK_SRC_XTAL  0
+#define CLK_SRC_PLL   1
+
+struct w100fb_par;
+
+unsigned long w100fb_gpio_read(int port);
+void w100fb_gpio_write(int port, unsigned long value);
+
+/* LCD Specific Routines and Config */
+struct w100_tg_info {
+       void (*change)(struct w100fb_par*);
+       void (*suspend)(struct w100fb_par*);
+       void (*resume)(struct w100fb_par*);
+};
+
+/* General Platform Specific w100 Register Values */
+struct w100_gen_regs {
+       unsigned long lcd_format;
+       unsigned long lcdd_cntl1;
+       unsigned long lcdd_cntl2;
+       unsigned long genlcd_cntl1;
+       unsigned long genlcd_cntl2;
+       unsigned long genlcd_cntl3;
+};
+
+struct w100_gpio_regs {
+       unsigned long init_data1;
+       unsigned long init_data2;
+       unsigned long gpio_dir1;
+       unsigned long gpio_oe1;
+       unsigned long gpio_dir2;
+       unsigned long gpio_oe2;
+};
+
+/* Optional External Memory Configuration */
+struct w100_mem_info {
+       unsigned long ext_cntl;
+       unsigned long sdram_mode_reg;
+       unsigned long ext_timing_cntl;
+       unsigned long io_cntl;
+       unsigned int size;
+};
+
+struct w100_bm_mem_info {
+       unsigned long ext_mem_bw;
+       unsigned long offset;
+       unsigned long ext_timing_ctl;
+       unsigned long ext_cntl;
+       unsigned long mode_reg;
+       unsigned long io_cntl;
+       unsigned long config;
+};
+
+/* LCD Mode definition */
+struct w100_mode {
+       unsigned int xres;
+       unsigned int yres;
+       unsigned short left_margin;
+       unsigned short right_margin;
+       unsigned short upper_margin;
+       unsigned short lower_margin;
+       unsigned long crtc_ss;
+       unsigned long crtc_ls;
+       unsigned long crtc_gs;
+       unsigned long crtc_vpos_gs;
+       unsigned long crtc_rev;
+       unsigned long crtc_dclk;
+       unsigned long crtc_gclk;
+       unsigned long crtc_goe;
+       unsigned long crtc_ps1_active;
+       char pll_freq;
+       char fast_pll_freq;
+       int sysclk_src;
+       int sysclk_divider;
+       int pixclk_src;
+       int pixclk_divider;
+       int pixclk_divider_rotated;
+};
+
+struct w100_pll_info {
+       uint16_t freq;  /* desired Fout for PLL (Mhz) */
+       uint8_t M;      /* input divider */
+       uint8_t N_int;  /* VCO multiplier */
+       uint8_t N_fac;  /* VCO multiplier fractional part */
+       uint8_t tfgoal;
+       uint8_t lock_time;
+};
+
+/* Initial Video mode orientation flags */
+#define INIT_MODE_ROTATED  0x1
+#define INIT_MODE_FLIPPED  0x2
+
 /*
  * This structure describes the machine which we are running on.
  * It is set by machine specific code and used in the probe routine
  * of drivers/video/w100fb.c
  */
-
 struct w100fb_mach_info {
-       void (*w100fb_ssp_send)(u8 adrs, u8 data);
-       int comadj;
-       int phadadj;
+       /* General Platform Specific Registers */
+       struct w100_gen_regs *regs;
+       /* Table of modes the LCD is capable of */
+       struct w100_mode *modelist;
+       unsigned int num_modes;
+       /* Hooks for any platform specific tg/lcd code (optional) */
+       struct w100_tg_info *tg;
+       /* External memory definition (if present) */
+       struct w100_mem_info *mem;
+       /* Additional External memory definition (if present) */
+       struct w100_bm_mem_info *bm_mem;
+       /* GPIO definitions (optional) */
+       struct w100_gpio_regs *gpio;
+       /* Initial Mode flags */
+       unsigned int init_mode;
+       /* Xtal Frequency */
+       unsigned int xtal_freq;
+       /* Enable Xtal input doubler (1 == enable) */
+       unsigned int xtal_dbl;
+};
+
+/* General frame buffer data structure */
+struct w100fb_par {
+       unsigned int chip_id;
+       unsigned int xres;
+       unsigned int yres;
+       unsigned int extmem_active;
+       unsigned int flip;
+       unsigned int blanked;
+       unsigned int fastpll_mode;
+       unsigned long hsync_len;
+       struct w100_mode *mode;
+       struct w100_pll_info *pll_table;
+       struct w100fb_mach_info *mach;
+       uint32_t *saved_intmem;
+       uint32_t *saved_extmem;
 };
index ff410063e4e13ca6a296a680a136a15297d079de..f142d403534190f4588b3d7eda585112077e0607 100644 (file)
@@ -123,6 +123,7 @@ extern void softirq_init(void);
 char saved_command_line[COMMAND_LINE_SIZE];
 
 static char *execute_command;
+static char *ramdisk_execute_command;
 
 /* Setup configured maximum number of CPUs to activate */
 static unsigned int max_cpus = NR_CPUS;
@@ -297,6 +298,18 @@ static int __init init_setup(char *str)
 }
 __setup("init=", init_setup);
 
+static int __init rdinit_setup(char *str)
+{
+       unsigned int i;
+
+       ramdisk_execute_command = str;
+       /* See "auto" comment in init_setup */
+       for (i = 1; i < MAX_INIT_ARGS; i++)
+               argv_init[i] = NULL;
+       return 1;
+}
+__setup("rdinit=", rdinit_setup);
+
 extern void setup_arch(char **);
 
 #ifndef CONFIG_SMP
@@ -614,6 +627,7 @@ static void do_pre_smp_initcalls(void)
        migration_init();
 #endif
        spawn_ksoftirqd();
+       spawn_softlockup_task();
 }
 
 static void run_init_process(char *init_filename)
@@ -680,10 +694,14 @@ static int init(void * unused)
         * check if there is an early userspace init.  If yes, let it do all
         * the work
         */
-       if (sys_access((const char __user *) "/init", 0) == 0)
-               execute_command = "/init";
-       else
+
+       if (!ramdisk_execute_command)
+               ramdisk_execute_command = "/init";
+
+       if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
+               ramdisk_execute_command = NULL;
                prepare_namespace();
+       }
 
        /*
         * Ok, we have completed the initial bootup, and
@@ -700,17 +718,24 @@ static int init(void * unused)
 
        (void) sys_dup(0);
        (void) sys_dup(0);
-       
+
+       if (ramdisk_execute_command) {
+               run_init_process(ramdisk_execute_command);
+               printk(KERN_WARNING "Failed to execute %s\n",
+                               ramdisk_execute_command);
+       }
+
        /*
         * We try each of these until one succeeds.
         *
         * The Bourne shell can be used instead of init if we are 
         * trying to recover a really broken machine.
         */
-
-       if (execute_command)
+       if (execute_command) {
                run_init_process(execute_command);
-
+               printk(KERN_WARNING "Failed to execute %s.  Attempting "
+                                       "defaults...\n", execute_command);
+       }
        run_init_process("/sbin/init");
        run_init_process("/etc/init");
        run_init_process("/bin/init");
index 3881d564c66837ad6a925ae7a43e429cf30cd482..1fe95f6659dd2b25cc28920051658f288a935f82 100644 (file)
@@ -42,10 +42,10 @@ struct compat_msgbuf {
 
 struct compat_ipc_perm {
        key_t key;
-       compat_uid_t uid;
-       compat_gid_t gid;
-       compat_uid_t cuid;
-       compat_gid_t cgid;
+       __compat_uid_t uid;
+       __compat_gid_t gid;
+       __compat_uid_t cuid;
+       __compat_gid_t cgid;
        compat_mode_t mode;
        unsigned short seq;
 };
@@ -174,8 +174,8 @@ static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
                                        struct compat_ipc_perm __user *up)
 {
        int err;
-       compat_uid_t u;
-       compat_gid_t g;
+       __compat_uid_t u;
+       __compat_gid_t g;
 
        err  = __put_user(p->key, &up->key);
        SET_UID(u, p->uid);
index 27e516f96cdc7c3907b7b25243ff1e4cd786a8e0..d035bd2aba9671cc56fdd6f10b81182ac628b011 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
+#include <linux/seq_file.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 #include "util.h"
@@ -74,16 +75,16 @@ static struct ipc_ids msg_ids;
 static void freeque (struct msg_queue *msq, int id);
 static int newque (key_t key, int msgflg);
 #ifdef CONFIG_PROC_FS
-static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
 void __init msg_init (void)
 {
        ipc_init_ids(&msg_ids,msg_ctlmni);
-
-#ifdef CONFIG_PROC_FS
-       create_proc_read_entry("sysvipc/msg", 0, NULL, sysvipc_msg_read_proc, NULL);
-#endif
+       ipc_init_proc_interface("sysvipc/msg",
+                               "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
+                               &msg_ids,
+                               sysvipc_msg_proc_show);
 }
 
 static int newque (key_t key, int msgflg)
@@ -113,6 +114,7 @@ static int newque (key_t key, int msgflg)
                return -ENOSPC;
        }
 
+       msq->q_id = msg_buildid(id,msq->q_perm.seq);
        msq->q_stime = msq->q_rtime = 0;
        msq->q_ctime = get_seconds();
        msq->q_cbytes = msq->q_qnum = 0;
@@ -123,7 +125,7 @@ static int newque (key_t key, int msgflg)
        INIT_LIST_HEAD(&msq->q_senders);
        msg_unlock(msq);
 
-       return msg_buildid(id,msq->q_perm.seq);
+       return msq->q_id;
 }
 
 static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss)
@@ -808,55 +810,25 @@ out_unlock:
 }
 
 #ifdef CONFIG_PROC_FS
-static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 {
-       off_t pos = 0;
-       off_t begin = 0;
-       int i, len = 0;
-
-       down(&msg_ids.sem);
-       len += sprintf(buffer, "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n");
-
-       for(i = 0; i <= msg_ids.max_id; i++) {
-               struct msg_queue * msq;
-               msq = msg_lock(i);
-               if(msq != NULL) {
-                       len += sprintf(buffer + len, "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
-                               msq->q_perm.key,
-                               msg_buildid(i,msq->q_perm.seq),
-                               msq->q_perm.mode,
-                               msq->q_cbytes,
-                               msq->q_qnum,
-                               msq->q_lspid,
-                               msq->q_lrpid,
-                               msq->q_perm.uid,
-                               msq->q_perm.gid,
-                               msq->q_perm.cuid,
-                               msq->q_perm.cgid,
-                               msq->q_stime,
-                               msq->q_rtime,
-                               msq->q_ctime);
-                       msg_unlock(msq);
-
-                       pos += len;
-                       if(pos < offset) {
-                               len = 0;
-                               begin = pos;
-                       }
-                       if(pos > offset + length)
-                               goto done;
-               }
-
-       }
-       *eof = 1;
-done:
-       up(&msg_ids.sem);
-       *start = buffer + (offset - begin);
-       len -= (offset - begin);
-       if(len > length)
-               len = length;
-       if(len < 0)
-               len = 0;
-       return len;
+       struct msg_queue *msq = it;
+
+       return seq_printf(s,
+                         "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
+                         msq->q_perm.key,
+                         msq->q_id,
+                         msq->q_perm.mode,
+                         msq->q_cbytes,
+                         msq->q_qnum,
+                         msq->q_lspid,
+                         msq->q_lrpid,
+                         msq->q_perm.uid,
+                         msq->q_perm.gid,
+                         msq->q_perm.cuid,
+                         msq->q_perm.cgid,
+                         msq->q_stime,
+                         msq->q_rtime,
+                         msq->q_ctime);
 }
 #endif
index 70975ce0784a9082207659c31e4e1cd946f32c7b..19af028a3e380d251d31e4b8ec4cd96ee679a1cb 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -73,6 +73,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include "util.h"
 
@@ -89,7 +90,7 @@ static struct ipc_ids sem_ids;
 static int newary (key_t, int, int);
 static void freeary (struct sem_array *sma, int id);
 #ifdef CONFIG_PROC_FS
-static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
 #endif
 
 #define SEMMSL_FAST    256 /* 512 bytes on stack */
@@ -116,10 +117,10 @@ void __init sem_init (void)
 {
        used_sems = 0;
        ipc_init_ids(&sem_ids,sc_semmni);
-
-#ifdef CONFIG_PROC_FS
-       create_proc_read_entry("sysvipc/sem", 0, NULL, sysvipc_sem_read_proc, NULL);
-#endif
+       ipc_init_proc_interface("sysvipc/sem",
+                               "       key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime\n",
+                               &sem_ids,
+                               sysvipc_sem_proc_show);
 }
 
 /*
@@ -193,6 +194,7 @@ static int newary (key_t key, int nsems, int semflg)
        }
        used_sems += nsems;
 
+       sma->sem_id = sem_buildid(id, sma->sem_perm.seq);
        sma->sem_base = (struct sem *) &sma[1];
        /* sma->sem_pending = NULL; */
        sma->sem_pending_last = &sma->sem_pending;
@@ -201,7 +203,7 @@ static int newary (key_t key, int nsems, int semflg)
        sma->sem_ctime = get_seconds();
        sem_unlock(sma);
 
-       return sem_buildid(id, sma->sem_perm.seq);
+       return sma->sem_id;
 }
 
 asmlinkage long sys_semget (key_t key, int nsems, int semflg)
@@ -1328,50 +1330,21 @@ next_entry:
 }
 
 #ifdef CONFIG_PROC_FS
-static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
 {
-       off_t pos = 0;
-       off_t begin = 0;
-       int i, len = 0;
-
-       len += sprintf(buffer, "       key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime\n");
-       down(&sem_ids.sem);
-
-       for(i = 0; i <= sem_ids.max_id; i++) {
-               struct sem_array *sma;
-               sma = sem_lock(i);
-               if(sma) {
-                       len += sprintf(buffer + len, "%10d %10d  %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
-                               sma->sem_perm.key,
-                               sem_buildid(i,sma->sem_perm.seq),
-                               sma->sem_perm.mode,
-                               sma->sem_nsems,
-                               sma->sem_perm.uid,
-                               sma->sem_perm.gid,
-                               sma->sem_perm.cuid,
-                               sma->sem_perm.cgid,
-                               sma->sem_otime,
-                               sma->sem_ctime);
-                       sem_unlock(sma);
-
-                       pos += len;
-                       if(pos < offset) {
-                               len = 0;
-                               begin = pos;
-                       }
-                       if(pos > offset + length)
-                               goto done;
-               }
-       }
-       *eof = 1;
-done:
-       up(&sem_ids.sem);
-       *start = buffer + (offset - begin);
-       len -= (offset - begin);
-       if(len > length)
-               len = length;
-       if(len < 0)
-               len = 0;
-       return len;
+       struct sem_array *sma = it;
+
+       return seq_printf(s,
+                         "%10d %10d  %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
+                         sma->sem_perm.key,
+                         sma->sem_id,
+                         sma->sem_perm.mode,
+                         sma->sem_nsems,
+                         sma->sem_perm.uid,
+                         sma->sem_perm.gid,
+                         sma->sem_perm.cuid,
+                         sma->sem_perm.cgid,
+                         sma->sem_otime,
+                         sma->sem_ctime);
 }
 #endif
index 1d6cf08d950b93c9f5223c7ead161b6f08ed9877..dca90489e3b0f7b9cfd189b593eeee1d3c0f197e 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/mman.h>
-#include <linux/proc_fs.h>
 #include <linux/shmem_fs.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
 #include <linux/ptrace.h>
+#include <linux/seq_file.h>
 
 #include <asm/uaccess.h>
 
@@ -51,7 +51,7 @@ static int newseg (key_t key, int shmflg, size_t size);
 static void shm_open (struct vm_area_struct *shmd);
 static void shm_close (struct vm_area_struct *shmd);
 #ifdef CONFIG_PROC_FS
-static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
 
 size_t shm_ctlmax = SHMMAX;
@@ -63,9 +63,10 @@ static int shm_tot; /* total number of shared memory pages */
 void __init shm_init (void)
 {
        ipc_init_ids(&shm_ids, 1);
-#ifdef CONFIG_PROC_FS
-       create_proc_read_entry("sysvipc/shm", 0, NULL, sysvipc_shm_read_proc, NULL);
-#endif
+       ipc_init_proc_interface("sysvipc/shm",
+                               "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n",
+                               &shm_ids,
+                               sysvipc_shm_proc_show);
 }
 
 static inline int shm_checkid(struct shmid_kernel *s, int id)
@@ -869,63 +870,32 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
 }
 
 #ifdef CONFIG_PROC_FS
-static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
 {
-       off_t pos = 0;
-       off_t begin = 0;
-       int i, len = 0;
-
-       down(&shm_ids.sem);
-       len += sprintf(buffer, "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n");
+       struct shmid_kernel *shp = it;
+       char *format;
 
-       for(i = 0; i <= shm_ids.max_id; i++) {
-               struct shmid_kernel* shp;
-
-               shp = shm_lock(i);
-               if(shp!=NULL) {
 #define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
 #define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
-                       char *format;
 
-                       if (sizeof(size_t) <= sizeof(int))
-                               format = SMALL_STRING;
-                       else
-                               format = BIG_STRING;
-                       len += sprintf(buffer + len, format,
-                               shp->shm_perm.key,
-                               shm_buildid(i, shp->shm_perm.seq),
-                               shp->shm_flags,
-                               shp->shm_segsz,
-                               shp->shm_cprid,
-                               shp->shm_lprid,
-                               is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
-                               shp->shm_perm.uid,
-                               shp->shm_perm.gid,
-                               shp->shm_perm.cuid,
-                               shp->shm_perm.cgid,
-                               shp->shm_atim,
-                               shp->shm_dtim,
-                               shp->shm_ctim);
-                       shm_unlock(shp);
-
-                       pos += len;
-                       if(pos < offset) {
-                               len = 0;
-                               begin = pos;
-                       }
-                       if(pos > offset + length)
-                               goto done;
-               }
-       }
-       *eof = 1;
-done:
-       up(&shm_ids.sem);
-       *start = buffer + (offset - begin);
-       len -= (offset - begin);
-       if(len > length)
-               len = length;
-       if(len < 0)
-               len = 0;
-       return len;
+       if (sizeof(size_t) <= sizeof(int))
+               format = SMALL_STRING;
+       else
+               format = BIG_STRING;
+       return seq_printf(s, format,
+                         shp->shm_perm.key,
+                         shp->id,
+                         shp->shm_flags,
+                         shp->shm_segsz,
+                         shp->shm_cprid,
+                         shp->shm_lprid,
+                         is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
+                         shp->shm_perm.uid,
+                         shp->shm_perm.gid,
+                         shp->shm_perm.cuid,
+                         shp->shm_perm.cgid,
+                         shp->shm_atim,
+                         shp->shm_dtim,
+                         shp->shm_ctim);
 }
 #endif
index e00c35f7b2b8055ffc9d516b69343eb6c3158836..10e836d0d89e86fb36de703364a0afdeb0f21c7e 100644 (file)
 #include <linux/security.h>
 #include <linux/rcupdate.h>
 #include <linux/workqueue.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 
 #include <asm/unistd.h>
 
 #include "util.h"
 
+struct ipc_proc_iface {
+       const char *path;
+       const char *header;
+       struct ipc_ids *ids;
+       int (*show)(struct seq_file *, void *);
+};
+
 /**
  *     ipc_init        -       initialise IPC subsystem
  *
@@ -86,6 +95,43 @@ void __init ipc_init_ids(struct ipc_ids* ids, int size)
                ids->entries->p[i] = NULL;
 }
 
+#ifdef CONFIG_PROC_FS
+static struct file_operations sysvipc_proc_fops;
+/**
+ *     ipc_init_proc_interface -  Create a proc interface for sysipc types
+ *                                using a seq_file interface.
+ *     @path: Path in procfs
+ *     @header: Banner to be printed at the beginning of the file.
+ *     @ids: ipc id table to iterate.
+ *     @show: show routine.
+ */
+void __init ipc_init_proc_interface(const char *path, const char *header,
+                                   struct ipc_ids *ids,
+                                   int (*show)(struct seq_file *, void *))
+{
+       struct proc_dir_entry *pde;
+       struct ipc_proc_iface *iface;
+
+       iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+       if (!iface)
+               return;
+       iface->path     = path;
+       iface->header   = header;
+       iface->ids      = ids;
+       iface->show     = show;
+
+       pde = create_proc_entry(path,
+                               S_IRUGO,        /* world readable */
+                               NULL            /* parent dir */);
+       if (pde) {
+               pde->data = iface;
+               pde->proc_fops = &sysvipc_proc_fops;
+       } else {
+               kfree(iface);
+       }
+}
+#endif
+
 /**
  *     ipc_findkey     -       find a key in an ipc identifier set     
  *     @ids: Identifier set
@@ -578,3 +624,113 @@ int ipc_parse_version (int *cmd)
 }
 
 #endif /* __ARCH_WANT_IPC_PARSE_VERSION */
+
+#ifdef CONFIG_PROC_FS
+static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
+{
+       struct ipc_proc_iface *iface = s->private;
+       struct kern_ipc_perm *ipc = it;
+       loff_t p;
+
+       /* If we had an ipc id locked before, unlock it */
+       if (ipc && ipc != SEQ_START_TOKEN)
+               ipc_unlock(ipc);
+
+       /*
+        * p = *pos - 1 (because id 0 starts at position 1)
+        *          + 1 (because we increment the position by one)
+        */
+       for (p = *pos; p <= iface->ids->max_id; p++) {
+               if ((ipc = ipc_lock(iface->ids, p)) != NULL) {
+                       *pos = p + 1;
+                       return ipc;
+               }
+       }
+
+       /* Out of range - return NULL to terminate iteration */
+       return NULL;
+}
+
+/*
+ * File positions: pos 0 -> header, pos n -> ipc id + 1.
+ * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START.
+ */
+static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
+{
+       struct ipc_proc_iface *iface = s->private;
+       struct kern_ipc_perm *ipc;
+       loff_t p;
+
+       /*
+        * Take the lock - this will be released by the corresponding
+        * call to stop().
+        */
+       down(&iface->ids->sem);
+
+       /* pos < 0 is invalid */
+       if (*pos < 0)
+               return NULL;
+
+       /* pos == 0 means header */
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+
+       /* Find the (pos-1)th ipc */
+       for (p = *pos - 1; p <= iface->ids->max_id; p++) {
+               if ((ipc = ipc_lock(iface->ids, p)) != NULL) {
+                       *pos = p + 1;
+                       return ipc;
+               }
+       }
+       return NULL;
+}
+
+static void sysvipc_proc_stop(struct seq_file *s, void *it)
+{
+       struct kern_ipc_perm *ipc = it;
+       struct ipc_proc_iface *iface = s->private;
+
+       /* If we had a locked segment, release it */
+       if (ipc && ipc != SEQ_START_TOKEN)
+               ipc_unlock(ipc);
+
+       /* Release the lock we took in start() */
+       up(&iface->ids->sem);
+}
+
+static int sysvipc_proc_show(struct seq_file *s, void *it)
+{
+       struct ipc_proc_iface *iface = s->private;
+
+       if (it == SEQ_START_TOKEN)
+               return seq_puts(s, iface->header);
+
+       return iface->show(s, it);
+}
+
+static struct seq_operations sysvipc_proc_seqops = {
+       .start = sysvipc_proc_start,
+       .stop  = sysvipc_proc_stop,
+       .next  = sysvipc_proc_next,
+       .show  = sysvipc_proc_show,
+};
+
+static int sysvipc_proc_open(struct inode *inode, struct file *file) {
+       int ret;
+       struct seq_file *seq;
+
+       ret = seq_open(file, &sysvipc_proc_seqops);
+       if (!ret) {
+               seq = file->private_data;
+               seq->private = PDE(inode)->data;
+       }
+       return ret;
+}
+
+static struct file_operations sysvipc_proc_fops = {
+       .open    = sysvipc_proc_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release,
+};
+#endif /* CONFIG_PROC_FS */
index 44348ca5a70738ab4033b68d66c97bdcaa626495..fc9a28be0797b3a27ac7f99f8572eeff99ffe99c 100644 (file)
@@ -30,7 +30,15 @@ struct ipc_ids {
        struct ipc_id_ary* entries;
 };
 
+struct seq_file;
 void __init ipc_init_ids(struct ipc_ids* ids, int size);
+#ifdef CONFIG_PROC_FS
+void __init ipc_init_proc_interface(const char *path, const char *header,
+                                   struct ipc_ids *ids,
+                                   int (*show)(struct seq_file *, void *));
+#else
+#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
+#endif
 
 /* must be called with ids->sem acquired.*/
 int ipc_findkey(struct ipc_ids* ids, key_t key);
index cb05cd05d2374b1ae316adb437ec14da370bd8a5..8d57a2f1226baa8034e8d93b7e4806d5a3f5fce1 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
 obj-$(CONFIG_KPROBES) += kprobes.o
 obj-$(CONFIG_SYSFS) += ksysfs.o
+obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
index 4168f631868e15bb5e9a50c457c9b5f539a6838c..f70e6027cca9758c7ca35f3dc4bd89b7d97d5b14 100644 (file)
@@ -220,7 +220,7 @@ asmlinkage long sys_acct(const char __user *name)
                        return (PTR_ERR(tmp));
                }
                /* Difference from BSD - they don't do O_APPEND */
-               file = filp_open(tmp, O_WRONLY|O_APPEND, 0);
+               file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
                putname(tmp);
                if (IS_ERR(file)) {
                        return (PTR_ERR(file));
index 8ab1b4e518b8909a867595534957dbf3c12cf3d8..1f06e76901067ffa1c08d586d0128f64ad6d6c65 100644 (file)
@@ -628,13 +628,6 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
  * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
  */
 
-/*
- * Hack to avoid 2.6.13 partial node dynamic sched domain bug.
- * Disable letting 'cpu_exclusive' cpusets define dynamic sched
- * domains, until the sched domain can handle partial nodes.
- * Remove this #if hackery when sched domains fixed.
- */
-#if 0
 static void update_cpu_domains(struct cpuset *cur)
 {
        struct cpuset *c, *par = cur->parent;
@@ -675,11 +668,6 @@ static void update_cpu_domains(struct cpuset *cur)
        partition_sched_domains(&pspan, &cspan);
        unlock_cpu_hotplug();
 }
-#else
-static void update_cpu_domains(struct cpuset *cur)
-{
-}
-#endif
 
 static int update_cpumask(struct cpuset *cs, char *buf)
 {
@@ -1611,17 +1599,114 @@ int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
        return 0;
 }
 
+/*
+ * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive
+ * ancestor to the specified cpuset.  Call while holding cpuset_sem.
+ * If no ancestor is mem_exclusive (an unusual configuration), then
+ * returns the root cpuset.
+ */
+static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+{
+       while (!is_mem_exclusive(cs) && cs->parent)
+               cs = cs->parent;
+       return cs;
+}
+
 /**
- * cpuset_zone_allowed - is zone z allowed in current->mems_allowed
- * @z: zone in question
+ * cpuset_zone_allowed - Can we allocate memory on zone z's memory node?
+ * @z: is this zone on an allowed node?
+ * @gfp_mask: memory allocation flags (we use __GFP_HARDWALL)
  *
- * Is zone z allowed in current->mems_allowed, or is
- * the CPU in interrupt context? (zone is always allowed in this case)
- */
-int cpuset_zone_allowed(struct zone *z)
+ * If we're in interrupt, yes, we can always allocate.  If zone
+ * z's node is in our tasks mems_allowed, yes.  If it's not a
+ * __GFP_HARDWALL request and this zone's nodes is in the nearest
+ * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
+ * Otherwise, no.
+ *
+ * GFP_USER allocations are marked with the __GFP_HARDWALL bit,
+ * and do not allow allocations outside the current tasks cpuset.
+ * GFP_KERNEL allocations are not so marked, so can escape to the
+ * nearest mem_exclusive ancestor cpuset.
+ *
+ * Scanning up parent cpusets requires cpuset_sem.  The __alloc_pages()
+ * routine only calls here with __GFP_HARDWALL bit _not_ set if
+ * it's a GFP_KERNEL allocation, and all nodes in the current tasks
+ * mems_allowed came up empty on the first pass over the zonelist.
+ * So only GFP_KERNEL allocations, if all nodes in the cpuset are
+ * short of memory, might require taking the cpuset_sem semaphore.
+ *
+ * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages()
+ * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing
+ * hardwall cpusets - no allocation on a node outside the cpuset is
+ * allowed (unless in interrupt, of course).
+ *
+ * The second loop doesn't even call here for GFP_ATOMIC requests
+ * (if the __alloc_pages() local variable 'wait' is set).  That check
+ * and the checks below have the combined affect in the second loop of
+ * the __alloc_pages() routine that:
+ *     in_interrupt - any node ok (current task context irrelevant)
+ *     GFP_ATOMIC   - any node ok
+ *     GFP_KERNEL   - any node in enclosing mem_exclusive cpuset ok
+ *     GFP_USER     - only nodes in current tasks mems allowed ok.
+ **/
+
+int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask)
 {
-       return in_interrupt() ||
-               node_isset(z->zone_pgdat->node_id, current->mems_allowed);
+       int node;                       /* node that zone z is on */
+       const struct cpuset *cs;        /* current cpuset ancestors */
+       int allowed = 1;                /* is allocation in zone z allowed? */
+
+       if (in_interrupt())
+               return 1;
+       node = z->zone_pgdat->node_id;
+       if (node_isset(node, current->mems_allowed))
+               return 1;
+       if (gfp_mask & __GFP_HARDWALL)  /* If hardwall request, stop here */
+               return 0;
+
+       /* Not hardwall and node outside mems_allowed: scan up cpusets */
+       down(&cpuset_sem);
+       cs = current->cpuset;
+       if (!cs)
+               goto done;              /* current task exiting */
+       cs = nearest_exclusive_ancestor(cs);
+       allowed = node_isset(node, cs->mems_allowed);
+done:
+       up(&cpuset_sem);
+       return allowed;
+}
+
+/**
+ * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors?
+ * @p: pointer to task_struct of some other task.
+ *
+ * Description: Return true if the nearest mem_exclusive ancestor
+ * cpusets of tasks @p and current overlap.  Used by oom killer to
+ * determine if task @p's memory usage might impact the memory
+ * available to the current task.
+ *
+ * Acquires cpuset_sem - not suitable for calling from a fast path.
+ **/
+
+int cpuset_excl_nodes_overlap(const struct task_struct *p)
+{
+       const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
+       int overlap = 0;                /* do cpusets overlap? */
+
+       down(&cpuset_sem);
+       cs1 = current->cpuset;
+       if (!cs1)
+               goto done;              /* current task exiting */
+       cs2 = p->cpuset;
+       if (!cs2)
+               goto done;              /* task p is exiting */
+       cs1 = nearest_exclusive_ancestor(cs1);
+       cs2 = nearest_exclusive_ancestor(cs2);
+       overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
+done:
+       up(&cpuset_sem);
+
+       return overlap;
 }
 
 /*
index c7130f86106c30a8c9970b425dad032d3885318e..ca05fe6a70b24a2921901505c99dd7eb105b3df7 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
+#include <asm/futex.h>
 
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
@@ -326,6 +327,118 @@ out:
        return ret;
 }
 
+/*
+ * Wake up all waiters hashed on the physical page that is mapped
+ * to this virtual address:
+ */
+static int futex_wake_op(unsigned long uaddr1, unsigned long uaddr2, int nr_wake, int nr_wake2, int op)
+{
+       union futex_key key1, key2;
+       struct futex_hash_bucket *bh1, *bh2;
+       struct list_head *head;
+       struct futex_q *this, *next;
+       int ret, op_ret, attempt = 0;
+
+retryfull:
+       down_read(&current->mm->mmap_sem);
+
+       ret = get_futex_key(uaddr1, &key1);
+       if (unlikely(ret != 0))
+               goto out;
+       ret = get_futex_key(uaddr2, &key2);
+       if (unlikely(ret != 0))
+               goto out;
+
+       bh1 = hash_futex(&key1);
+       bh2 = hash_futex(&key2);
+
+retry:
+       if (bh1 < bh2)
+               spin_lock(&bh1->lock);
+       spin_lock(&bh2->lock);
+       if (bh1 > bh2)
+               spin_lock(&bh1->lock);
+
+       op_ret = futex_atomic_op_inuser(op, (int __user *)uaddr2);
+       if (unlikely(op_ret < 0)) {
+               int dummy;
+
+               spin_unlock(&bh1->lock);
+               if (bh1 != bh2)
+                       spin_unlock(&bh2->lock);
+
+               /* futex_atomic_op_inuser needs to both read and write
+                * *(int __user *)uaddr2, but we can't modify it
+                * non-atomically.  Therefore, if get_user below is not
+                * enough, we need to handle the fault ourselves, while
+                * still holding the mmap_sem.  */
+               if (attempt++) {
+                       struct vm_area_struct * vma;
+                       struct mm_struct *mm = current->mm;
+
+                       ret = -EFAULT;
+                       if (attempt >= 2 ||
+                           !(vma = find_vma(mm, uaddr2)) ||
+                           vma->vm_start > uaddr2 ||
+                           !(vma->vm_flags & VM_WRITE))
+                               goto out;
+
+                       switch (handle_mm_fault(mm, vma, uaddr2, 1)) {
+                       case VM_FAULT_MINOR:
+                               current->min_flt++;
+                               break;
+                       case VM_FAULT_MAJOR:
+                               current->maj_flt++;
+                               break;
+                       default:
+                               goto out;
+                       }
+                       goto retry;
+               }
+
+               /* If we would have faulted, release mmap_sem,
+                * fault it in and start all over again.  */
+               up_read(&current->mm->mmap_sem);
+
+               ret = get_user(dummy, (int __user *)uaddr2);
+               if (ret)
+                       return ret;
+
+               goto retryfull;
+       }
+
+       head = &bh1->chain;
+
+       list_for_each_entry_safe(this, next, head, list) {
+               if (match_futex (&this->key, &key1)) {
+                       wake_futex(this);
+                       if (++ret >= nr_wake)
+                               break;
+               }
+       }
+
+       if (op_ret > 0) {
+               head = &bh2->chain;
+
+               op_ret = 0;
+               list_for_each_entry_safe(this, next, head, list) {
+                       if (match_futex (&this->key, &key2)) {
+                               wake_futex(this);
+                               if (++op_ret >= nr_wake2)
+                                       break;
+                       }
+               }
+               ret += op_ret;
+       }
+
+       spin_unlock(&bh1->lock);
+       if (bh1 != bh2)
+               spin_unlock(&bh2->lock);
+out:
+       up_read(&current->mm->mmap_sem);
+       return ret;
+}
+
 /*
  * Requeue all waiters hashed on one physical page to another
  * physical page.
@@ -673,23 +786,17 @@ static int futex_fd(unsigned long uaddr, int signal)
        filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
 
        if (signal) {
-               int err;
                err = f_setown(filp, current->pid, 1);
                if (err < 0) {
-                       put_unused_fd(ret);
-                       put_filp(filp);
-                       ret = err;
-                       goto out;
+                       goto error;
                }
                filp->f_owner.signum = signal;
        }
 
        q = kmalloc(sizeof(*q), GFP_KERNEL);
        if (!q) {
-               put_unused_fd(ret);
-               put_filp(filp);
-               ret = -ENOMEM;
-               goto out;
+               err = -ENOMEM;
+               goto error;
        }
 
        down_read(&current->mm->mmap_sem);
@@ -697,10 +804,8 @@ static int futex_fd(unsigned long uaddr, int signal)
 
        if (unlikely(err != 0)) {
                up_read(&current->mm->mmap_sem);
-               put_unused_fd(ret);
-               put_filp(filp);
                kfree(q);
-               return err;
+               goto error;
        }
 
        /*
@@ -716,6 +821,11 @@ static int futex_fd(unsigned long uaddr, int signal)
        fd_install(ret, filp);
 out:
        return ret;
+error:
+       put_unused_fd(ret);
+       put_filp(filp);
+       ret = err;
+       goto out;
 }
 
 long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
@@ -740,6 +850,9 @@ long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
        case FUTEX_CMP_REQUEUE:
                ret = futex_requeue(uaddr, uaddr2, val, val2, &val3);
                break;
+       case FUTEX_WAKE_OP:
+               ret = futex_wake_op(uaddr, uaddr2, val, val2, val3);
+               break;
        default:
                ret = -ENOSYS;
        }
index 388977f3e9b7d7a826e57d60a3227da0d4f3c1ac..0cbe633420fb9b6d46376debb0c68d201a5966d5 100644 (file)
@@ -39,7 +39,7 @@ void inter_module_register(const char *im_name, struct module *owner, const void
        struct list_head *tmp;
        struct inter_module_entry *ime, *ime_new;
 
-       if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
+       if (!(ime_new = kzalloc(sizeof(*ime), GFP_KERNEL))) {
                /* Overloaded kernel, not fatal */
                printk(KERN_ERR
                        "Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
@@ -47,7 +47,6 @@ void inter_module_register(const char *im_name, struct module *owner, const void
                kmalloc_failed = 1;
                return;
        }
-       memset(ime_new, 0, sizeof(*ime_new));
        ime_new->im_name = im_name;
        ime_new->owner = owner;
        ime_new->userdata = userdata;
index c29f83c16497cff719b118bf1a8fabfb78076cd2..3ff7b925c38773f1c0df8eb4dcda1ea5926f1ea3 100644 (file)
@@ -111,7 +111,7 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
        unsigned int status;
 
        kstat_this_cpu.irqs[irq]++;
-       if (desc->status & IRQ_PER_CPU) {
+       if (CHECK_IRQ_PER_CPU(desc->status)) {
                irqreturn_t action_ret;
 
                /*
index ac670098570579e980e6b7bba35a235f7be885a9..1cfdb08ddf2054f6f219d28c78b97828e2f8b447 100644 (file)
 
 cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
 
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+#endif
+
 /**
  *     synchronize_irq - wait for pending IRQ handlers (on other CPUs)
  *
index 85d08daa6600ee826e1810010500ddca76133e86..f26e534c6585dacf089be5fb602f70b08ee6db60 100644 (file)
@@ -19,12 +19,22 @@ static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS];
  */
 static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
 
-void __attribute__((weak))
-proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+{
+       /*
+        * Save these away for later use. Re-progam when the
+        * interrupt is pending
+        */
+       set_pending_irq(irq, mask_val);
+}
+#else
+void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
 {
        irq_affinity[irq] = mask_val;
        irq_desc[irq].handler->set_affinity(irq, mask_val);
 }
+#endif
 
 static int irq_affinity_read_proc(char *page, char **start, off_t off,
                                  int count, int *eof, void *data)
index b0237122b24e14667631716a8a6c3e23a495a7e9..f3ea492ab44dfcfc05e2fad4027e303f9b69d9dd 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleloader.h>
+#include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
 #include <asm/kdebug.h>
@@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pages;
  * get_insn_slot() - Find a slot on an executable page for an instruction.
  * We allocate an executable page if there's no room on existing ones.
  */
-kprobe_opcode_t *get_insn_slot(void)
+kprobe_opcode_t __kprobes *get_insn_slot(void)
 {
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
@@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void)
        return kip->insns;
 }
 
-void free_insn_slot(kprobe_opcode_t *slot)
+void __kprobes free_insn_slot(kprobe_opcode_t *slot)
 {
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
@@ -152,20 +153,42 @@ void free_insn_slot(kprobe_opcode_t *slot)
 }
 
 /* Locks kprobe: irqs must be disabled */
-void lock_kprobes(void)
+void __kprobes lock_kprobes(void)
 {
+       unsigned long flags = 0;
+
+       /* Avoiding local interrupts to happen right after we take the kprobe_lock
+        * and before we get a chance to update kprobe_cpu, this to prevent
+        * deadlock when we have a kprobe on ISR routine and a kprobe on task
+        * routine
+        */
+       local_irq_save(flags);
+
        spin_lock(&kprobe_lock);
        kprobe_cpu = smp_processor_id();
+
+       local_irq_restore(flags);
 }
 
-void unlock_kprobes(void)
+void __kprobes unlock_kprobes(void)
 {
+       unsigned long flags = 0;
+
+       /* Avoiding local interrupts to happen right after we update
+        * kprobe_cpu and before we get a a chance to release kprobe_lock,
+        * this to prevent deadlock when we have a kprobe on ISR routine and
+        * a kprobe on task routine
+        */
+       local_irq_save(flags);
+
        kprobe_cpu = NR_CPUS;
        spin_unlock(&kprobe_lock);
+
+       local_irq_restore(flags);
 }
 
 /* You have to be holding the kprobe_lock */
-struct kprobe *get_kprobe(void *addr)
+struct kprobe __kprobes *get_kprobe(void *addr)
 {
        struct hlist_head *head;
        struct hlist_node *node;
@@ -183,7 +206,7 @@ struct kprobe *get_kprobe(void *addr)
  * Aggregate handlers for multiple kprobes support - these handlers
  * take care of invoking the individual kprobe handlers on p->list
  */
-static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe *kp;
 
@@ -198,8 +221,8 @@ static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
-static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
-                             unsigned long flags)
+static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+                                       unsigned long flags)
 {
        struct kprobe *kp;
 
@@ -213,8 +236,8 @@ static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
        return;
 }
 
-static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
-                             int trapnr)
+static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
+                                       int trapnr)
 {
        /*
         * if we faulted "during" the execution of a user specified
@@ -227,7 +250,7 @@ static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
        return 0;
 }
 
-static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe *kp = curr_kprobe;
        if (curr_kprobe && kp->break_handler) {
@@ -240,7 +263,7 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
-struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
+struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
 {
        struct hlist_node *node;
        struct kretprobe_instance *ri;
@@ -249,7 +272,8 @@ struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
        return NULL;
 }
 
-static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
+static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
+                                                             *rp)
 {
        struct hlist_node *node;
        struct kretprobe_instance *ri;
@@ -258,7 +282,7 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
        return NULL;
 }
 
-void add_rp_inst(struct kretprobe_instance *ri)
+void __kprobes add_rp_inst(struct kretprobe_instance *ri)
 {
        /*
         * Remove rp inst off the free list -
@@ -276,7 +300,7 @@ void add_rp_inst(struct kretprobe_instance *ri)
        hlist_add_head(&ri->uflist, &ri->rp->used_instances);
 }
 
-void recycle_rp_inst(struct kretprobe_instance *ri)
+void __kprobes recycle_rp_inst(struct kretprobe_instance *ri)
 {
        /* remove rp inst off the rprobe_inst_table */
        hlist_del(&ri->hlist);
@@ -291,7 +315,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri)
                kfree(ri);
 }
 
-struct hlist_head kretprobe_inst_table_head(struct task_struct *tsk)
+struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
 {
        return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
 }
@@ -302,7 +326,7 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
  * instances associated with this task. These left over instances represent
  * probed functions that have been called but will never return.
  */
-void kprobe_flush_task(struct task_struct *tk)
+void __kprobes kprobe_flush_task(struct task_struct *tk)
 {
         struct kretprobe_instance *ri;
         struct hlist_head *head;
@@ -322,7 +346,8 @@ void kprobe_flush_task(struct task_struct *tk)
  * This kprobe pre_handler is registered with every kretprobe. When probe
  * hits it will set up the return probe.
  */
-static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+                                          struct pt_regs *regs)
 {
        struct kretprobe *rp = container_of(p, struct kretprobe, kp);
 
@@ -353,7 +378,7 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
 * Add the new probe to old_p->list. Fail if this is the
 * second jprobe at the address - two jprobes can't coexist
 */
-static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
 {
         struct kprobe *kp;
 
@@ -395,7 +420,8 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
  * the intricacies
  * TODO: Move kcalloc outside the spinlock
  */
-static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
+                                         struct kprobe *p)
 {
        int ret = 0;
        struct kprobe *ap;
@@ -434,15 +460,25 @@ static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
                spin_unlock_irqrestore(&kprobe_lock, flags);
 }
 
-int register_kprobe(struct kprobe *p)
+static int __kprobes in_kprobes_functions(unsigned long addr)
+{
+       if (addr >= (unsigned long)__kprobes_text_start
+               && addr < (unsigned long)__kprobes_text_end)
+               return -EINVAL;
+       return 0;
+}
+
+int __kprobes register_kprobe(struct kprobe *p)
 {
        int ret = 0;
        unsigned long flags = 0;
        struct kprobe *old_p;
 
-       if ((ret = arch_prepare_kprobe(p)) != 0) {
+       if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
+               return ret;
+       if ((ret = arch_prepare_kprobe(p)) != 0)
                goto rm_kprobe;
-       }
+
        spin_lock_irqsave(&kprobe_lock, flags);
        old_p = get_kprobe(p->addr);
        p->nmissed = 0;
@@ -466,7 +502,7 @@ rm_kprobe:
        return ret;
 }
 
-void unregister_kprobe(struct kprobe *p)
+void __kprobes unregister_kprobe(struct kprobe *p)
 {
        unsigned long flags;
        struct kprobe *old_p;
@@ -487,7 +523,7 @@ static struct notifier_block kprobe_exceptions_nb = {
        .priority = 0x7fffffff /* we need to notified first */
 };
 
-int register_jprobe(struct jprobe *jp)
+int __kprobes register_jprobe(struct jprobe *jp)
 {
        /* Todo: Verify probepoint is a function entry point */
        jp->kp.pre_handler = setjmp_pre_handler;
@@ -496,14 +532,14 @@ int register_jprobe(struct jprobe *jp)
        return register_kprobe(&jp->kp);
 }
 
-void unregister_jprobe(struct jprobe *jp)
+void __kprobes unregister_jprobe(struct jprobe *jp)
 {
        unregister_kprobe(&jp->kp);
 }
 
 #ifdef ARCH_SUPPORTS_KRETPROBES
 
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
 {
        int ret = 0;
        struct kretprobe_instance *inst;
@@ -540,14 +576,14 @@ int register_kretprobe(struct kretprobe *rp)
 
 #else /* ARCH_SUPPORTS_KRETPROBES */
 
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
 {
        return -ENOSYS;
 }
 
 #endif /* ARCH_SUPPORTS_KRETPROBES */
 
-void unregister_kretprobe(struct kretprobe *rp)
+void __kprobes unregister_kretprobe(struct kretprobe *rp)
 {
        unsigned long flags;
        struct kretprobe_instance *ri;
index c32995fbd8fd14b608bb49e5b0f5899e41ffd979..4b39d3793c720673452b6d8be18ade674360131a 100644 (file)
@@ -1509,6 +1509,7 @@ static struct module *load_module(void __user *umod,
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
        struct exception_table_entry *extable;
+       mm_segment_t old_fs;
 
        DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
               umod, len, uargs);
@@ -1779,6 +1780,24 @@ static struct module *load_module(void __user *umod,
        if (err < 0)
                goto cleanup;
 
+       /* flush the icache in correct context */
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       /*
+        * Flush the instruction cache, since we've played with text.
+        * Do it before processing of module parameters, so the module
+        * can provide parameter accessor functions of its own.
+        */
+       if (mod->module_init)
+               flush_icache_range((unsigned long)mod->module_init,
+                                  (unsigned long)mod->module_init
+                                  + mod->init_size);
+       flush_icache_range((unsigned long)mod->module_core,
+                          (unsigned long)mod->module_core + mod->core_size);
+
+       set_fs(old_fs);
+
        mod->args = args;
        if (obsparmindex) {
                err = obsolete_params(mod->name, mod->args,
@@ -1860,7 +1879,6 @@ sys_init_module(void __user *umod,
                const char __user *uargs)
 {
        struct module *mod;
-       mm_segment_t old_fs = get_fs();
        int ret = 0;
 
        /* Must have permission */
@@ -1878,19 +1896,6 @@ sys_init_module(void __user *umod,
                return PTR_ERR(mod);
        }
 
-       /* flush the icache in correct context */
-       set_fs(KERNEL_DS);
-
-       /* Flush the instruction cache, since we've played with text */
-       if (mod->module_init)
-               flush_icache_range((unsigned long)mod->module_init,
-                                  (unsigned long)mod->module_init
-                                  + mod->init_size);
-       flush_icache_range((unsigned long)mod->module_core,
-                          (unsigned long)mod->module_core + mod->core_size);
-
-       set_fs(old_fs);
-
        /* Now sew it into the lists.  They won't access us, since
            strong_try_module_get() will fail. */
        stop_machine_run(__link_module, mod, NR_CPUS);
index d586c35ef8fca8f4540031c5ad071b90c1071df4..fbf173215fd217bed3db643ba0676916f7085daf 100644 (file)
@@ -542,8 +542,8 @@ static void __init kernel_param_sysfs_setup(const char *name,
 {
        struct module_kobject *mk;
 
-       mk = kmalloc(sizeof(struct module_kobject), GFP_KERNEL);
-       memset(mk, 0, sizeof(struct module_kobject));
+       mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
+       BUG_ON(!mk);
 
        mk->mod = THIS_MODULE;
        kobj_set_kset_s(mk, module_subsys);
index 38798a2ff994e96c017010b8c2c62db578fe2002..b7b532acd9fc419050f03de66b12acb14d5c4077 100644 (file)
@@ -427,21 +427,23 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
        timr->sigq->info.si_code = SI_TIMER;
        timr->sigq->info.si_tid = timr->it_id;
        timr->sigq->info.si_value = timr->it_sigev_value;
+
        if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
-               if (unlikely(timr->it_process->flags & PF_EXITING)) {
-                       timr->it_sigev_notify = SIGEV_SIGNAL;
-                       put_task_struct(timr->it_process);
-                       timr->it_process = timr->it_process->group_leader;
-                       goto group;
-               }
-               return send_sigqueue(timr->it_sigev_signo, timr->sigq,
-                       timr->it_process);
-       }
-       else {
-       group:
-               return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
-                       timr->it_process);
+               struct task_struct *leader;
+               int ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
+                                       timr->it_process);
+
+               if (likely(ret >= 0))
+                       return ret;
+
+               timr->it_sigev_notify = SIGEV_SIGNAL;
+               leader = timr->it_process->group_leader;
+               put_task_struct(timr->it_process);
+               timr->it_process = leader;
        }
+
+       return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
+                                  timr->it_process);
 }
 EXPORT_SYMBOL_GPL(posix_timer_event);
 
index 917066a5767c342663c952d1018806dc67db1167..c14cd99911818c893294c52afff301b58e729554 100644 (file)
@@ -28,7 +28,7 @@ config PM_DEBUG
 
 config SOFTWARE_SUSPEND
        bool "Software Suspend"
-       depends on EXPERIMENTAL && PM && SWAP && ((X86 && SMP) || ((FVR || PPC32 || X86) && !SMP))
+       depends on PM && SWAP && (X86 || ((FVR || PPC32) && !SMP))
        ---help---
          Enable the possibility of suspending the machine.
          It doesn't need APM.
index 61deda04e39e2af3d7c31298665e02213afdafdd..159149321b3c2adb4dcf20372ada8edb2a098c7a 100644 (file)
@@ -60,9 +60,8 @@ struct pm_dev *pm_register(pm_dev_t type,
                           unsigned long id,
                           pm_callback callback)
 {
-       struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+       struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL);
        if (dev) {
-               memset(dev, 0, sizeof(*dev));
                dev->type = type;
                dev->id = id;
                dev->callback = callback;
index eaacd5cb58895438ac28013968651f0d1752c4c6..d967e875ee82f974d9f4e8e365aa59270a6f5c61 100644 (file)
@@ -1059,6 +1059,7 @@ int swsusp_resume(void)
        BUG_ON(!error);
        restore_processor_state();
        restore_highmem();
+       touch_softlockup_watchdog();
        device_power_up();
        local_irq_enable();
        return error;
index 5092397fac29926bfab6da75fc273882b14e905d..a967605bc2e358cbcf95dd7fe60f7870fe9dd14b 100644 (file)
@@ -514,6 +514,9 @@ asmlinkage int printk(const char *fmt, ...)
        return r;
 }
 
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int printk_cpu = UINT_MAX;
+
 asmlinkage int vprintk(const char *fmt, va_list args)
 {
        unsigned long flags;
@@ -522,11 +525,15 @@ asmlinkage int vprintk(const char *fmt, va_list args)
        static char printk_buf[1024];
        static int log_level_unknown = 1;
 
-       if (unlikely(oops_in_progress))
+       preempt_disable();
+       if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
+               /* If a crash is occurring during printk() on this CPU,
+                * make sure we can't deadlock */
                zap_locks();
 
        /* This stops the holder of console_sem just where we want him */
        spin_lock_irqsave(&logbuf_lock, flags);
+       printk_cpu = smp_processor_id();
 
        /* Emit the output into the temporary buffer */
        printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
@@ -595,6 +602,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * CPU until it is officially up.  We shouldn't be calling into
                 * random console drivers on a CPU which doesn't exist yet..
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
                goto out;
        }
@@ -604,6 +612,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * We own the drivers.  We can drop the spinlock and let
                 * release_console_sem() print the text
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
                console_may_schedule = 0;
                release_console_sem();
@@ -613,9 +622,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * allows the semaphore holder to proceed and to call the
                 * console drivers with the output which we just produced.
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
        }
 out:
+       preempt_enable();
        return printed_len;
 }
 EXPORT_SYMBOL(printk);
index 8dcb8f6288bcecf1f436a2904c0ded883f9d3862..019e04ec065a55d8f28157d3a1f7ba06cafd347f 100644 (file)
@@ -118,6 +118,33 @@ int ptrace_check_attach(struct task_struct *child, int kill)
        return ret;
 }
 
+static int may_attach(struct task_struct *task)
+{
+       if (!task->mm)
+               return -EPERM;
+       if (((current->uid != task->euid) ||
+            (current->uid != task->suid) ||
+            (current->uid != task->uid) ||
+            (current->gid != task->egid) ||
+            (current->gid != task->sgid) ||
+            (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+       smp_rmb();
+       if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+
+       return security_ptrace(current, task);
+}
+
+int ptrace_may_attach(struct task_struct *task)
+{
+       int err;
+       task_lock(task);
+       err = may_attach(task);
+       task_unlock(task);
+       return !err;
+}
+
 int ptrace_attach(struct task_struct *task)
 {
        int retval;
@@ -127,22 +154,10 @@ int ptrace_attach(struct task_struct *task)
                goto bad;
        if (task == current)
                goto bad;
-       if (!task->mm)
-               goto bad;
-       if(((current->uid != task->euid) ||
-           (current->uid != task->suid) ||
-           (current->uid != task->uid) ||
-           (current->gid != task->egid) ||
-           (current->gid != task->sgid) ||
-           (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-               goto bad;
-       smp_rmb();
-       if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
-               goto bad;
        /* the same process cannot be attached many times */
        if (task->ptrace & PT_PTRACED)
                goto bad;
-       retval = security_ptrace(current, task);
+       retval = may_attach(task);
        if (retval)
                goto bad;
 
index 26967e0422014a5957f4b01bbed9a4cea40098bf..92285d822de6c9ce3a75825b7b876b8379d522d6 100644 (file)
@@ -430,10 +430,9 @@ EXPORT_SYMBOL(adjust_resource);
  */
 struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
 {
-       struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+       struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 
        if (res) {
-               memset(res, 0, sizeof(*res));
                res->name = name;
                res->start = start;
                res->end = start + n - 1;
index 5f889d0cbfcc2e614aef87963ec0bea5ea6a5f21..9508527845df1d91beecb758ddd4f5626b11e77c 100644 (file)
@@ -4779,7 +4779,7 @@ static int sd_parent_degenerate(struct sched_domain *sd,
  * Attach the domain 'sd' to 'cpu' as its base domain.  Callers must
  * hold the hotplug lock.
  */
-void cpu_attach_domain(struct sched_domain *sd, int cpu)
+static void cpu_attach_domain(struct sched_domain *sd, int cpu)
 {
        runqueue_t *rq = cpu_rq(cpu);
        struct sched_domain *tmp;
@@ -4802,7 +4802,7 @@ void cpu_attach_domain(struct sched_domain *sd, int cpu)
 }
 
 /* cpus with isolated domains */
-cpumask_t __devinitdata cpu_isolated_map = CPU_MASK_NONE;
+static cpumask_t __devinitdata cpu_isolated_map = CPU_MASK_NONE;
 
 /* Setup the mask of cpus configured for isolated domains */
 static int __init isolated_cpu_setup(char *str)
@@ -4830,8 +4830,8 @@ __setup ("isolcpus=", isolated_cpu_setup);
  * covered by the given span, and will set each group's ->cpumask correctly,
  * and ->cpu_power to 0.
  */
-void init_sched_build_groups(struct sched_group groups[],
-                       cpumask_t span, int (*group_fn)(int cpu))
+static void init_sched_build_groups(struct sched_group groups[], cpumask_t span,
+                                   int (*group_fn)(int cpu))
 {
        struct sched_group *first = NULL, *last = NULL;
        cpumask_t covered = CPU_MASK_NONE;
@@ -4864,12 +4864,85 @@ void init_sched_build_groups(struct sched_group groups[],
        last->next = first;
 }
 
+#define SD_NODES_PER_DOMAIN 16
 
-#ifdef ARCH_HAS_SCHED_DOMAIN
-extern void build_sched_domains(const cpumask_t *cpu_map);
-extern void arch_init_sched_domains(const cpumask_t *cpu_map);
-extern void arch_destroy_sched_domains(const cpumask_t *cpu_map);
-#else
+#ifdef CONFIG_NUMA
+/**
+ * find_next_best_node - find the next node to include in a sched_domain
+ * @node: node whose sched_domain we're building
+ * @used_nodes: nodes already in the sched_domain
+ *
+ * Find the next node to include in a given scheduling domain.  Simply
+ * finds the closest node not already in the @used_nodes map.
+ *
+ * Should use nodemask_t.
+ */
+static int find_next_best_node(int node, unsigned long *used_nodes)
+{
+       int i, n, val, min_val, best_node = 0;
+
+       min_val = INT_MAX;
+
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               /* Start at @node */
+               n = (node + i) % MAX_NUMNODES;
+
+               if (!nr_cpus_node(n))
+                       continue;
+
+               /* Skip already used nodes */
+               if (test_bit(n, used_nodes))
+                       continue;
+
+               /* Simple min distance search */
+               val = node_distance(node, n);
+
+               if (val < min_val) {
+                       min_val = val;
+                       best_node = n;
+               }
+       }
+
+       set_bit(best_node, used_nodes);
+       return best_node;
+}
+
+/**
+ * sched_domain_node_span - get a cpumask for a node's sched_domain
+ * @node: node whose cpumask we're constructing
+ * @size: number of nodes to include in this span
+ *
+ * Given a node, construct a good cpumask for its sched_domain to span.  It
+ * should be one that prevents unnecessary balancing, but also spreads tasks
+ * out optimally.
+ */
+static cpumask_t sched_domain_node_span(int node)
+{
+       int i;
+       cpumask_t span, nodemask;
+       DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+
+       cpus_clear(span);
+       bitmap_zero(used_nodes, MAX_NUMNODES);
+
+       nodemask = node_to_cpumask(node);
+       cpus_or(span, span, nodemask);
+       set_bit(node, used_nodes);
+
+       for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
+               int next_node = find_next_best_node(node, used_nodes);
+               nodemask = node_to_cpumask(next_node);
+               cpus_or(span, span, nodemask);
+       }
+
+       return span;
+}
+#endif
+
+/*
+ * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we
+ * can switch it on easily if needed.
+ */
 #ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
 static struct sched_group sched_group_cpus[NR_CPUS];
@@ -4891,36 +4964,20 @@ static int cpu_to_phys_group(int cpu)
 }
 
 #ifdef CONFIG_NUMA
-
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static int cpu_to_node_group(int cpu)
-{
-       return cpu_to_node(cpu);
-}
-#endif
-
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
 /*
- * The domains setup code relies on siblings not spanning
- * multiple nodes. Make sure the architecture has a proper
- * siblings map:
+ * The init_sched_build_groups can't handle what we want to do with node
+ * groups, so roll our own. Now each node has its own list of groups which
+ * gets dynamically allocated.
  */
-static void check_sibling_maps(void)
-{
-       int i, j;
+static DEFINE_PER_CPU(struct sched_domain, node_domains);
+static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
 
-       for_each_online_cpu(i) {
-               for_each_cpu_mask(j, cpu_sibling_map[i]) {
-                       if (cpu_to_node(i) != cpu_to_node(j)) {
-                               printk(KERN_INFO "warning: CPU %d siblings map "
-                                       "to different node - isolating "
-                                       "them.\n", i);
-                               cpu_sibling_map[i] = cpumask_of_cpu(i);
-                               break;
-                       }
-               }
-       }
+static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
+static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS];
+
+static int cpu_to_allnodes_group(int cpu)
+{
+       return cpu_to_node(cpu);
 }
 #endif
 
@@ -4928,9 +4985,24 @@ static void check_sibling_maps(void)
  * Build sched domains for a given set of cpus and attach the sched domains
  * to the individual cpus
  */
-static void build_sched_domains(const cpumask_t *cpu_map)
+void build_sched_domains(const cpumask_t *cpu_map)
 {
        int i;
+#ifdef CONFIG_NUMA
+       struct sched_group **sched_group_nodes = NULL;
+       struct sched_group *sched_group_allnodes = NULL;
+
+       /*
+        * Allocate the per-node list of sched groups
+        */
+       sched_group_nodes = kmalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+                                          GFP_ATOMIC);
+       if (!sched_group_nodes) {
+               printk(KERN_WARNING "Can not alloc sched group node list\n");
+               return;
+       }
+       sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
+#endif
 
        /*
         * Set up domains for cpus specified by the cpu_map.
@@ -4943,11 +5015,35 @@ static void build_sched_domains(const cpumask_t *cpu_map)
                cpus_and(nodemask, nodemask, *cpu_map);
 
 #ifdef CONFIG_NUMA
+               if (cpus_weight(*cpu_map)
+                               > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+                       if (!sched_group_allnodes) {
+                               sched_group_allnodes
+                                       = kmalloc(sizeof(struct sched_group)
+                                                       * MAX_NUMNODES,
+                                                 GFP_KERNEL);
+                               if (!sched_group_allnodes) {
+                                       printk(KERN_WARNING
+                                       "Can not alloc allnodes sched group\n");
+                                       break;
+                               }
+                               sched_group_allnodes_bycpu[i]
+                                               = sched_group_allnodes;
+                       }
+                       sd = &per_cpu(allnodes_domains, i);
+                       *sd = SD_ALLNODES_INIT;
+                       sd->span = *cpu_map;
+                       group = cpu_to_allnodes_group(i);
+                       sd->groups = &sched_group_allnodes[group];
+                       p = sd;
+               } else
+                       p = NULL;
+
                sd = &per_cpu(node_domains, i);
-               group = cpu_to_node_group(i);
                *sd = SD_NODE_INIT;
-               sd->span = *cpu_map;
-               sd->groups = &sched_group_nodes[group];
+               sd->span = sched_domain_node_span(cpu_to_node(i));
+               sd->parent = p;
+               cpus_and(sd->span, sd->span, *cpu_map);
 #endif
 
                p = sd;
@@ -4972,7 +5068,7 @@ static void build_sched_domains(const cpumask_t *cpu_map)
 
 #ifdef CONFIG_SCHED_SMT
        /* Set up CPU (sibling) groups */
-       for_each_online_cpu(i) {
+       for_each_cpu_mask(i, *cpu_map) {
                cpumask_t this_sibling_map = cpu_sibling_map[i];
                cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
                if (i != first_cpu(this_sibling_map))
@@ -4997,8 +5093,77 @@ static void build_sched_domains(const cpumask_t *cpu_map)
 
 #ifdef CONFIG_NUMA
        /* Set up node groups */
-       init_sched_build_groups(sched_group_nodes, *cpu_map,
-                                       &cpu_to_node_group);
+       if (sched_group_allnodes)
+               init_sched_build_groups(sched_group_allnodes, *cpu_map,
+                                       &cpu_to_allnodes_group);
+
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               /* Set up node groups */
+               struct sched_group *sg, *prev;
+               cpumask_t nodemask = node_to_cpumask(i);
+               cpumask_t domainspan;
+               cpumask_t covered = CPU_MASK_NONE;
+               int j;
+
+               cpus_and(nodemask, nodemask, *cpu_map);
+               if (cpus_empty(nodemask)) {
+                       sched_group_nodes[i] = NULL;
+                       continue;
+               }
+
+               domainspan = sched_domain_node_span(i);
+               cpus_and(domainspan, domainspan, *cpu_map);
+
+               sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+               sched_group_nodes[i] = sg;
+               for_each_cpu_mask(j, nodemask) {
+                       struct sched_domain *sd;
+                       sd = &per_cpu(node_domains, j);
+                       sd->groups = sg;
+                       if (sd->groups == NULL) {
+                               /* Turn off balancing if we have no groups */
+                               sd->flags = 0;
+                       }
+               }
+               if (!sg) {
+                       printk(KERN_WARNING
+                       "Can not alloc domain group for node %d\n", i);
+                       continue;
+               }
+               sg->cpu_power = 0;
+               sg->cpumask = nodemask;
+               cpus_or(covered, covered, nodemask);
+               prev = sg;
+
+               for (j = 0; j < MAX_NUMNODES; j++) {
+                       cpumask_t tmp, notcovered;
+                       int n = (i + j) % MAX_NUMNODES;
+
+                       cpus_complement(notcovered, covered);
+                       cpus_and(tmp, notcovered, *cpu_map);
+                       cpus_and(tmp, tmp, domainspan);
+                       if (cpus_empty(tmp))
+                               break;
+
+                       nodemask = node_to_cpumask(n);
+                       cpus_and(tmp, tmp, nodemask);
+                       if (cpus_empty(tmp))
+                               continue;
+
+                       sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+                       if (!sg) {
+                               printk(KERN_WARNING
+                               "Can not alloc domain group for node %d\n", j);
+                               break;
+                       }
+                       sg->cpu_power = 0;
+                       sg->cpumask = tmp;
+                       cpus_or(covered, covered, tmp);
+                       prev->next = sg;
+                       prev = sg;
+               }
+               prev->next = sched_group_nodes[i];
+       }
 #endif
 
        /* Calculate CPU power for physical packages and nodes */
@@ -5017,14 +5182,46 @@ static void build_sched_domains(const cpumask_t *cpu_map)
                sd->groups->cpu_power = power;
 
 #ifdef CONFIG_NUMA
-               if (i == first_cpu(sd->groups->cpumask)) {
-                       /* Only add "power" once for each physical package. */
-                       sd = &per_cpu(node_domains, i);
-                       sd->groups->cpu_power += power;
+               sd = &per_cpu(allnodes_domains, i);
+               if (sd->groups) {
+                       power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
+                               (cpus_weight(sd->groups->cpumask)-1) / 10;
+                       sd->groups->cpu_power = power;
                }
 #endif
        }
 
+#ifdef CONFIG_NUMA
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               struct sched_group *sg = sched_group_nodes[i];
+               int j;
+
+               if (sg == NULL)
+                       continue;
+next_sg:
+               for_each_cpu_mask(j, sg->cpumask) {
+                       struct sched_domain *sd;
+                       int power;
+
+                       sd = &per_cpu(phys_domains, j);
+                       if (j != first_cpu(sd->groups->cpumask)) {
+                               /*
+                                * Only add "power" once for each
+                                * physical package.
+                                */
+                               continue;
+                       }
+                       power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
+                               (cpus_weight(sd->groups->cpumask)-1) / 10;
+
+                       sg->cpu_power += power;
+               }
+               sg = sg->next;
+               if (sg != sched_group_nodes[i])
+                       goto next_sg;
+       }
+#endif
+
        /* Attach the domains */
        for_each_cpu_mask(i, *cpu_map) {
                struct sched_domain *sd;
@@ -5039,13 +5236,10 @@ static void build_sched_domains(const cpumask_t *cpu_map)
 /*
  * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
  */
-static void arch_init_sched_domains(cpumask_t *cpu_map)
+static void arch_init_sched_domains(const cpumask_t *cpu_map)
 {
        cpumask_t cpu_default_map;
 
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
-       check_sibling_maps();
-#endif
        /*
         * Setup mask for cpus without special case scheduling requirements.
         * For now this just excludes isolated cpus, but could be used to
@@ -5058,10 +5252,47 @@ static void arch_init_sched_domains(cpumask_t *cpu_map)
 
 static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
 {
-       /* Do nothing: everything is statically allocated. */
-}
+#ifdef CONFIG_NUMA
+       int i;
+       int cpu;
+
+       for_each_cpu_mask(cpu, *cpu_map) {
+               struct sched_group *sched_group_allnodes
+                       = sched_group_allnodes_bycpu[cpu];
+               struct sched_group **sched_group_nodes
+                       = sched_group_nodes_bycpu[cpu];
+
+               if (sched_group_allnodes) {
+                       kfree(sched_group_allnodes);
+                       sched_group_allnodes_bycpu[cpu] = NULL;
+               }
+
+               if (!sched_group_nodes)
+                       continue;
+
+               for (i = 0; i < MAX_NUMNODES; i++) {
+                       cpumask_t nodemask = node_to_cpumask(i);
+                       struct sched_group *oldsg, *sg = sched_group_nodes[i];
 
-#endif /* ARCH_HAS_SCHED_DOMAIN */
+                       cpus_and(nodemask, nodemask, *cpu_map);
+                       if (cpus_empty(nodemask))
+                               continue;
+
+                       if (sg == NULL)
+                               continue;
+                       sg = sg->next;
+next_sg:
+                       oldsg = sg;
+                       sg = sg->next;
+                       kfree(oldsg);
+                       if (oldsg != sched_group_nodes[i])
+                               goto next_sg;
+               }
+               kfree(sched_group_nodes);
+               sched_group_nodes_bycpu[cpu] = NULL;
+       }
+#endif
+}
 
 /*
  * Detach sched domains from a group of cpus specified in cpu_map
index d282fea8113815c441417f91c8c0a5374879a4a3..4980a073237ff45ed28c39b38225c40923da0848 100644 (file)
@@ -678,7 +678,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
 
 /* forward decl */
 static void do_notify_parent_cldstop(struct task_struct *tsk,
-                                    struct task_struct *parent,
+                                    int to_self,
                                     int why);
 
 /*
@@ -729,14 +729,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
                        p->signal->group_stop_count = 0;
                        p->signal->flags = SIGNAL_STOP_CONTINUED;
                        spin_unlock(&p->sighand->siglock);
-                       if (p->ptrace & PT_PTRACED)
-                               do_notify_parent_cldstop(p, p->parent,
-                                                        CLD_STOPPED);
-                       else
-                               do_notify_parent_cldstop(
-                                       p->group_leader,
-                                       p->group_leader->real_parent,
-                                                        CLD_STOPPED);
+                       do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED);
                        spin_lock(&p->sighand->siglock);
                }
                rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
@@ -777,14 +770,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
                        p->signal->flags = SIGNAL_STOP_CONTINUED;
                        p->signal->group_exit_code = 0;
                        spin_unlock(&p->sighand->siglock);
-                       if (p->ptrace & PT_PTRACED)
-                               do_notify_parent_cldstop(p, p->parent,
-                                                        CLD_CONTINUED);
-                       else
-                               do_notify_parent_cldstop(
-                                       p->group_leader,
-                                       p->group_leader->real_parent,
-                                                        CLD_CONTINUED);
+                       do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED);
                        spin_lock(&p->sighand->siglock);
                } else {
                        /*
@@ -1380,16 +1366,16 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
        unsigned long flags;
        int ret = 0;
 
-       /*
-        * We need the tasklist lock even for the specific
-        * thread case (when we don't need to follow the group
-        * lists) in order to avoid races with "p->sighand"
-        * going away or changing from under us.
-        */
        BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
-       read_lock(&tasklist_lock);  
+       read_lock(&tasklist_lock);
+
+       if (unlikely(p->flags & PF_EXITING)) {
+               ret = -1;
+               goto out_err;
+       }
+
        spin_lock_irqsave(&p->sighand->siglock, flags);
-       
+
        if (unlikely(!list_empty(&q->list))) {
                /*
                 * If an SI_TIMER entry is already queue just increment
@@ -1399,7 +1385,7 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
                        BUG();
                q->info.si_overrun++;
                goto out;
-       } 
+       }
        /* Short-circuit ignored signals.  */
        if (sig_ignored(p, sig)) {
                ret = 1;
@@ -1414,8 +1400,10 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
 
 out:
        spin_unlock_irqrestore(&p->sighand->siglock, flags);
+out_err:
        read_unlock(&tasklist_lock);
-       return(ret);
+
+       return ret;
 }
 
 int
@@ -1542,14 +1530,20 @@ void do_notify_parent(struct task_struct *tsk, int sig)
        spin_unlock_irqrestore(&psig->siglock, flags);
 }
 
-static void
-do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent,
-                        int why)
+static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why)
 {
        struct siginfo info;
        unsigned long flags;
+       struct task_struct *parent;
        struct sighand_struct *sighand;
 
+       if (to_self)
+               parent = tsk->parent;
+       else {
+               tsk = tsk->group_leader;
+               parent = tsk->real_parent;
+       }
+
        info.si_signo = SIGCHLD;
        info.si_errno = 0;
        info.si_pid = tsk->pid;
@@ -1618,8 +1612,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
                   !(current->ptrace & PT_ATTACHED)) &&
            (likely(current->parent->signal != current->signal) ||
             !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
-               do_notify_parent_cldstop(current, current->parent,
-                                        CLD_TRAPPED);
+               do_notify_parent_cldstop(current, 1, CLD_TRAPPED);
                read_unlock(&tasklist_lock);
                schedule();
        } else {
@@ -1668,25 +1661,25 @@ void ptrace_notify(int exit_code)
 static void
 finish_stop(int stop_count)
 {
+       int to_self;
+
        /*
         * If there are no other threads in the group, or if there is
         * a group stop in progress and we are the last to stop,
         * report to the parent.  When ptraced, every thread reports itself.
         */
-       if (stop_count < 0 || (current->ptrace & PT_PTRACED)) {
-               read_lock(&tasklist_lock);
-               do_notify_parent_cldstop(current, current->parent,
-                                        CLD_STOPPED);
-               read_unlock(&tasklist_lock);
-       }
-       else if (stop_count == 0) {
-               read_lock(&tasklist_lock);
-               do_notify_parent_cldstop(current->group_leader,
-                                        current->group_leader->real_parent,
-                                        CLD_STOPPED);
-               read_unlock(&tasklist_lock);
-       }
+       if (stop_count < 0 || (current->ptrace & PT_PTRACED))
+               to_self = 1;
+       else if (stop_count == 0)
+               to_self = 0;
+       else
+               goto out;
 
+       read_lock(&tasklist_lock);
+       do_notify_parent_cldstop(current, to_self, CLD_STOPPED);
+       read_unlock(&tasklist_lock);
+
+out:
        schedule();
        /*
         * Now we don't run again until continued.
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
new file mode 100644 (file)
index 0000000..7597620
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Detect Soft Lockups
+ *
+ * started by Ingo Molnar, (C) 2005, Red Hat
+ *
+ * this code detects soft lockups: incidents in where on a CPU
+ * the kernel does not reschedule for 10 seconds or more.
+ */
+
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/module.h>
+
+static DEFINE_SPINLOCK(print_lock);
+
+static DEFINE_PER_CPU(unsigned long, timestamp) = 0;
+static DEFINE_PER_CPU(unsigned long, print_timestamp) = 0;
+static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
+
+static int did_panic = 0;
+static int softlock_panic(struct notifier_block *this, unsigned long event,
+                               void *ptr)
+{
+       did_panic = 1;
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+       .notifier_call = softlock_panic,
+};
+
+void touch_softlockup_watchdog(void)
+{
+       per_cpu(timestamp, raw_smp_processor_id()) = jiffies;
+}
+EXPORT_SYMBOL(touch_softlockup_watchdog);
+
+/*
+ * This callback runs from the timer interrupt, and checks
+ * whether the watchdog thread has hung or not:
+ */
+void softlockup_tick(struct pt_regs *regs)
+{
+       int this_cpu = smp_processor_id();
+       unsigned long timestamp = per_cpu(timestamp, this_cpu);
+
+       if (per_cpu(print_timestamp, this_cpu) == timestamp)
+               return;
+
+       /* Do not cause a second panic when there already was one */
+       if (did_panic)
+               return;
+
+       if (time_after(jiffies, timestamp + 10*HZ)) {
+               per_cpu(print_timestamp, this_cpu) = timestamp;
+
+               spin_lock(&print_lock);
+               printk(KERN_ERR "BUG: soft lockup detected on CPU#%d!\n",
+                       this_cpu);
+               show_regs(regs);
+               spin_unlock(&print_lock);
+       }
+}
+
+/*
+ * The watchdog thread - runs every second and touches the timestamp.
+ */
+static int watchdog(void * __bind_cpu)
+{
+       struct sched_param param = { .sched_priority = 99 };
+       int this_cpu = (long) __bind_cpu;
+
+       printk("softlockup thread %d started up.\n", this_cpu);
+
+       sched_setscheduler(current, SCHED_FIFO, &param);
+       current->flags |= PF_NOFREEZE;
+
+       set_current_state(TASK_INTERRUPTIBLE);
+
+       /*
+        * Run briefly once per second - if this gets delayed for
+        * more than 10 seconds then the debug-printout triggers
+        * in softlockup_tick():
+        */
+       while (!kthread_should_stop()) {
+               msleep_interruptible(1000);
+               touch_softlockup_watchdog();
+       }
+       __set_current_state(TASK_RUNNING);
+
+       return 0;
+}
+
+/*
+ * Create/destroy watchdog threads as CPUs come and go:
+ */
+static int __devinit
+cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+       int hotcpu = (unsigned long)hcpu;
+       struct task_struct *p;
+
+       switch (action) {
+       case CPU_UP_PREPARE:
+               BUG_ON(per_cpu(watchdog_task, hotcpu));
+               p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu);
+               if (IS_ERR(p)) {
+                       printk("watchdog for %i failed\n", hotcpu);
+                       return NOTIFY_BAD;
+               }
+               per_cpu(watchdog_task, hotcpu) = p;
+               kthread_bind(p, hotcpu);
+               break;
+       case CPU_ONLINE:
+
+               wake_up_process(per_cpu(watchdog_task, hotcpu));
+               break;
+#ifdef CONFIG_HOTPLUG_CPU
+       case CPU_UP_CANCELED:
+               /* Unbind so it can run.  Fall thru. */
+               kthread_bind(per_cpu(watchdog_task, hotcpu), smp_processor_id());
+       case CPU_DEAD:
+               p = per_cpu(watchdog_task, hotcpu);
+               per_cpu(watchdog_task, hotcpu) = NULL;
+               kthread_stop(p);
+               break;
+#endif /* CONFIG_HOTPLUG_CPU */
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata cpu_nfb = {
+       .notifier_call = cpu_callback
+};
+
+__init void spawn_softlockup_task(void)
+{
+       void *cpu = (void *)(long)smp_processor_id();
+
+       cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+       register_cpu_notifier(&cpu_nfb);
+
+       notifier_chain_register(&panic_notifier_list, &panic_block);
+}
+
index 0bcaed6560ac19f72ab308b2fe92839238e9ba70..c80412be2302c6321898b57ef3a99d10a1c21a68 100644 (file)
@@ -1711,7 +1711,6 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
                          unsigned long arg4, unsigned long arg5)
 {
        long error;
-       int sig;
 
        error = security_task_prctl(option, arg2, arg3, arg4, arg5);
        if (error)
@@ -1719,12 +1718,11 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 
        switch (option) {
                case PR_SET_PDEATHSIG:
-                       sig = arg2;
-                       if (!valid_signal(sig)) {
+                       if (!valid_signal(arg2)) {
                                error = -EINVAL;
                                break;
                        }
-                       current->pdeath_signal = sig;
+                       current->pdeath_signal = arg2;
                        break;
                case PR_GET_PDEATHSIG:
                        error = put_user(current->pdeath_signal, (int __user *)arg2);
index 5377f40723ff0dc37f13897847ea040f8c317292..13e2b513be019bf0b8b6b9218e4f268fff95f58a 100644 (file)
@@ -950,6 +950,7 @@ void do_timer(struct pt_regs *regs)
 {
        jiffies_64++;
        update_times();
+       softlockup_tick(regs);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
@@ -1428,7 +1429,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
        }
 }
 
-static inline u64 time_interpolator_get_counter(void)
+static inline u64 time_interpolator_get_counter(int writelock)
 {
        unsigned int src = time_interpolator->source;
 
@@ -1442,6 +1443,15 @@ static inline u64 time_interpolator_get_counter(void)
                        now = time_interpolator_get_cycles(src);
                        if (lcycle && time_after(lcycle, now))
                                return lcycle;
+
+                       /* When holding the xtime write lock, there's no need
+                        * to add the overhead of the cmpxchg.  Readers are
+                        * force to retry until the write lock is released.
+                        */
+                       if (writelock) {
+                               time_interpolator->last_cycle = now;
+                               return now;
+                       }
                        /* Keep track of the last timer value returned. The use of cmpxchg here
                         * will cause contention in an SMP environment.
                         */
@@ -1455,7 +1465,7 @@ static inline u64 time_interpolator_get_counter(void)
 void time_interpolator_reset(void)
 {
        time_interpolator->offset = 0;
-       time_interpolator->last_counter = time_interpolator_get_counter();
+       time_interpolator->last_counter = time_interpolator_get_counter(1);
 }
 
 #define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
@@ -1467,7 +1477,7 @@ unsigned long time_interpolator_get_offset(void)
                return 0;
 
        return time_interpolator->offset +
-               GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
+               GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
 }
 
 #define INTERPOLATOR_ADJUST 65536
@@ -1490,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec)
         * and the tuning logic insures that.
          */
 
-       counter = time_interpolator_get_counter();
+       counter = time_interpolator_get_counter(1);
        offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
 
        if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
index c7e36d4a70cabdb9711640575e68ac86d68a7da1..91bacb13a7e2fec56f5067f12e0b97c1043c30b7 100644 (file)
@@ -308,10 +308,9 @@ struct workqueue_struct *__create_workqueue(const char *name,
        struct workqueue_struct *wq;
        struct task_struct *p;
 
-       wq = kmalloc(sizeof(*wq), GFP_KERNEL);
+       wq = kzalloc(sizeof(*wq), GFP_KERNEL);
        if (!wq)
                return NULL;
-       memset(wq, 0, sizeof(*wq));
 
        wq->name = name;
        /* We don't need the distraction of CPUs appearing and vanishing. */
@@ -499,7 +498,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
        case CPU_UP_PREPARE:
                /* Create a new workqueue thread for it. */
                list_for_each_entry(wq, &workqueues, list) {
-                       if (create_workqueue_thread(wq, hotcpu) < 0) {
+                       if (!create_workqueue_thread(wq, hotcpu)) {
                                printk("workqueue for %i failed\n", hotcpu);
                                return NOTIFY_BAD;
                        }
index 299f7f3b5b0871fdd332a647f83ea54d2ddf059b..3754c9a8f5c8e1e3fccebf2d0f282fd5eda6bcb4 100644 (file)
@@ -46,6 +46,25 @@ config LOG_BUF_SHIFT
                     13 =>  8 KB
                     12 =>  4 KB
 
+config DETECT_SOFTLOCKUP
+       bool "Detect Soft Lockups"
+       depends on DEBUG_KERNEL
+       default y
+       help
+         Say Y here to enable the kernel to detect "soft lockups",
+         which are bugs that cause the kernel to loop in kernel
+         mode for more than 10 seconds, without giving other tasks a
+         chance to run.
+
+         When a soft-lockup is detected, the kernel will print the
+         current stack trace (which you should report), but the
+         system will stay locked up. This feature has negligible
+         overhead.
+
+         (Note that "hard lockups" are separate type of bugs that
+          can be detected via the NMI-watchdog, on platforms that
+          support it.)
+
 config SCHEDSTATS
        bool "Collect scheduler statistics"
        depends on DEBUG_KERNEL && PROC_FS
index 10bed1c8c3c3012b861a055eaaf095af7906e8e5..b972dd29289d6669fd353dcd2b3118cd93ab87cb 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
+ * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -51,7 +52,7 @@ struct radix_tree_node {
 };
 
 struct radix_tree_path {
-       struct radix_tree_node *node, **slot;
+       struct radix_tree_node *node;
        int offset;
 };
 
@@ -227,7 +228,7 @@ out:
 int radix_tree_insert(struct radix_tree_root *root,
                        unsigned long index, void *item)
 {
-       struct radix_tree_node *node = NULL, *tmp, **slot;
+       struct radix_tree_node *node = NULL, *slot;
        unsigned int height, shift;
        int offset;
        int error;
@@ -240,38 +241,42 @@ int radix_tree_insert(struct radix_tree_root *root,
                        return error;
        }
 
-       slot = &root->rnode;
+       slot = root->rnode;
        height = root->height;
        shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
        offset = 0;                     /* uninitialised var warning */
        while (height > 0) {
-               if (*slot == NULL) {
+               if (slot == NULL) {
                        /* Have to add a child node.  */
-                       if (!(tmp = radix_tree_node_alloc(root)))
+                       if (!(slot = radix_tree_node_alloc(root)))
                                return -ENOMEM;
-                       *slot = tmp;
-                       if (node)
+                       if (node) {
+                               node->slots[offset] = slot;
                                node->count++;
+                       } else
+                               root->rnode = slot;
                }
 
                /* Go a level down */
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-               node = *slot;
-               slot = (struct radix_tree_node **)(node->slots + offset);
+               node = slot;
+               slot = node->slots[offset];
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
 
-       if (*slot != NULL)
+       if (slot != NULL)
                return -EEXIST;
+
        if (node) {
                node->count++;
+               node->slots[offset] = item;
                BUG_ON(tag_get(node, 0, offset));
                BUG_ON(tag_get(node, 1, offset));
-       }
+       } else
+               root->rnode = item;
 
-       *slot = item;
        return 0;
 }
 EXPORT_SYMBOL(radix_tree_insert);
@@ -286,27 +291,25 @@ EXPORT_SYMBOL(radix_tree_insert);
 void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
 {
        unsigned int height, shift;
-       struct radix_tree_node **slot;
+       struct radix_tree_node *slot;
 
        height = root->height;
        if (index > radix_tree_maxindex(height))
                return NULL;
 
        shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-       slot = &root->rnode;
+       slot = root->rnode;
 
        while (height > 0) {
-               if (*slot == NULL)
+               if (slot == NULL)
                        return NULL;
 
-               slot = (struct radix_tree_node **)
-                       ((*slot)->slots +
-                               ((index >> shift) & RADIX_TREE_MAP_MASK));
+               slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK];
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
 
-       return *slot;
+       return slot;
 }
 EXPORT_SYMBOL(radix_tree_lookup);
 
@@ -326,27 +329,27 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
                        unsigned long index, int tag)
 {
        unsigned int height, shift;
-       struct radix_tree_node **slot;
+       struct radix_tree_node *slot;
 
        height = root->height;
        if (index > radix_tree_maxindex(height))
                return NULL;
 
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
-       slot = &root->rnode;
+       slot = root->rnode;
 
        while (height > 0) {
                int offset;
 
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-               tag_set(*slot, tag, offset);
-               slot = (struct radix_tree_node **)((*slot)->slots + offset);
-               BUG_ON(*slot == NULL);
+               tag_set(slot, tag, offset);
+               slot = slot->slots[offset];
+               BUG_ON(slot == NULL);
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
 
-       return *slot;
+       return slot;
 }
 EXPORT_SYMBOL(radix_tree_tag_set);
 
@@ -367,6 +370,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
                        unsigned long index, int tag)
 {
        struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
+       struct radix_tree_node *slot;
        unsigned int height, shift;
        void *ret = NULL;
 
@@ -376,38 +380,37 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
 
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
        pathp->node = NULL;
-       pathp->slot = &root->rnode;
+       slot = root->rnode;
 
        while (height > 0) {
                int offset;
 
-               if (*pathp->slot == NULL)
+               if (slot == NULL)
                        goto out;
 
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
                pathp[1].offset = offset;
-               pathp[1].node = *pathp[0].slot;
-               pathp[1].slot = (struct radix_tree_node **)
-                               (pathp[1].node->slots + offset);
+               pathp[1].node = slot;
+               slot = slot->slots[offset];
                pathp++;
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
 
-       ret = *pathp[0].slot;
+       ret = slot;
        if (ret == NULL)
                goto out;
 
        do {
                int idx;
 
-               tag_clear(pathp[0].node, tag, pathp[0].offset);
+               tag_clear(pathp->node, tag, pathp->offset);
                for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
-                       if (pathp[0].node->tags[tag][idx])
+                       if (pathp->node->tags[tag][idx])
                                goto out;
                }
                pathp--;
-       } while (pathp[0].node);
+       } while (pathp->node);
 out:
        return ret;
 }
@@ -415,21 +418,22 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
 
 #ifndef __KERNEL__     /* Only the test harness uses this at present */
 /**
- *     radix_tree_tag_get - get a tag on a radix tree node
- *     @root:          radix tree root
- *     @index:         index key
- *     @tag:           tag index
+ * radix_tree_tag_get - get a tag on a radix tree node
+ * @root:              radix tree root
+ * @index:             index key
+ * @tag:               tag index
  *
- *     Return the search tag corresponging to @index in the radix tree.
+ * Return values:
  *
- *     Returns zero if the tag is unset, or if there is no corresponding item
- *     in the tree.
+ *  0: tag not present
+ *  1: tag present, set
+ * -1: tag present, unset
  */
 int radix_tree_tag_get(struct radix_tree_root *root,
                        unsigned long index, int tag)
 {
        unsigned int height, shift;
-       struct radix_tree_node **slot;
+       struct radix_tree_node *slot;
        int saw_unset_tag = 0;
 
        height = root->height;
@@ -437,12 +441,12 @@ int radix_tree_tag_get(struct radix_tree_root *root,
                return 0;
 
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
-       slot = &root->rnode;
+       slot = root->rnode;
 
        for ( ; ; ) {
                int offset;
 
-               if (*slot == NULL)
+               if (slot == NULL)
                        return 0;
 
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
@@ -451,15 +455,15 @@ int radix_tree_tag_get(struct radix_tree_root *root,
                 * This is just a debug check.  Later, we can bale as soon as
                 * we see an unset tag.
                 */
-               if (!tag_get(*slot, tag, offset))
+               if (!tag_get(slot, tag, offset))
                        saw_unset_tag = 1;
                if (height == 1) {
-                       int ret = tag_get(*slot, tag, offset);
+                       int ret = tag_get(slot, tag, offset);
 
                        BUG_ON(ret && saw_unset_tag);
-                       return ret;
+                       return ret ? 1 : -1;
                }
-               slot = (struct radix_tree_node **)((*slot)->slots + offset);
+               slot = slot->slots[offset];
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
@@ -472,17 +476,21 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
        unsigned int max_items, unsigned long *next_index)
 {
        unsigned int nr_found = 0;
-       unsigned int shift;
-       unsigned int height = root->height;
+       unsigned int shift, height;
        struct radix_tree_node *slot;
+       unsigned long i;
+
+       height = root->height;
+       if (height == 0)
+               goto out;
 
        shift = (height-1) * RADIX_TREE_MAP_SHIFT;
        slot = root->rnode;
 
-       while (height > 0) {
-               unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK;
+       for ( ; height > 1; height--) {
 
-               for ( ; i < RADIX_TREE_MAP_SIZE; i++) {
+               for (i = (index >> shift) & RADIX_TREE_MAP_MASK ;
+                               i < RADIX_TREE_MAP_SIZE; i++) {
                        if (slot->slots[i] != NULL)
                                break;
                        index &= ~((1UL << shift) - 1);
@@ -492,22 +500,20 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
                }
                if (i == RADIX_TREE_MAP_SIZE)
                        goto out;
-               height--;
-               if (height == 0) {      /* Bottom level: grab some items */
-                       unsigned long j = index & RADIX_TREE_MAP_MASK;
 
-                       for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
-                               index++;
-                               if (slot->slots[j]) {
-                                       results[nr_found++] = slot->slots[j];
-                                       if (nr_found == max_items)
-                                               goto out;
-                               }
-                       }
-               }
                shift -= RADIX_TREE_MAP_SHIFT;
                slot = slot->slots[i];
        }
+
+       /* Bottom level: grab some items */
+       for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
+               index++;
+               if (slot->slots[i]) {
+                       results[nr_found++] = slot->slots[i];
+                       if (nr_found == max_items)
+                               goto out;
+               }
+       }
 out:
        *next_index = index;
        return nr_found;
@@ -655,6 +661,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 {
        struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
        struct radix_tree_path *orig_pathp;
+       struct radix_tree_node *slot;
        unsigned int height, shift;
        void *ret = NULL;
        char tags[RADIX_TREE_TAGS];
@@ -666,25 +673,23 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
        pathp->node = NULL;
-       pathp->slot = &root->rnode;
+       slot = root->rnode;
 
-       while (height > 0) {
+       for ( ; height > 0; height--) {
                int offset;
 
-               if (*pathp->slot == NULL)
+               if (slot == NULL)
                        goto out;
 
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
                pathp[1].offset = offset;
-               pathp[1].node = *pathp[0].slot;
-               pathp[1].slot = (struct radix_tree_node **)
-                               (pathp[1].node->slots + offset);
+               pathp[1].node = slot;
+               slot = slot->slots[offset];
                pathp++;
                shift -= RADIX_TREE_MAP_SHIFT;
-               height--;
        }
 
-       ret = *pathp[0].slot;
+       ret = slot;
        if (ret == NULL)
                goto out;
 
@@ -704,10 +709,10 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
                        if (tags[tag])
                                continue;
 
-                       tag_clear(pathp[0].node, tag, pathp[0].offset);
+                       tag_clear(pathp->node, tag, pathp->offset);
 
                        for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
-                               if (pathp[0].node->tags[tag][idx]) {
+                               if (pathp->node->tags[tag][idx]) {
                                        tags[tag] = 1;
                                        nr_cleared_tags--;
                                        break;
@@ -715,18 +720,19 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
                        }
                }
                pathp--;
-       } while (pathp[0].node && nr_cleared_tags);
+       } while (pathp->node && nr_cleared_tags);
 
-       pathp = orig_pathp;
-       *pathp[0].slot = NULL;
-       while (pathp[0].node && --pathp[0].node->count == 0) {
-               pathp--;
-               BUG_ON(*pathp[0].slot == NULL);
-               *pathp[0].slot = NULL;
-               radix_tree_node_free(pathp[1].node);
+       /* Now free the nodes we do not need anymore */
+       for (pathp = orig_pathp; pathp->node; pathp--) {
+               pathp->node->slots[pathp->offset] = NULL;
+               if (--pathp->node->count)
+                       goto out;
+
+               /* Node with zero slots in use so free it */
+               radix_tree_node_free(pathp->node);
        }
-       if (root->rnode == NULL)
-               root->height = 0;
+       root->rnode = NULL;
+       root->height = 0;
 out:
        return ret;
 }
index 404319477e71d61679166bc954ed246719affe89..12334aecf8ad3d74b62f93da8db6f529e981d51d 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -61,7 +61,7 @@ pgprot_t protection_map[16] = {
 
 int sysctl_overcommit_memory = OVERCOMMIT_GUESS;  /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50;      /* default is 50% */
-int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
+int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
 
 /*
@@ -203,13 +203,6 @@ static void remove_vm_struct(struct vm_area_struct *vma)
        kmem_cache_free(vm_area_cachep, vma);
 }
 
-/*
- *  sys_brk() for the most part doesn't need the global kernel
- *  lock, except when an application is doing something nasty
- *  like trying to un-brk an area that has already been mapped
- *  to a regular file.  in this case, the unmapping will need
- *  to invoke file system routines that need the global lock.
- */
 asmlinkage unsigned long sys_brk(unsigned long brk)
 {
        unsigned long rlim, retval;
index 1e56076672f5870e9766753270d77442e5743ac9..5ec8da12cfd986523bb1968ffa9f2ea0be064868 100644 (file)
@@ -6,8 +6,8 @@
  *     for goading me into coding this file...
  *
  *  The routines in this file are used to kill a process when
- *  we're seriously out of memory. This gets called from kswapd()
- *  in linux/mm/vmscan.c when we really run out of memory.
+ *  we're seriously out of memory. This gets called from __alloc_pages()
+ *  in mm/page_alloc.c when we really run out of memory.
  *
  *  Since we won't call these routines often (on a well-configured
  *  machine) this file will double as a 'coding guide' and a signpost
 #include <linux/swap.h>
 #include <linux/timex.h>
 #include <linux/jiffies.h>
+#include <linux/cpuset.h>
 
 /* #define DEBUG */
 
 /**
  * oom_badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
- * @p: current uptime in seconds
+ * @uptime: current uptime in seconds
  *
  * The formula used is relatively simple and documented inline in the
  * function. The main rationale is that we want to select a good task
@@ -57,9 +58,9 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
 
        /*
         * Processes which fork a lot of child processes are likely
-        * a good choice. We add the vmsize of the childs if they
+        * a good choice. We add the vmsize of the children if they
         * have an own mm. This prevents forking servers to flood the
-        * machine with an endless amount of childs
+        * machine with an endless amount of children
         */
        list_for_each(tsk, &p->children) {
                struct task_struct *chld;
@@ -143,28 +144,36 @@ static struct task_struct * select_bad_process(void)
        struct timespec uptime;
 
        do_posix_clock_monotonic_gettime(&uptime);
-       do_each_thread(g, p)
+       do_each_thread(g, p) {
+               unsigned long points;
+               int releasing;
+
                /* skip the init task with pid == 1 */
-               if (p->pid > 1 && p->oomkilladj != OOM_DISABLE) {
-                       unsigned long points;
-
-                       /*
-                        * This is in the process of releasing memory so wait it
-                        * to finish before killing some other task by mistake.
-                        */
-                       if ((unlikely(test_tsk_thread_flag(p, TIF_MEMDIE)) || (p->flags & PF_EXITING)) &&
-                           !(p->flags & PF_DEAD))
-                               return ERR_PTR(-1UL);
-                       if (p->flags & PF_SWAPOFF)
-                               return p;
-
-                       points = badness(p, uptime.tv_sec);
-                       if (points > maxpoints || !chosen) {
-                               chosen = p;
-                               maxpoints = points;
-                       }
+               if (p->pid == 1)
+                       continue;
+               if (p->oomkilladj == OOM_DISABLE)
+                       continue;
+               /* If p's nodes don't overlap ours, it won't help to kill p. */
+               if (!cpuset_excl_nodes_overlap(p))
+                       continue;
+
+               /*
+                * This is in the process of releasing memory so for wait it
+                * to finish before killing some other task by mistake.
+                */
+               releasing = test_tsk_thread_flag(p, TIF_MEMDIE) ||
+                                               p->flags & PF_EXITING;
+               if (releasing && !(p->flags & PF_DEAD))
+                       return ERR_PTR(-1UL);
+               if (p->flags & PF_SWAPOFF)
+                       return p;
+
+               points = badness(p, uptime.tv_sec);
+               if (points > maxpoints || !chosen) {
+                       chosen = p;
+                       maxpoints = points;
                }
-       while_each_thread(g, p);
+       while_each_thread(g, p);
        return chosen;
 }
 
@@ -189,7 +198,8 @@ static void __oom_kill_task(task_t *p)
                return;
        }
        task_unlock(p);
-       printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
+       printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n",
+                                                       p->pid, p->comm);
 
        /*
         * We give our sacrificial lamb high priority and access to
index b06a9636d971d2a3e89dcab022047b24753d0479..3974fd81d27c0de38a12a299e6f6b6dd2645cbf7 100644 (file)
  * MCD - HACK: Find somewhere to initialize this EARLY, or make this
  * initializer cleaner
  */
-nodemask_t node_online_map = { { [0] = 1UL } };
+nodemask_t node_online_map __read_mostly = { { [0] = 1UL } };
 EXPORT_SYMBOL(node_online_map);
-nodemask_t node_possible_map = NODE_MASK_ALL;
+nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
 EXPORT_SYMBOL(node_possible_map);
-struct pglist_data *pgdat_list;
-unsigned long totalram_pages;
-unsigned long totalhigh_pages;
+struct pglist_data *pgdat_list __read_mostly;
+unsigned long totalram_pages __read_mostly;
+unsigned long totalhigh_pages __read_mostly;
 long nr_swap_pages;
 
 /*
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(nr_swap_pages);
  * Used by page_zone() to look up the address of the struct zone whose
  * id is encoded in the upper bits of page->flags
  */
-struct zone *zone_table[1 << ZONETABLE_SHIFT];
+struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly;
 EXPORT_SYMBOL(zone_table);
 
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
@@ -806,11 +806,14 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
        classzone_idx = zone_idx(zones[0]);
 
 restart:
-       /* Go through the zonelist once, looking for a zone with enough free */
+       /*
+        * Go through the zonelist once, looking for a zone with enough free.
+        * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
+        */
        for (i = 0; (z = zones[i]) != NULL; i++) {
                int do_reclaim = should_reclaim_zone(z, gfp_mask);
 
-               if (!cpuset_zone_allowed(z))
+               if (!cpuset_zone_allowed(z, __GFP_HARDWALL))
                        continue;
 
                /*
@@ -845,6 +848,7 @@ zone_reclaim_retry:
         *
         * This is the last chance, in general, before the goto nopage.
         * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
+        * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
         */
        for (i = 0; (z = zones[i]) != NULL; i++) {
                if (!zone_watermark_ok(z, order, z->pages_min,
@@ -852,7 +856,7 @@ zone_reclaim_retry:
                                       gfp_mask & __GFP_HIGH))
                        continue;
 
-               if (wait && !cpuset_zone_allowed(z))
+               if (wait && !cpuset_zone_allowed(z, gfp_mask))
                        continue;
 
                page = buffered_rmqueue(z, order, gfp_mask);
@@ -867,7 +871,7 @@ zone_reclaim_retry:
                if (!(gfp_mask & __GFP_NOMEMALLOC)) {
                        /* go through the zonelist yet again, ignoring mins */
                        for (i = 0; (z = zones[i]) != NULL; i++) {
-                               if (!cpuset_zone_allowed(z))
+                               if (!cpuset_zone_allowed(z, gfp_mask))
                                        continue;
                                page = buffered_rmqueue(z, order, gfp_mask);
                                if (page)
@@ -903,7 +907,7 @@ rebalance:
                                               gfp_mask & __GFP_HIGH))
                                continue;
 
-                       if (!cpuset_zone_allowed(z))
+                       if (!cpuset_zone_allowed(z, gfp_mask))
                                continue;
 
                        page = buffered_rmqueue(z, order, gfp_mask);
@@ -922,7 +926,7 @@ rebalance:
                                               classzone_idx, 0, 0))
                                continue;
 
-                       if (!cpuset_zone_allowed(z))
+                       if (!cpuset_zone_allowed(z, __GFP_HARDWALL))
                                continue;
 
                        page = buffered_rmqueue(z, order, gfp_mask);
index b840e7c6ea740433d1851c379705efe191259e1d..d0b50034e245a0095c7d359388b59676af0bdb59 100644 (file)
@@ -540,6 +540,7 @@ void handle_ra_miss(struct address_space *mapping,
 {
        ra->flags |= RA_FLAG_MISS;
        ra->flags &= ~RA_FLAG_INCACHE;
+       ra->cache_hit = 0;
 }
 
 /*
index bdc4bbb6ddbb84f01d625870789695aa8cd61b07..db2c9e8d99095ace5bae8324f2387b9ebdbaf7c6 100644 (file)
@@ -180,7 +180,7 @@ static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
-static struct backing_dev_info shmem_backing_dev_info = {
+static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
        .ra_pages       = 0,    /* No readahead */
        .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
        .unplug_io_fn   = default_unplug_io_fn,
index a9ff4f7f9860b2f1f37891fe4fe8c50a5caa637d..d7c4443991fe8e29e16dfaffa30a1711c6844c30 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2558,24 +2558,18 @@ void kmem_cache_free(kmem_cache_t *cachep, void *objp)
 EXPORT_SYMBOL(kmem_cache_free);
 
 /**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
  */
-void *kcalloc(size_t n, size_t size, unsigned int __nocast flags)
+void *kzalloc(size_t size, unsigned int __nocast flags)
 {
-       void *ret = NULL;
-
-       if (n != 0 && size > INT_MAX / n)
-               return ret;
-
-       ret = kmalloc(n * size, flags);
+       void *ret = kmalloc(size, flags);
        if (ret)
-               memset(ret, 0, n * size);
+               memset(ret, 0, size);
        return ret;
 }
-EXPORT_SYMBOL(kcalloc);
+EXPORT_SYMBOL(kzalloc);
 
 /**
  * kfree - free previously allocated memory
index 0095533cdde963143f7988c048a110519cc50a31..a740778f688da277d35eb0d15a60168257dbe42e 100644 (file)
@@ -894,7 +894,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
                if (zone->present_pages == 0)
                        continue;
 
-               if (!cpuset_zone_allowed(zone))
+               if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
                        continue;
 
                zone->temp_priority = sc->priority;
@@ -940,7 +940,7 @@ int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
        for (i = 0; zones[i] != NULL; i++) {
                struct zone *zone = zones[i];
 
-               if (!cpuset_zone_allowed(zone))
+               if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
                        continue;
 
                zone->temp_priority = DEF_PRIORITY;
@@ -986,7 +986,7 @@ out:
        for (i = 0; zones[i] != 0; i++) {
                struct zone *zone = zones[i];
 
-               if (!cpuset_zone_allowed(zone))
+               if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
                        continue;
 
                zone->prev_priority = zone->temp_priority;
@@ -1256,7 +1256,7 @@ void wakeup_kswapd(struct zone *zone, int order)
                return;
        if (pgdat->kswapd_max_order < order)
                pgdat->kswapd_max_order = order;
-       if (!cpuset_zone_allowed(zone))
+       if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
                return;
        if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
                return;
index ea43dfb774e228c3e044c283a7c6be11fd4195eb..ed705ddad56be0e9bb6b69580b681b1e5c91f6d0 100644 (file)
@@ -1874,6 +1874,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v)
 static int ax25_info_show(struct seq_file *seq, void *v)
 {
        ax25_cb *ax25 = v;
+       char buf[11];
        int k;
 
 
@@ -1885,13 +1886,13 @@ static int ax25_info_show(struct seq_file *seq, void *v)
        seq_printf(seq, "%8.8lx %s %s%s ",
                   (long) ax25,
                   ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
-                  ax2asc(&ax25->source_addr),
+                  ax2asc(buf, &ax25->source_addr),
                   ax25->iamdigi? "*":"");
-       seq_printf(seq, "%s", ax2asc(&ax25->dest_addr));
+       seq_printf(seq, "%s", ax2asc(buf, &ax25->dest_addr));
 
        for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
                seq_printf(seq, ",%s%s",
-                          ax2asc(&ax25->digipeat->calls[k]),
+                          ax2asc(buf, &ax25->digipeat->calls[k]),
                           ax25->digipeat->repeated[k]? "*":"");
        }
 
index f4fa6dfb846e6aa4cf2359584e4efed452dc8f58..dca179daf4150d3202e290709e611e13505dbd7d 100644 (file)
@@ -36,9 +36,8 @@ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
 /*
  *     ax25 -> ascii conversion
  */
-char *ax2asc(ax25_address *a)
+char *ax2asc(char *buf, ax25_address *a)
 {
-       static char buf[11];
        char c, *s;
        int n;
 
index c288526da4ce194c65f49878f40cd686cedd1216..26b77d9722201232d7adfcb2bb27dcc3fb90e246 100644 (file)
@@ -298,6 +298,8 @@ static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
 
 static int ax25_rt_seq_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
+
        if (v == SEQ_START_TOKEN)
                seq_puts(seq, "callsign  dev  mode digipeaters\n");
        else {
@@ -308,7 +310,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
                if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
                        callsign = "default";
                else
-                       callsign = ax2asc(&ax25_rt->callsign);
+                       callsign = ax2asc(buf, &ax25_rt->callsign);
 
                seq_printf(seq, "%-9s %-4s",
                        callsign,
@@ -328,7 +330,8 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
 
                if (ax25_rt->digipeat != NULL)
                        for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
-                               seq_printf(seq, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
+                               seq_printf(seq, " %s",
+                                    ax2asc(buf, &ax25_rt->digipeat->calls[i]));
 
                seq_puts(seq, "\n");
        }
index a8b3822f3ee42155032c914c31e80e1354b1fbfb..d53cc8615865f4b2e9ea7cc82452b57ddbbcef99 100644 (file)
@@ -168,12 +168,14 @@ static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
 
 static int ax25_uid_seq_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
+
        if (v == SEQ_START_TOKEN)
                seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
        else {
                struct ax25_uid_assoc *pt = v;
 
-               seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(&pt->call));
+               seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call));
        }
        return 0;
 }
index c13594579bfb193009e22e2fbc0635cfd3a0b14b..ac63b56e23b29c45113df81fa226bc2c9568d758 100644 (file)
@@ -341,11 +341,11 @@ set_rcvbuf:
                                sock_reset_flag(sk, SOCK_LINGER);
                        else {
 #if (BITS_PER_LONG == 32)
-                               if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
+                               if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
                                        sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
                                else
 #endif
-                                       sk->sk_lingertime = ling.l_linger * HZ;
+                                       sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
                                sock_set_flag(sk, SOCK_LINGER);
                        }
                        break;
@@ -1529,6 +1529,8 @@ EXPORT_SYMBOL(proto_register);
 void proto_unregister(struct proto *prot)
 {
        write_lock(&proto_list_lock);
+       list_del(&prot->node);
+       write_unlock(&proto_list_lock);
 
        if (prot->slab != NULL) {
                kmem_cache_destroy(prot->slab);
@@ -1550,9 +1552,6 @@ void proto_unregister(struct proto *prot)
                kfree(name);
                prot->twsk_slab = NULL;
        }
-
-       list_del(&prot->node);
-       write_unlock(&proto_list_lock);
 }
 
 EXPORT_SYMBOL(proto_unregister);
index 9e6e683cc34d4396560b19bfc9b1d4f2bca2f9df..e7d26d9943c2d5aea36b465304b8b98db12a7abd 100644 (file)
@@ -457,7 +457,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 
        if (pskb_pull(skb, ihl) == NULL)
                goto err;
-       if (pskb_trim(skb, end-offset))
+       if (pskb_trim_rcsum(skb, end-offset))
                goto err;
 
        /* Find out which fragments are in front and at the back of us
index e046f55218142d091ba71da87e6af0747bad7277..30aa8e2ee214263c6b1d124f5566eb56c804bf58 100644 (file)
@@ -34,6 +34,7 @@ config IP_NF_CT_ACCT
 
 config IP_NF_CONNTRACK_MARK
        bool  'Connection mark tracking support'
+       depends on IP_NF_CONNTRACK
        help
          This option enables support for connection marks, used by the
          `CONNMARK' target and `connmark' match. Similar to the mark value
@@ -85,6 +86,25 @@ config IP_NF_IRC
 
          To compile it as a module, choose M here.  If unsure, say Y.
 
+config IP_NF_NETBIOS_NS
+       tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
+       depends on IP_NF_CONNTRACK && EXPERIMENTAL
+       help
+         NetBIOS name service requests are sent as broadcast messages from an
+         unprivileged port and responded to with unicast messages to the
+         same port. This make them hard to firewall properly because connection
+         tracking doesn't deal with broadcasts. This helper tracks locally
+         originating NetBIOS name service requests and the corresponding
+         responses. It relies on correct IP address configuration, specifically
+         netmask and broadcast address. When properly configured, the output
+         of "ip address show" should look similar to this:
+
+         $ ip -4 address show eth0
+         4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
+             inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0
+         
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_TFTP
        tristate "TFTP protocol support"
        depends on IP_NF_CONNTRACK
index a7bd38f5052202c8230e572f27080b39c40db416..1ba0db746817cf2809e80c073899c8a37ba3d50c 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
 
 # NAT helpers 
 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
index be4c9eb3243f94698f35de5af6d11aad219137a7..dc20881004bc57731b4ae348b8272d26622b863e 100644 (file)
@@ -108,6 +108,7 @@ static int help(struct sk_buff **pskb,
                }
 
                exp->expectfn = NULL;
+               exp->flags = 0;
 
                exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
                exp->tuple.src.u.tcp.port = 0;
index a0648600190e1b16827e0f363ea138b759f9f656..19cba16e6e1e587c5281a997ac67ec7fa291da8a 100644 (file)
@@ -197,7 +197,7 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
 
 
 /* ip_conntrack_expect helper functions */
-static void unlink_expect(struct ip_conntrack_expect *exp)
+void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
 {
        ASSERT_WRITE_LOCK(&ip_conntrack_lock);
        IP_NF_ASSERT(!timer_pending(&exp->timeout));
@@ -207,18 +207,12 @@ static void unlink_expect(struct ip_conntrack_expect *exp)
        ip_conntrack_expect_put(exp);
 }
 
-void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp)
-{
-       unlink_expect(exp);
-       ip_conntrack_expect_put(exp);
-}
-
 static void expectation_timed_out(unsigned long ul_expect)
 {
        struct ip_conntrack_expect *exp = (void *)ul_expect;
 
        write_lock_bh(&ip_conntrack_lock);
-       unlink_expect(exp);
+       ip_ct_unlink_expect(exp);
        write_unlock_bh(&ip_conntrack_lock);
        ip_conntrack_expect_put(exp);
 }
@@ -264,10 +258,14 @@ find_expectation(const struct ip_conntrack_tuple *tuple)
                   master ct never got confirmed, we'd hold a reference to it
                   and weird things would happen to future packets). */
                if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
-                   && is_confirmed(i->master)
-                   && del_timer(&i->timeout)) {
-                       unlink_expect(i);
-                       return i;
+                   && is_confirmed(i->master)) {
+                       if (i->flags & IP_CT_EXPECT_PERMANENT) {
+                               atomic_inc(&i->use);
+                               return i;
+                       } else if (del_timer(&i->timeout)) {
+                               ip_ct_unlink_expect(i);
+                               return i;
+                       }
                }
        }
        return NULL;
@@ -284,7 +282,7 @@ void ip_ct_remove_expectations(struct ip_conntrack *ct)
 
        list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) {
                if (i->master == ct && del_timer(&i->timeout)) {
-                       unlink_expect(i);
+                       ip_ct_unlink_expect(i);
                        ip_conntrack_expect_put(i);
                }
        }
@@ -925,7 +923,7 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
        /* choose the the oldest expectation to evict */
        list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
                if (expect_matches(i, exp) && del_timer(&i->timeout)) {
-                       unlink_expect(i);
+                       ip_ct_unlink_expect(i);
                        write_unlock_bh(&ip_conntrack_lock);
                        ip_conntrack_expect_put(i);
                        return;
@@ -934,6 +932,9 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
        write_unlock_bh(&ip_conntrack_lock);
 }
 
+/* We don't increase the master conntrack refcount for non-fulfilled
+ * conntracks. During the conntrack destruction, the expectations are 
+ * always killed before the conntrack itself */
 struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
 {
        struct ip_conntrack_expect *new;
@@ -944,17 +945,14 @@ struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
                return NULL;
        }
        new->master = me;
-       atomic_inc(&new->master->ct_general.use);
        atomic_set(&new->use, 1);
        return new;
 }
 
 void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
 {
-       if (atomic_dec_and_test(&exp->use)) {
-               ip_conntrack_put(exp->master);
+       if (atomic_dec_and_test(&exp->use))
                kmem_cache_free(ip_conntrack_expect_cachep, exp);
-       }
 }
 
 static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
@@ -982,7 +980,7 @@ static void evict_oldest_expect(struct ip_conntrack *master)
        list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
                if (i->master == master) {
                        if (del_timer(&i->timeout)) {
-                               unlink_expect(i);
+                               ip_ct_unlink_expect(i);
                                ip_conntrack_expect_put(i);
                        }
                        break;
@@ -1099,7 +1097,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
        /* Get rid of expectations */
        list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
                if (exp->master->helper == me && del_timer(&exp->timeout)) {
-                       unlink_expect(exp);
+                       ip_ct_unlink_expect(exp);
                        ip_conntrack_expect_put(exp);
                }
        }
index 3a2627db1729b81ed9002e086a107e8bd0d50595..1b79ec36085ffed8896fdd9882126b24400fd57c 100644 (file)
@@ -421,6 +421,7 @@ static int help(struct sk_buff **pskb,
                  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
 
        exp->expectfn = NULL;
+       exp->flags = 0;
 
        /* Now, NAT might want to mangle the packet, and register the
         * (possibly changed) expectation itself. */
index 25438eec21a11008c48d607f1c375f34c8ed81f9..d7a8a98c05e1982a9b4b13839ac169a44d00deea 100644 (file)
@@ -221,6 +221,7 @@ static int help(struct sk_buff **pskb,
                                { { 0, { 0 } },
                                  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
                        exp->expectfn = NULL;
+                       exp->flags = 0;
                        if (ip_nat_irc_hook)
                                ret = ip_nat_irc_hook(pskb, ctinfo, 
                                                      addr_beg_p - ib_ptr,
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
new file mode 100644 (file)
index 0000000..2b5cf9c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *      NetBIOS name service broadcast connection tracking helper
+ *
+ *      (c) 2005 Patrick McHardy <kaber@trash.net>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+/*
+ *      This helper tracks locally originating NetBIOS name service
+ *      requests by issuing permanent expectations (valid until
+ *      timing out) matching all reply connections from the
+ *      destination network. The only NetBIOS specific thing is
+ *      actually the port number.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/route.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
+MODULE_LICENSE("GPL");
+
+static unsigned int timeout = 3;
+module_param(timeout, int, 0600);
+MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
+
+static int help(struct sk_buff **pskb,
+                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+       struct ip_conntrack_expect *exp;
+       struct iphdr *iph = (*pskb)->nh.iph;
+       struct udphdr _uh, *uh;
+       struct rtable *rt = (struct rtable *)(*pskb)->dst;
+       struct in_device *in_dev;
+       u_int32_t mask = 0;
+
+       /* we're only interested in locally generated packets */
+       if ((*pskb)->sk == NULL)
+               goto out;
+       if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
+               goto out;
+       if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+               goto out;
+
+       rcu_read_lock();
+       in_dev = __in_dev_get(rt->u.dst.dev);
+       if (in_dev != NULL) {
+               for_primary_ifa(in_dev) {
+                       if (ifa->ifa_broadcast == iph->daddr) {
+                               mask = ifa->ifa_mask;
+                               break;
+                       }
+               } endfor_ifa(in_dev);
+       }
+       rcu_read_unlock();
+
+       if (mask == 0)
+               goto out;
+
+       uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh);
+       BUG_ON(uh == NULL);
+
+       exp = ip_conntrack_expect_alloc(ct);
+       if (exp == NULL)
+               goto out;
+       memset(&exp->tuple, 0, sizeof(exp->tuple));
+       exp->tuple.src.ip         = iph->daddr & mask;
+       exp->tuple.dst.ip         = iph->saddr;
+       exp->tuple.dst.u.udp.port = uh->source;
+       exp->tuple.dst.protonum   = IPPROTO_UDP;
+
+       memset(&exp->mask, 0, sizeof(exp->mask));
+       exp->mask.src.ip          = mask;
+       exp->mask.dst.ip          = 0xFFFFFFFF;
+       exp->mask.dst.u.udp.port  = 0xFFFF;
+       exp->mask.dst.protonum    = 0xFF;
+
+       exp->expectfn             = NULL;
+       exp->flags                = IP_CT_EXPECT_PERMANENT;
+
+       ip_conntrack_expect_related(exp);
+       ip_conntrack_expect_put(exp);
+
+       ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ);
+out:
+       return NF_ACCEPT;
+}
+
+static struct ip_conntrack_helper helper = {
+       .name                   = "netbios-ns",
+       .tuple = {
+               .src.u.udp.port = __constant_htons(137),
+               .dst.protonum   = IPPROTO_UDP,
+       },
+       .mask = {
+               .src.u.udp.port = 0xFFFF,
+               .dst.protonum   = 0xFF,
+       },
+       .max_expected           = 1,
+       .me                     = THIS_MODULE,
+       .help                   = help,
+};
+
+static int __init init(void)
+{
+       helper.timeout = timeout;
+       return ip_conntrack_helper_register(&helper);
+}
+
+static void __exit fini(void)
+{
+       ip_conntrack_helper_unregister(&helper);
+}
+
+module_init(init);
+module_exit(fini);
index a4e9278db4eda7d2050e95a2344e504c34b8f396..15aef356474264926ef3449a69751897e51ae8ce 100644 (file)
@@ -1349,8 +1349,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
                list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
                                         list) {
                        if (exp->master->helper == h 
-                           && del_timer(&exp->timeout))
-                               __ip_ct_expect_unlink_destroy(exp);
+                           && del_timer(&exp->timeout)) {
+                               ip_ct_unlink_expect(exp);
+                               ip_conntrack_expect_put(exp);
+                       }
                }
                write_unlock(&ip_conntrack_lock);
        } else {
@@ -1358,8 +1360,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
                write_lock_bh(&ip_conntrack_lock);
                list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
                                         list) {
-                       if (del_timer(&exp->timeout))
-                               __ip_ct_expect_unlink_destroy(exp);
+                       if (del_timer(&exp->timeout)) {
+                               ip_ct_unlink_expect(exp);
+                               ip_conntrack_expect_put(exp);
+                       }
                }
                write_unlock_bh(&ip_conntrack_lock);
        }
@@ -1413,6 +1417,7 @@ ctnetlink_create_expect(struct nfattr *cda[])
        }
        
        exp->expectfn = NULL;
+       exp->flags = 0;
        exp->master = ct;
        memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple));
        memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple));
index f23ef1f88c46b40701f956b74f49f3c9d7ef9ceb..1985abc59d2497f13c453750277d71da0bf73946 100644 (file)
@@ -349,6 +349,7 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
        return 0;
 
 nfattr_failure:
+       read_unlock_bh(&tcp_lock);
        return -1;
 }
 #endif
index ee5895afd0c3e8a0bfb932c56bc623f16de0cd05..ae3e3e655db555054c14dd34372e792abb2e25e5 100644 (file)
@@ -998,7 +998,7 @@ EXPORT_SYMBOL(ip_conntrack_expect_related);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
 EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
-EXPORT_SYMBOL_GPL(__ip_ct_expect_unlink_destroy);
+EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
 
 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
 EXPORT_SYMBOL(ip_ct_gather_frags);
index f8ff170f390a3ad8bd8e5f0100658d7d1908008f..d2b590533452e201d48c8b1bc172a0661828b917 100644 (file)
@@ -75,6 +75,7 @@ static int tftp_help(struct sk_buff **pskb,
                exp->mask.dst.u.udp.port = 0xffff;
                exp->mask.dst.protonum = 0xff;
                exp->expectfn = NULL;
+               exp->flags = 0;
 
                DEBUGP("expect: ");
                DUMP_TUPLE(&exp->tuple);
index 60d70fa41a156a63bd4abb9a04a894297a8fa0d7..cb66b8bddeb3d63eb2ef23ee359a2491c6511c63 100644 (file)
@@ -255,6 +255,27 @@ alloc_null_binding(struct ip_conntrack *conntrack,
        return ip_nat_setup_info(conntrack, &range, hooknum);
 }
 
+unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+                             struct ip_nat_info *info,
+                             unsigned int hooknum)
+{
+       u_int32_t ip
+               = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+                  ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
+                  : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
+       u_int16_t all
+               = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+                  ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+                  : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+       struct ip_nat_range range
+               = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
+
+       DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+              conntrack, NIPQUAD(ip));
+       return ip_nat_setup_info(conntrack, &range, hooknum);
+}
+
 int ip_nat_rule_find(struct sk_buff **pskb,
                     unsigned int hooknum,
                     const struct net_device *in,
index 89db052add81e4a61def654f00cc4bcc9d92f889..0ff368b131f6bac3bfd27e8201b519ce700b64bd 100644 (file)
@@ -123,8 +123,12 @@ ip_nat_fn(unsigned int hooknum,
                if (!ip_nat_initialized(ct, maniptype)) {
                        unsigned int ret;
 
-                       /* LOCAL_IN hook doesn't have a chain!  */
-                       if (hooknum == NF_IP_LOCAL_IN)
+                       if (unlikely(is_confirmed(ct)))
+                               /* NAT module was loaded late */
+                               ret = alloc_null_binding_confirmed(ct, info,
+                                                                  hooknum);
+                       else if (hooknum == NF_IP_LOCAL_IN)
+                               /* LOCAL_IN hook doesn't have a chain!  */
                                ret = alloc_null_binding(ct, info, hooknum);
                        else
                                ret = ip_nat_rule_find(pskb, hooknum,
index 249bddb28acd9057bccac1b89960ecc8994041b3..f81fe8c52e99ba2d3d90762cecc9ac4194fbf956 100644 (file)
@@ -371,6 +371,12 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
                break;
        
        case NFQNL_COPY_PACKET:
+               if (entry->skb->ip_summed == CHECKSUM_HW &&
+                   (*errp = skb_checksum_help(entry->skb,
+                                              entry->info->outdev == NULL))) {
+                       spin_unlock_bh(&queue->lock);
+                       return NULL;
+               }
                if (queue->copy_range == 0 
                    || queue->copy_range > entry->skb->len)
                        data_len = entry->skb->len;
@@ -636,7 +642,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
        if (!skb_make_writable(&e->skb, data_len))
                return -ENOMEM;
        memcpy(e->skb->data, data, data_len);
-
+       e->skb->ip_summed = CHECKSUM_NONE;
        return 0;
 }
 
index 62435ffc61846396e6a862dd9907319a1a3b8688..a64e1d5ce3ca8f38ae3cb76c41d62d4bd0a8d136 100644 (file)
@@ -398,24 +398,13 @@ static int netlink_create(struct socket *sock, int protocol)
        if (nl_table[protocol].registered &&
            try_module_get(nl_table[protocol].module))
                module = nl_table[protocol].module;
-       else
-               err = -EPROTONOSUPPORT;
        groups = nl_table[protocol].groups;
        netlink_unlock_table();
 
-       if (err || (err = __netlink_create(sock, protocol) < 0))
+       if ((err = __netlink_create(sock, protocol) < 0))
                goto out_module;
 
        nlk = nlk_sk(sock->sk);
-
-       nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
-       if (nlk->groups == NULL) {
-               err = -ENOMEM;
-               goto out_module;
-       }
-       memset(nlk->groups, 0, NLGRPSZ(groups));
-       nlk->ngroups = groups;
-
        nlk->module = module;
 out:
        return err;
@@ -534,6 +523,29 @@ netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
        nlk->subscriptions = subscriptions;
 }
 
+static int netlink_alloc_groups(struct sock *sk)
+{
+       struct netlink_sock *nlk = nlk_sk(sk);
+       unsigned int groups;
+       int err = 0;
+
+       netlink_lock_table();
+       groups = nl_table[sk->sk_protocol].groups;
+       if (!nl_table[sk->sk_protocol].registered)
+               err = -ENOENT;
+       netlink_unlock_table();
+
+       if (err)
+               return err;
+
+       nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
+       if (nlk->groups == NULL)
+               return -ENOMEM;
+       memset(nlk->groups, 0, NLGRPSZ(groups));
+       nlk->ngroups = groups;
+       return 0;
+}
+
 static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 {
        struct sock *sk = sock->sk;
@@ -545,8 +557,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
                return -EINVAL;
 
        /* Only superuser is allowed to listen multicasts */
-       if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_RECV))
-               return -EPERM;
+       if (nladdr->nl_groups) {
+               if (!netlink_capable(sock, NL_NONROOT_RECV))
+                       return -EPERM;
+               if (nlk->groups == NULL) {
+                       err = netlink_alloc_groups(sk);
+                       if (err)
+                               return err;
+               }
+       }
 
        if (nlk->pid) {
                if (nladdr->nl_pid != nlk->pid)
@@ -559,7 +578,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
                        return err;
        }
 
-       if (!nladdr->nl_groups && !(u32)nlk->groups[0])
+       if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
                return 0;
 
        netlink_table_grab();
@@ -620,7 +639,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr
                nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
        } else {
                nladdr->nl_pid = nlk->pid;
-               nladdr->nl_groups = nlk->groups[0];
+               nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
        }
        return 0;
 }
@@ -976,6 +995,11 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
 
                if (!netlink_capable(sock, NL_NONROOT_RECV))
                        return -EPERM;
+               if (nlk->groups == NULL) {
+                       err = netlink_alloc_groups(sk);
+                       if (err)
+                               return err;
+               }
                if (!val || val - 1 >= nlk->ngroups)
                        return -EINVAL;
                netlink_table_grab();
@@ -1483,8 +1507,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
                           s,
                           s->sk_protocol,
                           nlk->pid,
-                          nlk->flags & NETLINK_KERNEL_SOCKET ?
-                               0 : (unsigned int)nlk->groups[0],
+                          nlk->groups ? (u32)nlk->groups[0] : 0,
                           atomic_read(&s->sk_rmem_alloc),
                           atomic_read(&s->sk_wmem_alloc),
                           nlk->cb,
index 4b53de982114d242706ba632960781190641c85a..f4578c759ffcc3350ebbd708c7f0a2ffef52c587 100644 (file)
@@ -1261,6 +1261,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
        struct net_device *dev;
        struct nr_sock *nr;
        const char *devname;
+       char buf[11];
 
        if (v == SEQ_START_TOKEN)
                seq_puts(seq,
@@ -1276,11 +1277,11 @@ static int nr_info_show(struct seq_file *seq, void *v)
                else
                        devname = dev->name;
 
-               seq_printf(seq, "%-9s ", ax2asc(&nr->user_addr));
-               seq_printf(seq, "%-9s ", ax2asc(&nr->dest_addr));
+               seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));
+               seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));
                seq_printf(seq, 
 "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n",
-                       ax2asc(&nr->source_addr),
+                       ax2asc(buf, &nr->source_addr),
                        devname,
                        nr->my_index,
                        nr->my_id,
index 7a86b36cba505d6547a0a63620e5105858c9955d..b3b9097c87c7df5ae3c9af4a8d5b7115c34a9d10 100644 (file)
@@ -881,6 +881,7 @@ static void nr_node_stop(struct seq_file *seq, void *v)
 
 static int nr_node_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
        int i;
 
        if (v == SEQ_START_TOKEN)
@@ -890,7 +891,7 @@ static int nr_node_show(struct seq_file *seq, void *v)
                struct nr_node *nr_node = v;
                nr_node_lock(nr_node);
                seq_printf(seq, "%-9s %-7s  %d %d",
-                       ax2asc(&nr_node->callsign),
+                       ax2asc(buf, &nr_node->callsign),
                        (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
                        nr_node->which + 1,
                        nr_node->count);
@@ -964,6 +965,7 @@ static void nr_neigh_stop(struct seq_file *seq, void *v)
 
 static int nr_neigh_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
        int i;
 
        if (v == SEQ_START_TOKEN)
@@ -973,7 +975,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
 
                seq_printf(seq, "%05d %-9s %-4s  %3d    %d   %3d    %3d",
                        nr_neigh->number,
-                       ax2asc(&nr_neigh->callsign),
+                       ax2asc(buf, &nr_neigh->callsign),
                        nr_neigh->dev ? nr_neigh->dev->name : "???",
                        nr_neigh->quality,
                        nr_neigh->locked,
@@ -983,7 +985,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
                if (nr_neigh->digipeat != NULL) {
                        for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
                                seq_printf(seq, " %s", 
-                                          ax2asc(&nr_neigh->digipeat->calls[i]));
+                                          ax2asc(buf, &nr_neigh->digipeat->calls[i]));
                }
 
                seq_puts(seq, "\n");
index ba997095f08f7ba3c670e0de052a694d39da6a11..8690f171c1ef28136e7e57e160e980955d6b742d 100644 (file)
@@ -1535,8 +1535,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
 static void packet_mm_open(struct vm_area_struct *vma)
 {
        struct file *file = vma->vm_file;
-       struct inode *inode = file->f_dentry->d_inode;
-       struct socket * sock = SOCKET_I(inode);
+       struct socket * sock = file->private_data;
        struct sock *sk = sock->sk;
        
        if (sk)
@@ -1546,8 +1545,7 @@ static void packet_mm_open(struct vm_area_struct *vma)
 static void packet_mm_close(struct vm_area_struct *vma)
 {
        struct file *file = vma->vm_file;
-       struct inode *inode = file->f_dentry->d_inode;
-       struct socket * sock = SOCKET_I(inode);
+       struct socket * sock = file->private_data;
        struct sock *sk = sock->sk;
        
        if (sk)
index c6e59f84c3ae78594dca71aa480a724cae9a00d0..3077878ed4f09fdc1a9a1bcf0b1303084f098641 100644 (file)
@@ -1363,6 +1363,8 @@ static void rose_info_stop(struct seq_file *seq, void *v)
 
 static int rose_info_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
+
        if (v == SEQ_START_TOKEN)
                seq_puts(seq, 
                         "dest_addr  dest_call src_addr   src_call  dev   lci neigh st vs vr va   t  t1  t2  t3  hb    idle Snd-Q Rcv-Q inode\n");
@@ -1380,12 +1382,12 @@ static int rose_info_show(struct seq_file *seq, void *v)
                
                seq_printf(seq, "%-10s %-9s ",
                        rose2asc(&rose->dest_addr),
-                       ax2asc(&rose->dest_call));
+                       ax2asc(buf, &rose->dest_call));
 
                if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
                        callsign = "??????-?";
                else
-                       callsign = ax2asc(&rose->source_call);
+                       callsign = ax2asc(buf, &rose->source_call);
 
                seq_printf(seq,
                           "%-10s %-9s %-5s %3.3X %05d  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
index 4510cd7613ecd851259bd4d6b43dc7637fd54ebf..e556d92c0bc4d2eb5883acda48b051a608a10d9f 100644 (file)
@@ -851,6 +851,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        unsigned char cause, diagnostic;
        struct net_device *dev;
        int len, res = 0;
+       char buf[11];
 
 #if 0
        if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
@@ -876,7 +877,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
        if (rose_neigh == NULL) {
                printk("rose_route : unknown neighbour or device %s\n",
-                      ax2asc(&ax25->dest_addr));
+                      ax2asc(buf, &ax25->dest_addr));
                goto out;
        }
 
@@ -1178,6 +1179,7 @@ static void rose_neigh_stop(struct seq_file *seq, void *v)
 
 static int rose_neigh_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
        int i;
 
        if (v == SEQ_START_TOKEN)
@@ -1189,7 +1191,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
                /* if (!rose_neigh->loopback) { */
                seq_printf(seq, "%05d %-9s %-4s   %3d %3d  %3s     %3s %3lu %3lu",
                           rose_neigh->number,
-                          (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign),
+                          (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),
                           rose_neigh->dev ? rose_neigh->dev->name : "???",
                           rose_neigh->count,
                           rose_neigh->use,
@@ -1200,7 +1202,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
 
                if (rose_neigh->digipeat != NULL) {
                        for (i = 0; i < rose_neigh->digipeat->ndigi; i++)
-                               seq_printf(seq, " %s", ax2asc(&rose_neigh->digipeat->calls[i]));
+                               seq_printf(seq, " %s", ax2asc(buf, &rose_neigh->digipeat->calls[i]));
                }
 
                seq_puts(seq, "\n");
@@ -1260,6 +1262,8 @@ static void rose_route_stop(struct seq_file *seq, void *v)
 
 static int rose_route_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
+
        if (v == SEQ_START_TOKEN)
                seq_puts(seq, 
                         "lci  address     callsign   neigh  <-> lci  address     callsign   neigh\n");
@@ -1271,7 +1275,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
                                   "%3.3X  %-10s  %-9s  %05d      ",
                                   rose_route->lci1,
                                   rose2asc(&rose_route->src_addr),
-                                  ax2asc(&rose_route->src_call),
+                                  ax2asc(buf, &rose_route->src_call),
                                   rose_route->neigh1->number);
                else 
                        seq_puts(seq, 
@@ -1282,7 +1286,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
                                   "%3.3X  %-10s  %-9s  %05d\n",
                                rose_route->lci2,
                                rose2asc(&rose_route->dest_addr),
-                               ax2asc(&rose_route->dest_call),
+                               ax2asc(buf, &rose_route->dest_call),
                                rose_route->neigh2->number);
                 else 
                         seq_puts(seq,
index a29a3a960fd657efa21c50a13b3936f5ce28e7bb..02891ce2db37b3ee52c118f9fcb4ca876ccc18ff 100644 (file)
@@ -400,6 +400,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
 {
        unsigned char *p = buffer + 1;
        char *callsign;
+       char buf[11];
        int len, nb;
 
        /* National Facilities */
@@ -456,7 +457,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
 
        *p++ = FAC_CCITT_DEST_NSAP;
 
-       callsign = ax2asc(&rose->dest_call);
+       callsign = ax2asc(buf, &rose->dest_call);
 
        *p++ = strlen(callsign) + 10;
        *p++ = (strlen(callsign) + 9) * 2;              /* ??? */
@@ -471,7 +472,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
 
        *p++ = FAC_CCITT_SRC_NSAP;
 
-       callsign = ax2asc(&rose->source_call);
+       callsign = ax2asc(buf, &rose->source_call);
 
        *p++ = strlen(callsign) + 10;
        *p++ = (strlen(callsign) + 9) * 2;              /* ??? */
index 94fe638b4d72b3721cbda637573c7182f5535b32..e1bd5d84d7bf11acce8a2c6b73d0f5ac41809d05 100644 (file)
@@ -667,7 +667,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
        }
        iocb->private = x;
        x->kiocb = iocb;
-       sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode)
+       sock = iocb->ki_filp->private_data
 
        x->async_msg.msg_name = NULL;
        x->async_msg.msg_namelen = 0;
@@ -709,7 +709,7 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
        }
        iocb->private = x;
        x->kiocb = iocb;
-       sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode)
+       sock = iocb->ki_filp->private_data
 
        x->async_msg.msg_name = NULL;
        x->async_msg.msg_namelen = 0;
@@ -732,7 +732,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
        struct socket *sock;
        int flags;
 
-       sock = SOCKET_I(file->f_dentry->d_inode);
+       sock = file->private_data;
 
        flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
        if (more)
@@ -741,14 +741,14 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
        return sock->ops->sendpage(sock, page, offset, size, flags);
 }
 
-static int sock_readv_writev(int type, struct inode * inode,
+static int sock_readv_writev(int type,
                             struct file * file, const struct iovec * iov,
                             long count, size_t size)
 {
        struct msghdr msg;
        struct socket *sock;
 
-       sock = SOCKET_I(inode);
+       sock = file->private_data;
 
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
@@ -775,7 +775,7 @@ static ssize_t sock_readv(struct file *file, const struct iovec *vector,
        int i;
         for (i = 0 ; i < count ; i++)
                 tot_len += vector[i].iov_len;
-       return sock_readv_writev(VERIFY_WRITE, file->f_dentry->d_inode,
+       return sock_readv_writev(VERIFY_WRITE,
                                 file, vector, count, tot_len);
 }
        
@@ -786,7 +786,7 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
        int i;
         for (i = 0 ; i < count ; i++)
                 tot_len += vector[i].iov_len;
-       return sock_readv_writev(VERIFY_READ, file->f_dentry->d_inode,
+       return sock_readv_writev(VERIFY_READ,
                                 file, vector, count, tot_len);
 }
 
@@ -840,7 +840,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        void __user *argp = (void __user *)arg;
        int pid, err;
 
-       sock = SOCKET_I(file->f_dentry->d_inode);
+       sock = file->private_data;
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                err = dev_ioctl(cmd, argp);
        } else
@@ -939,13 +939,13 @@ static unsigned int sock_poll(struct file *file, poll_table * wait)
        /*
         *      We can't return errors to poll, so it's either yes or no. 
         */
-       sock = SOCKET_I(file->f_dentry->d_inode);
+       sock = file->private_data;
        return sock->ops->poll(file, sock, wait);
 }
 
 static int sock_mmap(struct file * file, struct vm_area_struct * vma)
 {
-       struct socket *sock = SOCKET_I(file->f_dentry->d_inode);
+       struct socket *sock = file->private_data;
 
        return sock->ops->mmap(file, sock, vma);
 }
@@ -995,7 +995,7 @@ static int sock_fasync(int fd, struct file *filp, int on)
                        return -ENOMEM;
        }
 
-       sock = SOCKET_I(filp->f_dentry->d_inode);
+       sock = filp->private_data;
 
        if ((sk=sock->sk) == NULL) {
                kfree(fna);
index 5c8fe3bfc49415195058c8b6c939767d619478bb..e3308195374e635b2ea617d64fc48684c24d1241 100644 (file)
@@ -250,6 +250,7 @@ out:
 }
 
 static struct cache_detail rsi_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = RSI_HASHMAX,
        .hash_table     = rsi_table,
        .name           = "auth.rpcsec.init",
@@ -436,6 +437,7 @@ out:
 }
 
 static struct cache_detail rsc_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = RSC_HASHMAX,
        .hash_table     = rsc_table,
        .name           = "auth.rpcsec.context",
@@ -1074,7 +1076,9 @@ gss_svc_init(void)
 void
 gss_svc_shutdown(void)
 {
-       cache_unregister(&rsc_cache);
-       cache_unregister(&rsi_cache);
+       if (cache_unregister(&rsc_cache))
+               printk(KERN_ERR "auth_rpcgss: failed to unregister rsc cache\n");
+       if (cache_unregister(&rsi_cache))
+               printk(KERN_ERR "auth_rpcgss: failed to unregister rsi cache\n");
        svc_auth_unregister(RPC_AUTH_GSS);
 }
index 900f5bc7e3366480426f0674ec4a2ca5c2113f7d..f509e99927675e173f251f44637f976489a0abf1 100644 (file)
@@ -177,7 +177,7 @@ void cache_register(struct cache_detail *cd)
        cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
        if (cd->proc_ent) {
                struct proc_dir_entry *p;
-               cd->proc_ent->owner = THIS_MODULE;
+               cd->proc_ent->owner = cd->owner;
                cd->channel_ent = cd->content_ent = NULL;
                
                p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
@@ -185,7 +185,7 @@ void cache_register(struct cache_detail *cd)
                cd->flush_ent =  p;
                if (p) {
                        p->proc_fops = &cache_flush_operations;
-                       p->owner = THIS_MODULE;
+                       p->owner = cd->owner;
                        p->data = cd;
                }
  
@@ -195,7 +195,7 @@ void cache_register(struct cache_detail *cd)
                        cd->channel_ent = p;
                        if (p) {
                                p->proc_fops = &cache_file_operations;
-                               p->owner = THIS_MODULE;
+                               p->owner = cd->owner;
                                p->data = cd;
                        }
                }
@@ -205,7 +205,7 @@ void cache_register(struct cache_detail *cd)
                        cd->content_ent = p;
                        if (p) {
                                p->proc_fops = &content_file_operations;
-                               p->owner = THIS_MODULE;
+                               p->owner = cd->owner;
                                p->data = cd;
                        }
                }
index 9b67dc19944c0d0c7d40e96852b19359fae5c181..4979f226e285f57117cc8daa71667f64549b0b7a 100644 (file)
@@ -35,13 +35,13 @@ static int rpc_proc_show(struct seq_file *seq, void *v) {
        int             i, j;
 
        seq_printf(seq,
-               "net %d %d %d %d\n",
+               "net %u %u %u %u\n",
                        statp->netcnt,
                        statp->netudpcnt,
                        statp->nettcpcnt,
                        statp->nettcpconn);
        seq_printf(seq,
-               "rpc %d %d %d\n",
+               "rpc %u %u %u\n",
                        statp->rpccnt,
                        statp->rpcretrans,
                        statp->rpcauthrefresh);
@@ -50,10 +50,10 @@ static int rpc_proc_show(struct seq_file *seq, void *v) {
                const struct rpc_version *vers = prog->version[i];
                if (!vers)
                        continue;
-               seq_printf(seq, "proc%d %d",
+               seq_printf(seq, "proc%u %u",
                                        vers->number, vers->nrprocs);
                for (j = 0; j < vers->nrprocs; j++)
-                       seq_printf(seq, " %d",
+                       seq_printf(seq, " %u",
                                        vers->procs[j].p_count);
                seq_putc(seq, '\n');
        }
@@ -83,13 +83,13 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
        int             i, j;
 
        seq_printf(seq,
-               "net %d %d %d %d\n",
+               "net %u %u %u %u\n",
                        statp->netcnt,
                        statp->netudpcnt,
                        statp->nettcpcnt,
                        statp->nettcpconn);
        seq_printf(seq,
-               "rpc %d %d %d %d %d\n",
+               "rpc %u %u %u %u %u\n",
                        statp->rpccnt,
                        statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
                        statp->rpcbadfmt,
@@ -99,9 +99,9 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
        for (i = 0; i < prog->pg_nvers; i++) {
                if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
                        continue;
-               seq_printf(seq, "proc%d %d", i, vers->vs_nproc);
+               seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
                for (j = 0; j < vers->vs_nproc; j++, proc++)
-                       seq_printf(seq, " %d", proc->pc_count);
+                       seq_printf(seq, " %u", proc->pc_count);
                seq_putc(seq, '\n');
        }
 }
index 62a0734952766b56ae48e1053dce92f91ecf278c..ed48ff022d3529055c4a508ca86db9379052107d 100644 (file)
@@ -176,8 +176,10 @@ cleanup_sunrpc(void)
 {
        unregister_rpc_pipefs();
        rpc_destroy_mempool();
-       cache_unregister(&auth_domain_cache);
-       cache_unregister(&ip_map_cache);
+       if (cache_unregister(&auth_domain_cache))
+               printk(KERN_ERR "sunrpc: failed to unregister auth_domain cache\n");
+       if (cache_unregister(&ip_map_cache))
+               printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
 #ifdef RPC_DEBUG
        rpc_unregister_sysctl();
 #endif
index bde8147ef2db54dc35ad8dbf77dd43994aae84fa..dda4f0c63511ca74475e9d1259bc73c0db9c47ef 100644 (file)
@@ -143,6 +143,7 @@ static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
 
 
 struct cache_detail auth_domain_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = DN_HASHMAX,
        .hash_table     = auth_domain_table,
        .name           = "auth.domain",
index d6baf6fdf8a97d43f8569d9fef0bc762ebc616b9..cac2e774dd813669d810f464a2263f2c08354a6a 100644 (file)
@@ -242,6 +242,7 @@ static int ip_map_show(struct seq_file *m,
        
 
 struct cache_detail ip_map_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = IP_HASHMAX,
        .hash_table     = ip_table,
        .name           = "auth.unix.ip",
index 9be41a9f5aff77b319f388917fcd384d67361ed7..d591578bd3b209ab8258a814b30727366e8909d8 100644 (file)
  *
  */
 
+#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-/* maximum token length used. It doesn't pay to increase it a lot, because
- * very long substrings probably don't repeat themselves too often. */
-#define MAX_TOK_SIZE           11
 #define KSYM_NAME_LEN          127
 
-/* we use only a subset of the complete symbol table to gather the token count,
- * to speed up compression, at the expense of a little compression ratio */
-#define WORKING_SET            1024
-
-/* first find the best token only on the list of tokens that would profit more
- * than GOOD_BAD_THRESHOLD. Only if this list is empty go to the "bad" list.
- * Increasing this value will put less tokens on the "good" list, so the search
- * is faster. However, if the good list runs out of tokens, we must painfully
- * search the bad list. */
-#define GOOD_BAD_THRESHOLD     10
-
-/* token hash parameters */
-#define HASH_BITS              18
-#define HASH_TABLE_SIZE                (1 << HASH_BITS)
-#define HASH_MASK              (HASH_TABLE_SIZE - 1)
-#define HASH_BASE_OFFSET       2166136261U
-#define HASH_FOLD(a)           ((a)&(HASH_MASK))
-
-/* flags to mark symbols */
-#define SYM_FLAG_VALID         1
-#define SYM_FLAG_SAMPLED       2
 
 struct sym_entry {
        unsigned long long addr;
-       char type;
-       unsigned char flags;
-       unsigned char len;
+       unsigned int len;
        unsigned char *sym;
 };
 
 
 static struct sym_entry *table;
-static int size, cnt;
+static unsigned int table_size, table_cnt;
 static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
 static int all_symbols = 0;
 static char symbol_prefix_char = '\0';
 
-struct token {
-       unsigned char data[MAX_TOK_SIZE];
-       unsigned char len;
-       /* profit: the number of bytes that could be saved by inserting this
-        * token into the table */
-       int profit;
-       struct token *next;     /* next token on the hash list */
-       struct token *right;    /* next token on the good/bad list */
-       struct token *left;    /* previous token on the good/bad list */
-       struct token *smaller; /* token that is less one letter than this one */
-       };
-
-struct token bad_head, good_head;
-struct token *hash_table[HASH_TABLE_SIZE];
+int token_profit[0x10000];
 
 /* the table that holds the result of the compression */
-unsigned char best_table[256][MAX_TOK_SIZE+1];
+unsigned char best_table[256][2];
 unsigned char best_table_len[256];
 
 
-static void
-usage(void)
+static void usage(void)
 {
        fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
        exit(1);
@@ -102,21 +64,19 @@ usage(void)
  * This ignores the intensely annoying "mapping symbols" found
  * in ARM ELF files: $a, $t and $d.
  */
-static inline int
-is_arm_mapping_symbol(const char *str)
+static inline int is_arm_mapping_symbol(const char *str)
 {
        return str[0] == '$' && strchr("atd", str[1])
               && (str[2] == '\0' || str[2] == '.');
 }
 
-static int
-read_symbol(FILE *in, struct sym_entry *s)
+static int read_symbol(FILE *in, struct sym_entry *s)
 {
        char str[500];
-       char *sym;
+       char *sym, stype;
        int rc;
 
-       rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
+       rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
        if (rc != 3) {
                if (rc != EOF) {
                        /* skip line */
@@ -143,7 +103,7 @@ read_symbol(FILE *in, struct sym_entry *s)
                _sextratext = s->addr;
        else if (strcmp(sym, "_eextratext") == 0)
                _eextratext = s->addr;
-       else if (toupper(s->type) == 'A')
+       else if (toupper(stype) == 'A')
        {
                /* Keep these useful absolute symbols */
                if (strcmp(sym, "__kernel_syscall_via_break") &&
@@ -153,22 +113,24 @@ read_symbol(FILE *in, struct sym_entry *s)
                        return -1;
 
        }
-       else if (toupper(s->type) == 'U' ||
+       else if (toupper(stype) == 'U' ||
                 is_arm_mapping_symbol(sym))
                return -1;
+       /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
+       else if (str[0] == '$')
+               return -1;
 
        /* include the type field in the symbol name, so that it gets
         * compressed together */
        s->len = strlen(str) + 1;
-       s->sym = (char *) malloc(s->len + 1);
-       strcpy(s->sym + 1, str);
-       s->sym[0] = s->type;
+       s->sym = malloc(s->len + 1);
+       strcpy((char *)s->sym + 1, str);
+       s->sym[0] = stype;
 
        return 0;
 }
 
-static int
-symbol_valid(struct sym_entry *s)
+static int symbol_valid(struct sym_entry *s)
 {
        /* Symbols which vary between passes.  Passes 1 and 2 must have
         * identical symbol lists.  The kallsyms_* symbols below are only added
@@ -214,30 +176,29 @@ symbol_valid(struct sym_entry *s)
        }
 
        /* Exclude symbols which vary between passes. */
-       if (strstr(s->sym + offset, "_compiled."))
+       if (strstr((char *)s->sym + offset, "_compiled."))
                return 0;
 
        for (i = 0; special_symbols[i]; i++)
-               if( strcmp(s->sym + offset, special_symbols[i]) == 0 )
+               if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
                        return 0;
 
        return 1;
 }
 
-static void
-read_map(FILE *in)
+static void read_map(FILE *in)
 {
        while (!feof(in)) {
-               if (cnt >= size) {
-                       size += 10000;
-                       table = realloc(table, sizeof(*table) * size);
+               if (table_cnt >= table_size) {
+                       table_size += 10000;
+                       table = realloc(table, sizeof(*table) * table_size);
                        if (!table) {
                                fprintf(stderr, "out of memory\n");
                                exit (1);
                        }
                }
-               if (read_symbol(in, &table[cnt]) == 0)
-                       cnt++;
+               if (read_symbol(in, &table[table_cnt]) == 0)
+                       table_cnt++;
        }
 }
 
@@ -281,10 +242,9 @@ static int expand_symbol(unsigned char *data, int len, char *result)
        return total;
 }
 
-static void
-write_src(void)
+static void write_src(void)
 {
-       int i, k, off, valid;
+       unsigned int i, k, off;
        unsigned int best_idx[256];
        unsigned int *markers;
        char buf[KSYM_NAME_LEN+1];
@@ -301,33 +261,24 @@ write_src(void)
        printf(".data\n");
 
        output_label("kallsyms_addresses");
-       valid = 0;
-       for (i = 0; i < cnt; i++) {
-               if (table[i].flags & SYM_FLAG_VALID) {
-                       printf("\tPTR\t%#llx\n", table[i].addr);
-                       valid++;
-               }
+       for (i = 0; i < table_cnt; i++) {
+               printf("\tPTR\t%#llx\n", table[i].addr);
        }
        printf("\n");
 
        output_label("kallsyms_num_syms");
-       printf("\tPTR\t%d\n", valid);
+       printf("\tPTR\t%d\n", table_cnt);
        printf("\n");
 
        /* table of offset markers, that give the offset in the compressed stream
         * every 256 symbols */
-       markers = (unsigned int *) malloc(sizeof(unsigned int)*((valid + 255) / 256));
+       markers = (unsigned int *) malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
 
        output_label("kallsyms_names");
-       valid = 0;
        off = 0;
-       for (i = 0; i < cnt; i++) {
-
-               if (!table[i].flags & SYM_FLAG_VALID)
-                       continue;
-
-               if ((valid & 0xFF) == 0)
-                       markers[valid >> 8] = off;
+       for (i = 0; i < table_cnt; i++) {
+               if ((i & 0xFF) == 0)
+                       markers[i >> 8] = off;
 
                printf("\t.byte 0x%02x", table[i].len);
                for (k = 0; k < table[i].len; k++)
@@ -335,12 +286,11 @@ write_src(void)
                printf("\n");
 
                off += table[i].len + 1;
-               valid++;
        }
        printf("\n");
 
        output_label("kallsyms_markers");
-       for (i = 0; i < ((valid + 255) >> 8); i++)
+       for (i = 0; i < ((table_cnt + 255) >> 8); i++)
                printf("\tPTR\t%d\n", markers[i]);
        printf("\n");
 
@@ -350,7 +300,7 @@ write_src(void)
        off = 0;
        for (i = 0; i < 256; i++) {
                best_idx[i] = off;
-               expand_symbol(best_table[i],best_table_len[i],buf);
+               expand_symbol(best_table[i], best_table_len[i], buf);
                printf("\t.asciz\t\"%s\"\n", buf);
                off += strlen(buf) + 1;
        }
@@ -365,153 +315,13 @@ write_src(void)
 
 /* table lookup compression functions */
 
-static inline unsigned int rehash_token(unsigned int hash, unsigned char data)
-{
-       return ((hash * 16777619) ^ data);
-}
-
-static unsigned int hash_token(unsigned char *data, int len)
-{
-       unsigned int hash=HASH_BASE_OFFSET;
-       int i;
-
-       for (i = 0; i < len; i++)
-               hash = rehash_token(hash, data[i]);
-
-       return HASH_FOLD(hash);
-}
-
-/* find a token given its data and hash value */
-static struct token *find_token_hash(unsigned char *data, int len, unsigned int hash)
-{
-       struct token *ptr;
-
-       ptr = hash_table[hash];
-
-       while (ptr) {
-               if ((ptr->len == len) && (memcmp(ptr->data, data, len) == 0))
-                       return ptr;
-               ptr=ptr->next;
-       }
-
-       return NULL;
-}
-
-static inline void insert_token_in_group(struct token *head, struct token *ptr)
-{
-       ptr->right = head->right;
-       ptr->right->left = ptr;
-       head->right = ptr;
-       ptr->left = head;
-}
-
-static inline void remove_token_from_group(struct token *ptr)
-{
-       ptr->left->right = ptr->right;
-       ptr->right->left = ptr->left;
-}
-
-
-/* build the counts for all the tokens that start with "data", and have lenghts
- * from 2 to "len" */
-static void learn_token(unsigned char *data, int len)
-{
-       struct token *ptr,*last_ptr;
-       int i, newprofit;
-       unsigned int hash = HASH_BASE_OFFSET;
-       unsigned int hashes[MAX_TOK_SIZE + 1];
-
-       if (len > MAX_TOK_SIZE)
-               len = MAX_TOK_SIZE;
-
-       /* calculate and store the hash values for all the sub-tokens */
-       hash = rehash_token(hash, data[0]);
-       for (i = 2; i <= len; i++) {
-               hash = rehash_token(hash, data[i-1]);
-               hashes[i] = HASH_FOLD(hash);
-       }
-
-       last_ptr = NULL;
-       ptr = NULL;
-
-       for (i = len; i >= 2; i--) {
-               hash = hashes[i];
-
-               if (!ptr) ptr = find_token_hash(data, i, hash);
-
-               if (!ptr) {
-                       /* create a new token entry */
-                       ptr = (struct token *) malloc(sizeof(*ptr));
-
-                       memcpy(ptr->data, data, i);
-                       ptr->len = i;
-
-                       /* when we create an entry, it's profit is 0 because
-                        * we also take into account the size of the token on
-                        * the compressed table. We then subtract GOOD_BAD_THRESHOLD
-                        * so that the test to see if this token belongs to
-                        * the good or bad list, is a comparison to zero */
-                       ptr->profit = -GOOD_BAD_THRESHOLD;
-
-                       ptr->next = hash_table[hash];
-                       hash_table[hash] = ptr;
-
-                       insert_token_in_group(&bad_head, ptr);
-
-                       ptr->smaller = NULL;
-               } else {
-                       newprofit = ptr->profit + (ptr->len - 1);
-                       /* check to see if this token needs to be moved to a
-                        * different list */
-                       if((ptr->profit < 0) && (newprofit >= 0)) {
-                               remove_token_from_group(ptr);
-                               insert_token_in_group(&good_head,ptr);
-                       }
-                       ptr->profit = newprofit;
-               }
-
-               if (last_ptr) last_ptr->smaller = ptr;
-               last_ptr = ptr;
-
-               ptr = ptr->smaller;
-       }
-}
-
-/* decrease the counts for all the tokens that start with "data", and have lenghts
- * from 2 to "len". This function is much simpler than learn_token because we have
- * more guarantees (tho tokens exist, the ->smaller pointer is set, etc.)
- * The two separate functions exist only because of compression performance */
-static void forget_token(unsigned char *data, int len)
-{
-       struct token *ptr;
-       int i, newprofit;
-       unsigned int hash=0;
-
-       if (len > MAX_TOK_SIZE) len = MAX_TOK_SIZE;
-
-       hash = hash_token(data, len);
-       ptr = find_token_hash(data, len, hash);
-
-       for (i = len; i >= 2; i--) {
-
-               newprofit = ptr->profit - (ptr->len - 1);
-               if ((ptr->profit >= 0) && (newprofit < 0)) {
-                       remove_token_from_group(ptr);
-                       insert_token_in_group(&bad_head, ptr);
-               }
-               ptr->profit=newprofit;
-
-               ptr=ptr->smaller;
-       }
-}
-
 /* count all the possible tokens in a symbol */
 static void learn_symbol(unsigned char *symbol, int len)
 {
        int i;
 
        for (i = 0; i < len - 1; i++)
-               learn_token(symbol + i, len - i);
+               token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
 }
 
 /* decrease the count for all the possible tokens in a symbol */
@@ -520,117 +330,90 @@ static void forget_symbol(unsigned char *symbol, int len)
        int i;
 
        for (i = 0; i < len - 1; i++)
-               forget_token(symbol + i, len - i);
+               token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
 }
 
-/* set all the symbol flags and do the initial token count */
+/* remove all the invalid symbols from the table and do the initial token count */
 static void build_initial_tok_table(void)
 {
-       int i, use_it, valid;
+       unsigned int i, pos;
 
-       valid = 0;
-       for (i = 0; i < cnt; i++) {
-               table[i].flags = 0;
+       pos = 0;
+       for (i = 0; i < table_cnt; i++) {
                if ( symbol_valid(&table[i]) ) {
-                       table[i].flags |= SYM_FLAG_VALID;
-                       valid++;
+                       if (pos != i)
+                               table[pos] = table[i];
+                       learn_symbol(table[pos].sym, table[pos].len);
+                       pos++;
                }
        }
-
-       use_it = 0;
-       for (i = 0; i < cnt; i++) {
-
-               /* subsample the available symbols. This method is almost like
-                * a Bresenham's algorithm to get uniformly distributed samples
-                * across the symbol table */
-               if (table[i].flags & SYM_FLAG_VALID) {
-
-                       use_it += WORKING_SET;
-
-                       if (use_it >= valid) {
-                               table[i].flags |= SYM_FLAG_SAMPLED;
-                               use_it -= valid;
-                       }
-               }
-               if (table[i].flags & SYM_FLAG_SAMPLED)
-                       learn_symbol(table[i].sym, table[i].len);
-       }
+       table_cnt = pos;
 }
 
 /* replace a given token in all the valid symbols. Use the sampled symbols
  * to update the counts */
-static void compress_symbols(unsigned char *str, int tlen, int idx)
+static void compress_symbols(unsigned char *str, int idx)
 {
-       int i, len, learn, size;
-       unsigned char *p;
+       unsigned int i, len, size;
+       unsigned char *p1, *p2;
 
-       for (i = 0; i < cnt; i++) {
-
-               if (!(table[i].flags & SYM_FLAG_VALID)) continue;
+       for (i = 0; i < table_cnt; i++) {
 
                len = table[i].len;
-               learn = 0;
-               p = table[i].sym;
+               p1 = table[i].sym;
+
+               /* find the token on the symbol */
+               p2 = memmem(p1, len, str, 2);
+               if (!p2) continue;
+
+               /* decrease the counts for this symbol's tokens */
+               forget_symbol(table[i].sym, len);
+
+               size = len;
 
                do {
+                       *p2 = idx;
+                       p2++;
+                       size -= (p2 - p1);
+                       memmove(p2, p2 + 1, size);
+                       p1 = p2;
+                       len--;
+
+                       if (size < 2) break;
+
                        /* find the token on the symbol */
-                       p = (unsigned char *) strstr((char *) p, (char *) str);
-                       if (!p) break;
-
-                       if (!learn) {
-                               /* if this symbol was used to count, decrease it */
-                               if (table[i].flags & SYM_FLAG_SAMPLED)
-                                       forget_symbol(table[i].sym, len);
-                               learn = 1;
-                       }
+                       p2 = memmem(p1, size, str, 2);
 
-                       *p = idx;
-                       size = (len - (p - table[i].sym)) - tlen + 1;
-                       memmove(p + 1, p + tlen, size);
-                       p++;
-                       len -= tlen - 1;
+               } while (p2);
 
-               } while (size >= tlen);
+               table[i].len = len;
 
-               if(learn) {
-                       table[i].len = len;
-                       /* if this symbol was used to count, learn it again */
-                       if(table[i].flags & SYM_FLAG_SAMPLED)
-                               learn_symbol(table[i].sym, len);
-               }
+               /* increase the counts for this symbol's new tokens */
+               learn_symbol(table[i].sym, len);
        }
 }
 
 /* search the token with the maximum profit */
-static struct token *find_best_token(void)
+static int find_best_token(void)
 {
-       struct token *ptr,*best,*head;
-       int bestprofit;
+       int i, best, bestprofit;
 
        bestprofit=-10000;
+       best = 0;
 
-       /* failsafe: if the "good" list is empty search from the "bad" list */
-       if(good_head.right == &good_head) head = &bad_head;
-       else head = &good_head;
-
-       ptr = head->right;
-       best = NULL;
-       while (ptr != head) {
-               if (ptr->profit > bestprofit) {
-                       bestprofit = ptr->profit;
-                       best = ptr;
+       for (i = 0; i < 0x10000; i++) {
+               if (token_profit[i] > bestprofit) {
+                       best = i;
+                       bestprofit = token_profit[i];
                }
-               ptr = ptr->right;
        }
-
        return best;
 }
 
 /* this is the core of the algorithm: calculate the "best" table */
 static void optimize_result(void)
 {
-       struct token *best;
-       int i;
+       int i, best;
 
        /* using the '\0' symbol last allows compress_symbols to use standard
         * fast string functions */
@@ -644,14 +427,12 @@ static void optimize_result(void)
                        best = find_best_token();
 
                        /* place it in the "best" table */
-                       best_table_len[i] = best->len;
-                       memcpy(best_table[i], best->data, best_table_len[i]);
-                       /* zero terminate the token so that we can use strstr
-                          in compress_symbols */
-                       best_table[i][best_table_len[i]]='\0';
+                       best_table_len[i] = 2;
+                       best_table[i][0] = best & 0xFF;
+                       best_table[i][1] = (best >> 8) & 0xFF;
 
                        /* replace this token in all the valid symbols */
-                       compress_symbols(best_table[i], best_table_len[i], i);
+                       compress_symbols(best_table[i], i);
                }
        }
 }
@@ -659,39 +440,28 @@ static void optimize_result(void)
 /* start by placing the symbols that are actually used on the table */
 static void insert_real_symbols_in_table(void)
 {
-       int i, j, c;
+       unsigned int i, j, c;
 
        memset(best_table, 0, sizeof(best_table));
        memset(best_table_len, 0, sizeof(best_table_len));
 
-       for (i = 0; i < cnt; i++) {
-               if (table[i].flags & SYM_FLAG_VALID) {
-                       for (j = 0; j < table[i].len; j++) {
-                               c = table[i].sym[j];
-                               best_table[c][0]=c;
-                               best_table_len[c]=1;
-                       }
+       for (i = 0; i < table_cnt; i++) {
+               for (j = 0; j < table[i].len; j++) {
+                       c = table[i].sym[j];
+                       best_table[c][0]=c;
+                       best_table_len[c]=1;
                }
        }
 }
 
 static void optimize_token_table(void)
 {
-       memset(hash_table, 0, sizeof(hash_table));
-
-       good_head.left = &good_head;
-       good_head.right = &good_head;
-
-       bad_head.left = &bad_head;
-       bad_head.right = &bad_head;
-
        build_initial_tok_table();
 
        insert_real_symbols_in_table();
 
        /* When valid symbol is not registered, exit to error */
-       if (good_head.left == good_head.right &&
-           bad_head.left == bad_head.right) {
+       if (!table_cnt) {
                fprintf(stderr, "No valid symbol.\n");
                exit(1);
        }
@@ -700,8 +470,7 @@ static void optimize_token_table(void)
 }
 
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
        if (argc >= 2) {
                int i;
index a28c279c49dd043b86aa976ce58bd01261d86410..beb43ef7f761fffaaa80393129e554922f92b544 100755 (executable)
@@ -25,9 +25,11 @@ ld -v | awk -F\) '{print $1}' | awk \
 '/BFD/{print "binutils              ",$NF} \
 /^GNU/{print "binutils              ",$4}'
 
-fdformat --version | awk -F\- '{print "util-linux            ", $NF}'
+echo -n "util-linux             "
+fdformat --version | awk '{print $NF}' | sed -e s/^util-linux-// -e s/\)$//
 
-mount --version | awk -F\- '{print "mount                 ", $NF}'
+echo -n "mount                  "
+mount --version | awk '{print $NF}' | sed -e s/^mount-// -e s/\)$//
 
 depmod -V  2>&1 | awk 'NR==1 {print "module-init-tools     ",$NF}'
 
index 103f136926d9bea7d754d9358a99662787764755..4ef6dd00c6eeafb9916378ad7098b642a309a0cc 100644 (file)
@@ -2,12 +2,14 @@
 # Makefile for ALSA
 #
 
-snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
-snd-aaci-objs                  := aaci.o devdma.o
-snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
-snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
-
 obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
+snd-sa11xx-uda1341-objs                := sa11xx-uda1341.o
+
 obj-$(CONFIG_SND_ARMAACI)      += snd-aaci.o
-obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
-obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
+snd-aaci-objs                  := aaci.o devdma.o
+
+obj-$(CONFIG_SND_PXA2XX_PCM)   += snd-pxa2xx-pcm.o
+snd-pxa2xx-pcm-objs            := pxa2xx-pcm.o
+
+obj-$(CONFIG_SND_PXA2XX_AC97)  += snd-pxa2xx-ac97.o
+snd-pxa2xx-ac97-objs           := pxa2xx-ac97.o
index 08cc3ddca96fb385d1a23db07b32ae3a5fe9fc2b..98877030d579fa6f641dee8dca596241940f32e6 100644 (file)
@@ -821,7 +821,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
 
 static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 {
-       void *base = aaci->base + AACI_CSCH1;
+       void __iomem *base = aaci->base + AACI_CSCH1;
        int i;
 
        writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
@@ -877,7 +877,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
        aaci->playback.fifo = aaci->base + AACI_DR1;
 
        for (i = 0; i < 4; i++) {
-               void *base = aaci->base + i * 0x14;
+               void __iomem *base = aaci->base + i * 0x14;
 
                writel(0, base + AACI_IE);
                writel(0, base + AACI_TXCR);
index d752e64268940efe5dba7d192b4953bc8716a048..b2f969bc7845e66b903c48f07e16c21fbc214629 100644 (file)
 
 
 struct aaci_runtime {
-       void                    *base;
-       void                    *fifo;
+       void                    __iomem *base;
+       void                    __iomem *fifo;
 
        struct ac97_pcm         *pcm;
        int                     pcm_open;
@@ -223,7 +223,7 @@ struct aaci_runtime {
 struct aaci {
        struct amba_device      *dev;
        snd_card_t              *card;
-       void                    *base;
+       void                    __iomem *base;
        unsigned int            fifosize;
 
        /* AC'97 */
index 1622893d00a228df4f1f46f17d4af8f875b82c25..291b4769bde38f2bf2775958ce94f200e62f9732 100644 (file)
@@ -116,15 +116,21 @@ void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags)
        return _snd_kmalloc(size, flags);
 }
 
+void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags)
+{
+       void *ret = _snd_kmalloc(size, flags);
+       if (ret)
+               memset(ret, 0, size);
+       return ret;
+}
+EXPORT_SYMBOL(snd_hidden_kzalloc);
+
 void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags)
 {
        void *ret = NULL;
        if (n != 0 && size > INT_MAX / n)
                return ret;
-       ret = _snd_kmalloc(n * size, flags);
-       if (ret)
-               memset(ret, 0, n * size);
-       return ret;
+       return snd_hidden_kzalloc(n * size, flags);
 }
 
 void snd_hidden_kfree(const void *obj)
index be4ea60a367924b0808651f5a542aa0021940804..5c3948311528efdca7817e63e8e3fea96c8b8460 100644 (file)
@@ -15,7 +15,8 @@ config SND_CS4231_LIB
 
 config SND_AD1816A
        tristate "Analog Devices SoundPort AD1816A"
-       depends on SND && ISAPNP
+       depends on SND && PNP && ISA
+       select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -80,7 +81,8 @@ config SND_CS4236
 
 config SND_ES968
        tristate "Generic ESS ES968 driver"
-       depends on SND && ISAPNP
+       depends on SND && PNP && ISA
+       select ISAPNP
        select SND_MPU401_UART
        select SND_PCM
        help
@@ -160,7 +162,7 @@ config SND_GUSMAX
 
 config SND_INTERWAVE
        tristate "AMD InterWave, Gravis UltraSound PnP"
-       depends on SND
+       depends on SND && PNP && ISA
        select SND_RAWMIDI
        select SND_CS4231_LIB
        select SND_GUS_SYNTH
@@ -175,7 +177,7 @@ config SND_INTERWAVE
 
 config SND_INTERWAVE_STB
        tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
-       depends on SND
+       depends on SND && PNP && ISA
        select SND_RAWMIDI
        select SND_CS4231_LIB
        select SND_GUS_SYNTH
@@ -291,7 +293,8 @@ config SND_WAVEFRONT
 
 config SND_ALS100
        tristate "Avance Logic ALS100/ALS120"
-       depends on SND && ISAPNP
+       depends on SND && PNP && ISA
+       select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -304,7 +307,8 @@ config SND_ALS100
 
 config SND_AZT2320
        tristate "Aztech Systems AZT2320"
-       depends on SND && ISAPNP
+       depends on SND && PNP && ISA
+       select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_CS4231_LIB
@@ -328,7 +332,8 @@ config SND_CMI8330
 
 config SND_DT019X
        tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
-       depends on SND && ISAPNP
+       depends on SND && PNP && ISA
+       select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
index d6b96297835ca8b2ab284d4a1920c59848177f15..80dce329cc3a65d8d0a9fcef8793370c415a2687 100644 (file)
@@ -19,9 +19,6 @@
 #include <linux/ioport.h>
 #include <asm/page.h>
 #include <asm/system.h>
-#ifdef __alpha__
-#include <asm/segment.h>
-#endif
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>
index ce6c9fadb5948b57c185dbf44d91e783bb969de0..4943299cf137dce8ab4bcb369ad9813ad0660173 100644 (file)
@@ -2249,7 +2249,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
                return -ENXIO;
        }
 
-       if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL) {
+       if ((codec = kzalloc(sizeof(*codec), GFP_KERNEL)) == NULL) {
                pci_disable_device(pci);
                return -ENOMEM;
        }